【发布时间】:2015-03-12 14:30:41
【问题描述】:
我正在制作一个基于运算符优先级将数学方程构建到树中的程序,例如x^2+5*x+1 变为
/ \
/ \
x^2+5*x + 1
/ \
/ \
x^2 + 5*x
/ \ / \
x ^ x 5 * x
我一直用于树结节的数据结构是
struct node
{
std::string eq;
oper op;
node * LHS;
node * RHS;
};
oper 定义为
enum oper { NONE, ADD, SUB, MULT, DIV, EXP };
我上面画的树的根节点因此可以表示为
{ "x^2+5*x+1", PLUS, ->{ "x^2+5*x", PLUS, ..., ... }, ->{"1", NONE, NULL, NULL} }
如果这有意义的话。
在编写构建这棵树的算法时,我意识到随着这棵树的构建,它的节点具有不同的“状态”,这使得我的代码在尝试处理这些状态时变得混乱和重复。例如,我有一大段代码,就像
if (rootNode == nullptr)
{
rootNode = new node;
rootNode = thisNode;
}
else
{
if (rootNode->RHS == nullptr)
{
rootNode->RHS = thisNode;
}
else
{
if (thisNode->op < rootNode->op)
{
node * temp = rootNode;
rootNode = thisNode;
rootNode->LHS = temp;
}
else
{
rootNode->RHS = thisNode;
}
}
}
以及其他我正在检查指针是否为NULL 并试图确定node 的构建量和yada-yada 的东西。我觉得我应该将我的 node 对象从 structs 更改为 classes 并找出某种使事情变得更清洁的方法,以及节点具有的某种“状态”,相当于“有一个左侧和一个运算符,但还没有右侧”等等。
关于如何利用 C++ 来做到这一点的任何想法?
【问题讨论】:
-
也许这个公认的答案至少可以作为一个起点? stackoverflow.com/questions/17806760/binary-expression-tree-c
-
我会将结构更改为类,使用继承对不同类型的运算符进行建模,并在这些类中封装不同的行为。在构造过程中,我会确保节点在构造函数中获取所有数据并在此之后保持不可变,除非您以后想操作树结构。
-
不是答案,因为我不确定这是否是适合这种情况的正确解决方案,但状态可以由 state pattern 处理
-
这个问题很好但是太宽泛了。我们不知道您想对树执行哪些操作,也不知道树是否应该是可变的。一般来说,继承在这里并不是一个好的解决方案。我的直觉告诉我,你想要一个 STL 风格的数据结构、迭代器和算法分离。
标签: c++ oop design-patterns data-structures tree