【问题标题】:Create a binary tree from an algebraic expression从代数表达式创建二叉树
【发布时间】:2011-10-23 14:08:54
【问题描述】:

我必须在 Java 中创建一个算术评估器。为此,我必须解析二叉树中的代数表达式,然后计算并返回结果。那么第一步如何解析二叉树中的表达式?我知道这个理论,但我的问题是如何在 Java 中做到这一点。我阅读了以下帖子 create recursive binary tree

但我缺少基本的技巧或方法。我知道如何创建一个节点(我有一个带有 returnNodeValue、isLeaf、isDoubleNode、isSingleNode 等方法的类),但我认为我需要一种方法来在二叉树中插入一个节点来实现我想要的。有什么想法吗?

【问题讨论】:

  • 到目前为止您尝试过什么?伪代码就在那里(网络上有大量的实现,无论好坏)。
  • 我已经编写了按后缀、中缀和前缀顺序读取树的函数。我知道有很多例子,但我找不到我要找的东西。我需要一些关于如何从代数表达式创建树的入门帮助(我的意思是如何获取表达式并测试优先级并存储值等)。我知道我要的是基本的,但我只是卡住了。任何链接或帮助将不胜感激。谢谢。
  • 一般来说,要写一个解析器,你需要一个语法。然后有很多种解析器。在网上搜索“递归下降”解析器——很容易理解如何编写它们。顺便问一下,这是作业吗?

标签: java parsing tree binary-tree


【解决方案1】:

前缀表达式的树构造

def insert

     Insert each token in the expression from left to right:

     (0) If the tree is empty, the first token in the expression (must
         be an operator) becomes the root

     (1) Else if the last inserted token is an
         operator, then insert the token as the left child of the last inserted
         node.

     (2) Else if the last inserted token is an operand, backtrack up the
         tree starting from the last inserted node and find the first node with a NULL
         right child, insert the token there. **Note**: don't insert into the last inserted 
         node. 
end def

我们举个例子:+ 2 + 1 1

应用 (0)。

  +

应用 (1)。

  +
 /
2 

应用 (2)。

  +
 / \
2   +

应用 (1)。

  +
 / \
2   +
   /
  1 

最后,应用(2)。

  +
 / \
2   +
   / \
  1   1

该算法已经针对- * / 15 - 7 + 1 1 3 + 2 + 1 1进行了测试

所以Tree.insert 的实现就是这三个规则。

insert(rootNode, token)
  //create new node with token
  if (isLastTokenOperator)//case 1
      //insert into last inserted's left child
  else {                  //case 2
      //backtrack: get node with NULL right child
      //insert
  }
  //maintain state
  lastInsertedNode = ?, isLastTokenOperator = ?

评估树有点有趣,因为您必须从树的右下角开始。执行反向post-order 遍历。首先访问正确的孩子。

evalPostorder(node)
  if (node == null) then return 0
  int rightVal = evalPostorder(node.right)
  int leftVal = evalPostorder(node.left)
  if(isOperator(node.value)) 
       return rightVal <operator> leftVal    
  else
       return node.value

鉴于从前缀表达式构造树的简单性,我建议使用标准 stack algorithm 将中缀转换为前缀。在实践中,您会使用堆栈算法来计算中缀表达式。

【讨论】:

  • 感谢您,终于找到了所有步骤。从中缀转换为前缀(参见Shunting-yard algorithm:比提供的链接更好地解释)-> 创建树-> 使用反向后序遍历进行评估。谢谢!
  • 如果树为空,则表达式中的第一个标记(必须是运算符) 除非整个表达式由一个操作数组成。
  • 能否给出一个回溯到正确空节点的示例代码?
【解决方案2】:

我想你可能对你应该做什么有点困惑:

...但我想我需要一种方法来在二叉树中插入一个节点...

你说的二叉树其实是解析树,严格来说并不是二叉树(因为不是所有的树节点都是二叉的)。 (除了“二叉树”还有二叉搜索树的含义,这根本不是你需要的。)

您已经想出解析表达式的方法,解析树的构造非常简单。例如:

Tree parseExpression() {
    // ....
    // binary expression case:
        Tree left = parseExpression();
        // parse operator
        Tree right = parseExpression();
        // lookahead to next operator
        if (...) {
        } else {
            return new BinaryNode(operator, left, right);
        }
     // ...
}

注意:这不是工作代码...它是帮助您完成作业的提示。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    相关资源
    最近更新 更多