我目前正在尝试找出表达式树的算法。我目前将获得的字符串类似于 Hello+12+World
或 A2-12-A3-14
。这些字符串将具有相同的运算符。使用我的算法,目前最后一个操作数没有被放入树中。我在网上看过,但我很难理解如何让它正常工作。
Stack<BaseNode> TreeStack = new Stack<BaseNode>();
BaseNode temp1 = new BaseNode();
BaseNode temp2 = new BaseNode();
for (int i = 0; i < tree.Length; i++)
{
VariableNode varNode = new VariableNode();
NumericalNode numNode = new NumericalNode();
if (CheckExpressions(tree[i])) // if the character is an operator
{
OperatorNode expression = new OperatorNode(tree[i]);
temp1 = TreeStack.Pop();
if (TreeStack.Count != 0)
{
temp2 = TreeStack.Pop();
}
expression.Right = temp1;
expression.Left = temp2;
TreeStack.Push(expression);
}
else if (!CheckExpressions(tree[i]))
{
if (Char.IsLetter(tree[i]))
{
while (Char.IsLetter(tree[i])) // for the variable node
{
varNode.name += tree[i];
if (i + 1 == tree.Length)
{
break;
}
i++;
}
TreeStack.Push(varNode);
if (i + 1 != tree.Length)
{
i--;
}
}
else if (Char.IsDigit(tree[i])) // for constant value
{
int zero = 0; // for appending the numbers to combine them
while (Char.IsDigit(tree[i]))
{
if (zero == 0)
{
zero = tree[i] - '0';
}
else
{
zero = int.Parse(zero.ToString() + tree[i].ToString());
}
if (i < tree.Length)
{
i++;
}
}
if (i + 1 != tree.Length)
{
i--;
}
numNode.number = zero;
TreeStack.Push(numNode);
}
}
}
最佳答案
我想您知道您缺少第二个操作数,因为您一看到运算符,就会尝试弹出堆栈以获得 2 个值。在示例中,您很容易看出它永远不会是这种情况(堆栈将有 2 个变量,因为运算符是二进制的)。因此,您应该了解如何存储第二个变量和运算符,并尝试在稍后对其进行评估。下面的算法可能会有帮助,请理解它是简单运算符的基本算法。
- 从 2 个堆栈、一个变量和一个运算符开始。
- 在将运算符压入运算符堆栈之前,检查优先级/优先级。如果栈顶现有运算符的优先级高于或等于您要压入的运算符,则开始为运算符和变量弹出堆栈。
- 最后,当您遍历整个字符串后,检查您的堆栈中是否有任何遗漏的运算符,完成对其的评估,您应该会得到最终结果。
在 2*3+4 中,当您达到 + 时,您将在一堆中有 2,3,在另一堆中有 *。现在尝试压入 + 时,您会看到堆栈中现有的 * 具有更高的优先级,因此弹出它,因为它是一个二元运算符弹出 2 个变量,构建一个表达式对其进行评估并压入变量堆栈(因为结果是评估将是一个变量/数字),然后再次查看堆栈中是否还有更高优先级的运算符。
添加解决方案,请务必牢记: 1. 运算符优先级/什么样的运算符(一元/二元)/是否对称/非对称(+是对称的但幂不是)将起重要作用。
尽量不要在循环内修改 i 变量,迟早会遇到麻烦。
给出的代码只对给定的2个例子有效,检查优先级的部分是空白的,但可以在现有代码的基础上填写。
您将需要修改您的变量命名 loigc,如果混合名称如“A2”,您当前的逻辑将失败。
string tree = "AB-12-AC-14";
Stack<BaseNode> TreeStack = new Stack<BaseNode>();
Stack<BaseNode> TreeStack1 = new Stack<BaseNode>();
BaseNode temp1 = new BaseNode();
BaseNode temp2 = new BaseNode();
for (int i = 0; i < tree.Length; i++)
{
VariableNode varNode = new VariableNode();
NumericalNode numNode = new NumericalNode();
if (CheckExpressions(tree[i])) // if the character is an operator
{
OperatorNode expression = new OperatorNode(tree[i]);
//check priority should pass the current operator to really check for priority
if (CheckPriority() || TreeStack1.Count == 0)
{
TreeStack1.Push(expression);
}
else
{
// assuming binary operators only
temp1 = TreeStack.Pop();
temp2 = TreeStack.Pop();
expression.Right = temp1;
expression.Left = temp2;
TreeStack.Push(expression);
// need to check if there are more operators on stack1 are they higher priority then current operator
// if they are then pop them and apply them too
}
}
else if (!CheckExpressions(tree[i]))
{
if (Char.IsLetter(tree[i]))
{
while (Char.IsLetter(tree[i])) // for the variable node
{
varNode.name += tree[i];
if (i + 1 == tree.Length)
{
break;
}
i++;
}
TreeStack.Push(varNode);
if (i + 1 != tree.Length)
{
i--;
}
}
else if (Char.IsDigit(tree[i])) // for constant value
{
int zero = 0; // for appending the numbers to combine them
while (i < tree.Length && Char.IsDigit(tree[i])) // need to check for length otherwise index will go out of bounds
{
if (zero == 0)
{
zero = tree[i] - '0';
}
else
{
zero = int.Parse(zero.ToString() + tree[i].ToString());
}
if (i < tree.Length)
{
i++;
}
}
if (i + 1 != tree.Length)
{
i--;
}
numNode.number = zero;
TreeStack.Push(numNode);
}
}
}
// finish any remaining operators and push the final expression on the stack
while (TreeStack1.Count!=0)
{
OperatorNode expression1 = new OperatorNode(((OperatorNode)TreeStack1.Pop()).v);
expression1.Right = TreeStack.Pop();
expression1.Left = TreeStack.Pop();
TreeStack.Push(expression1);
}
关于c# - 表达式树的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54975166/