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]); 
    } 
}