1

我頭痛地嘗試構建一個表達式樹,尤其是treenodes的指針,我不知道如何實現並實際創建存儲應該是數據的節點的線索很基本,但代碼只是讓我困惑。表達式樹實現問題

例如,當我想創建的5 + 5,這是它應該是什麼樣子的表達式:

+ 
/\ 
5 5 

實施這一然而,當,我不知道如何開始。我如何獲得根節點中的運算符和孩子的數字?我知道我可以將它們存儲在一個堆棧中並讀取頂部,但是集合父,左子節點和右子節點方法僅使用(TreeNode *)參數,而矢量標記則是字符串類型。

此外,TreeNode的構造函數需要一個整數和運算符值,爲什麼?我怎樣才能將這些值作爲根,父母和孩子分別存入各自的節點?

ExprTree.cpp 

    #include "ExprTree.h" 
    #include <sstream> 
    #include <iostream> 

    TreeNode * createOperatorNode(const string & op){ 

     if (op == "+") return new TreeNode(Plus); 
     if (op == "-") return new TreeNode(Minus); 
     if (op == "*") return new TreeNode(Times); 
     if (op == "/") return new TreeNode(Divide); 
     return new TreeNode(NoOp); 

    } 

    /* 
    * Basic constructor that sets up an empty Expr Tree. 
    */ 
    ExprTree::ExprTree(){ 

     this->root = NULL; 
     this-> _size = 0; 

    } 

    /* 
    * Constructor that takes a TreeNode and sets up an ExprTree with that node at the root. 
    */ 
    ExprTree::ExprTree(TreeNode * r){ 

     this->root = r; 
    } 

    ExprTree ExprTree::buildTree(vector<string> tokens){ 

// the tokens are the broken up arithimec expression 
i.e 
5 
+ 
5 
// not sure what to do here, i've tried using stacks but i wasn't sure how to get the stored data into the nodes. 

    } 

TreeNode.cpp

#include "TreeNode.h" 

TreeNode::TreeNode(Operator o){ 
    op = o; 
    parent = 0; 
    leftChild = 0; 
    rightChild = 0; 
} 

TreeNode::TreeNode(int val){ 
    op = Value; 
    value = val; 
    parent = 0; 
    leftChild = 0; 
    rightChild = 0; 
} 

TreeNode.h

#include <string> 
#include <sstream> 

enum Operator {Value, Plus, Minus, Times, Divide, NoOp}; 

class TreeNode { 

private: 

    Operator op; //If this node represents an operator, this is where it's stored. 
       //It can take values from the Operator enum (i.e. Plus, Minus, etc.) 
       //If it represents a value, use the Value value. :D 
    int value; //If this node stores an actual number, this is it. 

    TreeNode * parent; //Pointer to the parent. 
    TreeNode * leftChild; //Pointer to the left child of this node. 
    TreeNode * rightChild; //Pointer to the right child of this node. 

public: 

    TreeNode(Operator); //Constructor to use for +, -, * and /. 
         //Example: TreeNode(Plus); 
    TreeNode(int); //Constructor to use for actual numbers. 
       //Example: TreeNode(5); 
    void setParent(TreeNode *); //Set the parent pointer. 
    void setLeftChild(TreeNode *); //Set the left child pointer. 
    void setRightChild(TreeNode *); //Set the right child pointer. 
    TreeNode * getParent(); //Get the parent pointer. 
    TreeNode * getLeftChild(); //Get the left child pointer. 
    TreeNode * getRightChild(); //Get the right child pointer. 
    int getValue(); //Returns the stored value; 
    Operator getOperator(); //Returns the stored operator. 
    bool isValue(); //Returns true if this node is a Value node. 
    bool isOperator(); //Returns truee if this node is Plus, Minus, Times or Divide node. 
    std::string toString(); //Returns a simple string representation of the node. 

}; 
+0

「ExprTree.h」在哪裏? –

回答

0

解析表達式的最簡單的方法是建立一個遞歸下降解析器。這由稱爲表達式,術語和因子的相互遞歸函數組成。一個因素是最小的單位,可以是基本數字,也可以是開括號,表達式,右括號(所以相互遞歸進來)。術語是乘法和除法運算符的集合,表達式是加號和減號運算符加入的術語集合。

您需要一個一元減號的特殊規則。

現在遞歸下降解析器實際上並沒有在內存中構建一棵樹作爲結構。該樹隱含在調用模式中。但是,如果你想要一棵樹,你可以很容易地修改它來構建一棵樹。

這可能有助於看看我最簡單的Basic解釋

https://github.com/MalcolmMcLean/minibasic

0

您只需用什麼TreeNode.h給你。

舉例來說,如果你想創建一個名爲根代表5 + 5一棵樹,你去像

TreeNode root(Plus); 
root.setLeftChild(new TreeNode(5)); 
root.setRightChild(new TreeNode(5)); 

在一個解析器,那麼,嘗試建立一個。請注意,您可以通過關注子項和父指針來輕鬆遍歷樹。

另一種方式是創建了一個字符串構造函數,計算作爲最外層的運營商,然後遞歸構建它的孩子們,給他們相應的子串,像

TreeNode::TreeNode(string expression){ 

    if(expression is number){ 
     create this as number node 
    } 
    create this as operator node with outermost operator 
    split string by outermost operator 
    set left child to left side of split string 
    set right child to ... 
} 

這就是說,作爲一個此言一出,我沒有看到~TreeNode()被定義,這意味着你將有內存泄漏。另外,我建議將Tree和TreeNode分開,即創建一個TreeNode作爲內部類的Tree類,並且TreeNode的構造函數和析構函數是私有的(Tree作爲朋友)。給你更多的控制權。如果錯誤地執行setLeftChild等操作,會對內存泄漏造成危險,並且可以創建循環(這違背了樹的想法)。

0

首先,將您的表達式轉換爲後綴表達式(Infix To Postfix)。

表達:5 + 5

後綴:5 5 +

然後解析後綴串,只要你找到一個操作數推入堆棧,或者如果你發現一個運營商則彈出兩個操作數從堆棧中(如果它是一個二元運算符),然後將樹根作爲操作符左側的&作爲操作數。

Tree *t; 
Stack<string> stack; 

// parsing the tokens(expression)... 
for(int i=0; i<token[i].length(); i++) { 
    if(token[i] == "+" || token[i] == "-" || token[i] == "*" || token[i] == "/") { 
     string op1 = stack.top(); stack.pop(); 
     string op2 = stack.top(); stack.pop(); 
     t->root = new createOperatorNode(token[i]); 
     t->leftChild = new TreeNode(op1); 
     t->rightChild = new TreeNode(op2); 
    } 
    else { 
     stack.push(token[i]); 
    } 
}