【问题标题】:Trouble with expression tree表达式树的问题
【发布时间】:2019-07-25 06:55:54
【问题描述】:

我目前正在尝试找出表达式树的算法。我目前将获得的字符串类似于Hello+12+WorldA2-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);
        }
    }
}

【问题讨论】:

  • 我想你可以搜索波兰表示法。

标签: c# algorithm tree expression


【解决方案1】:

我想你明白你错过了第二个操作数,因为一旦你看到一个运算符,你就会尝试从堆栈中弹出 2 个值。在示例中,您很容易看出它永远不会出现这种情况(该堆栈将有 2 个变量,因为运算符是二进制的)。因此,您应该了解如何存储第二个变量和运算符,并尝试在稍后的某个时间对其进行评估。下面的算法可能会有所帮助,请理解它是简单运算符的基本算法。

  1. 从 2 个堆栈、一个变量和一个运算符开始。
  2. 在将运算符压入运算符堆栈之前,请检查优先级/优先级。如果堆栈顶部现有运算符的优先级高于或等于您将要推送的优先级,则开始为运算符和变量弹出堆栈。
  3. 最后,当您遍历整个字符串后,检查堆栈中是否存在任何遗留的运算符,完成对其的评估,您应该会得到最终结果。

在 2*3+4 中,当你达到 + 时,你将有 2,3 在一个堆栈中,而 * 在另一个堆栈中。现在尝试 push + 时,您会看到堆栈中现有的 * 具有更高的优先级,所以弹出它,因为它是一个二元运算符弹出 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);
            }

【讨论】:

  • "如果优先级...更高...",难道大于或等于也有效吗?微小的变化,但可以防止为1 + 1 + 1 + ... 之类的东西建立一个不必要的巨大堆栈事实上,它只能与运算符的数量一样大(常量,所以 that 堆栈的空间是恒定的)。
  • 谢谢@DillonDavis,你是对的,更新了答案
  • 非常感谢!我真的很感激这个
猜你喜欢
  • 1970-01-01
  • 2017-09-22
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 2011-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多