這次來介紹一下expression tree
當你輸入一個運算式的時候,將其拆解成 運算元(operand) 運算子(operatior)
像這樣:
運算式 1 + 2
運算元(operand) 1 ,2 (共兩個)
運算子(operatior) +
運算式 A * B
運算元(operand) A ,B (共兩個)
運算子(operatior) *
接著把他轉換成用tree來表示
規則:
1. 運算元後面不會有subtree,運算子才會有
2. 運算子的左右subtree 是 運算元 或 其他式子(即其他運算子構成的subtree)
+
/ \
1 2
類似是這樣子,如果要判斷正確與否,只要用infix的方式印出tree
若與輸入的式子是相同的即正確
至於實現這個tree的寫法網路上真的是百百種,我上去看之後自嘆自己實在還是太嫩了
以下是他code的寫法
以上程式碼轉載自:#include <iostream> #include <string> #include <sstream> #include <cassert> using namespace std; typedef struct Node{ // store operator or operand string data; // only valid for operator int precedence; struct Node* parent; struct Node* left; struct Node* right; }CNode, *PNode; PNode CreateNode(const string& x) { PNode p = new CNode; p->parent = p->left = p->right = NULL; p->data = x; return p; } bool IsOperator(const string& x) { // Since the only impact of parentheses () is on precedence, // they are not considered as operators here return ((x.length() == 1) && (x[0] == '*' || x[0] == '/' || x[0] == '+' || x[0] == '-')); } bool IsLeftParenthesis(const string& x) { return x == "("; } bool IsRightParenthesis(const string& x) { return x == ")"; } bool IsOperand(const string& x) { int y; stringstream ss(x); if (ss >> y) return true; else return false; } int GetPrecedence(const string& x) { assert(IsOperator(x)); if (x[0] == '*' || x[0] == '/') return 2; else return 1; } PNode CreateInfixTree(const string& exp) { // create a dummy root with minimal precedence // its content is trivial PNode root = CreateNode("0"); root->precedence = INT_MIN; // the previous operand of current operator PNode preOperand = NULL; // the previous operator of current operator PNode preOperator = root; // the impact of preceding parenthesis, if any int correction = 0; string token; stringstream ss(exp); while (ss >> token) { if (IsOperand(token)) { preOperand = CreateNode(token); } else if (IsOperator(token)) { PNode p = CreateNode(token); p->precedence = GetPrecedence(token) + correction; if (p->precedence > preOperator->precedence) { p->left = preOperand; preOperator->right = p; p->parent = preOperator; } else { preOperator->right = preOperand; PNode q = preOperator->parent; while (p->precedence <= q->precedence) q = q->parent; p->left = q->right; q->right = p; p->parent = q; } preOperand = NULL; preOperator = p; }//else if (IsOperator(token) else if (IsLeftParenthesis(token)) { correction += 2; } else if (IsRightParenthesis(token)) { correction -= 2; } else { cout << "illegal token found: " << token << endl; break; } }//while if (preOperand == NULL) cout << "illegal expression: cannot end with operator: " << preOperator->data << endl; else preOperator->right = preOperand; // delete dummy root PNode realRoot = root->right; delete root; if (realRoot) realRoot->parent = NULL; return realRoot; } void PostOrderPrintTree(PNode node) { if (node) { PostOrderPrintTree(node->left); PostOrderPrintTree(node->right); cout << node->data << " "; } } int main() { // valid operators: + - * / ( ) // valid operands: integers // whitespace separated as: ( 1 + 2 ) * 3 string exp; getline(cin, exp); PNode root = CreateInfixTree(exp); PostOrderPrintTree(root); cout << endl; }
https://stackoverflow.com/questions/6973528/build-a-binary-tree-from-an-infix-expression-without-using-a-stack
沒有留言:
張貼留言