我正在努力构建一个表达式树头,特别是treenodes的指针,我不知道如何实现并实际创建节点来存储数据,这应该是非常基本的但是代码让我很困惑。
例如,当我想创建一个5 + 5的表达式时,它应该是这样的:
+
/ \
5 5
然而,当实施这个时,我不知道如何开始。如何获取根节点中的运算符和作为子节点的数字?我知道我可以将它们存储在堆栈中并从顶部读取,但是设置的父,左子和右子方法只接受(TreeNode *)参数,而向量标记是类型字符串。
TreeNode的构造函数也采用整数和运算符值,为什么呢?我如何以root,parent和children的形式将这些值放入各自的节点?
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 :(得分:0)
解析表达式的最简单方法是构建递归下降解析器。它由称为表达式,术语和因子的相互递归函数组成。因子是最小单位,可以是基本数字,也可以是括号,表达式,近括号(因此相互递归进入)。术语是乘法和除法运算符的因子集合,表达式是由加号和减号运算符连接的术语集合。
你需要一个特殊规则来减少一元。
现在递归下降解析器实际上并没有将树构建为内存中的结构。树在调用模式中隐含。但是,如果你想要一棵树,你可以很容易地修改它来构建一棵树。
查看我非常简单的Basic解释器
可能会有所帮助答案 1 :(得分:0)
您只需使用TreeNode.h为您提供的内容。
例如,如果你想创建一个名为root的树,代表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等操作可能会对内存泄漏造成危险,并且可以创建循环(这违背了树的想法)。
答案 2 :(得分: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]);
}
}