将后缀表示法转换为 ExpressionTree

Posted

技术标签:

【中文标题】将后缀表示法转换为 ExpressionTree【英文标题】:Converting a Postfix Notation to an ExpressionTree 【发布时间】:2015-02-15 19:07:56 【问题描述】:

正如标题中所说,我正在尝试创建一个将后缀符号转换为表达式树的代码。在这里你可以检查构造函数:

  public byte type;         // 0    : operator, 1: operand (a number)
  public char operator;     // One of '+', '-', '*', '/'
  public int operand;       // A number
ExpressionTreeNode(byte type)this.type = type; left=right=null;

这是我的代码:

    public static ExpressionTreeNode Postfix2ExpressionTree(String postfixExpr)

            Stack s = new Stack<Object>();
            ExpressionTreeNode root = new ExpressionTreeNode((byte) 0);
            root.operator = postfixExpr.charAt(postfixExpr.length()-1);
            String number = "";

            for(int i = 0;i<postfixExpr.length()-1;i++)

                if(Character.isDigit(postfixExpr.charAt(i)) == true)

                     number = number + postfixExpr.charAt(i);
                     if(Character.isDigit(postfixExpr.charAt(i+1)) == false)
                         ExpressionTreeNode node = new ExpressionTreeNode((byte) 1);
                         node.operand = Integer.valueOf(number);
                         node.right = null;
                         node.left = null;

                         s.push(node);
                         number = "";
                                
                         
                if(i == postfixExpr.length()-2)

                    root.right = (ExpressionTreeNode) s.pop();
                    root.left =(ExpressionTreeNode) s.pop();
                    s.push(root);
                    break;
                
                else 
                    if(postfixExpr.charAt(i) == '+' || postfixExpr.charAt(i) == '*' || postfixExpr.charAt(i) == '-' || postfixExpr.charAt(i) == '/' )


                    ExpressionTreeNode node = new ExpressionTreeNode((byte)0);
                    node.operand = postfixExpr.charAt(i);
                    node.right = (ExpressionTreeNode) s.pop();
                    node.left = (ExpressionTreeNode) s.pop();

                    s.push(node);

                    

                

            

        return (ExpressionTreeNode) s.pop();
      

我用 charAt() 方法一一检查每个字符。简单地 1-将每个操作数压入堆栈 2-当遇到运算符时,从堆栈中弹出两个操作数并将它们分配给运算符的右侧和左侧,然后将新节点推入堆栈。 3-最后我将根压入堆栈然后返回它。

当我尝试运行时没有发生错误,但它也没有以正确的方式工作。代码我检查了很多次,但我无法解决。如果有人看到错误并帮助我,那就太好了。

【问题讨论】:

请在格式化您的代码方面付出更多努力 - 缩进现在到处都是,使其难以阅读。 “它没有以正确的方式工作”:输入是什么,它应该做什么,以及它做了什么? 请解释if(i == postfixExpr.length()-2)的原因。 我使用了 if(i == postfixExpr.length()-2) 因为我想知道 charAt(i) 是否在堆栈的顶部。如果它在顶部,我已经定义了根,所以我可以将左右分配给根。 为什么?后缀是一种线性符号。你不需要一棵树。您可以从左到右评估它,或者直接从中生成目标代码,... 【参考方案1】:

后缀表达式是从左到右解析的——在你出现之前不要看 postfixExpr.length()-1。

不要以任何特殊方式创建和处理根节点。解析后会在栈顶。

这是一个错误:

node.operand = postfixExpr.charAt(i);

这必须存储在 node.operator 中。

这就是我将如何实现它:

public interface Entry 
  int evaluate();

public class Value implements Entry 
  private int value;
  public Value( int value )
    this.value = value;
  
  public int  evaluate()
    return value;
  

public class Operation implements Entry 
  private char operator;
  private Entry left;
  private Entry right;
  public Operation( char operator, Entry left, Entry right )
    this.operator = operator;
    this.left = left;
    this.right = right;
  
  public int  evaluate()
    int l = left.evaluate();
    int r = right.evaluate();
    switch(operator)
    case '+':
      return l + r;
    case '-':
      return l - r;
    case '*':
      return l * r;
    case '/':
      return l / r;
    
    throw new IllegalStateException( "operator " + operator );
  

public class Parser 
  private Stack<Entry> stack = new Stack<>();
  Pattern pat = Pattern.compile( "[-+*/]" );
  Scanner scanner;
  public void parse( String ex )
    scanner = new Scanner( ex );
    while( scanner.hasNext() )
      while( scanner.hasNextInt() )
        stack.push( new Value( scanner.nextInt() ) );
      
      while( scanner.hasNext( pat ) )
        char op = scanner.next( pat ).charAt( 0 );
        Entry right = stack.pop();
        Entry left = stack.pop();
        stack.push( new Operation( op, left, right ) );
      
    
  
  public Entry get()
    return stack.pop();
  

绝对没有错误处理,所以考虑添加它。

【讨论】:

你说得对,我错过了这一点,我修复了它但仍然无法正常工作:/ 感谢代码,我也修复了我的错误,我犯的错误是使用 charAt() 检查字符串。我通过 split 方法从字符串中创建一个数组。这是正确的方式。

以上是关于将后缀表示法转换为 ExpressionTree的主要内容,如果未能解决你的问题,请参考以下文章

尝试将中缀转换为后缀返回向后输出

使用链表堆栈的中缀到后缀转换器

PTA-7-20 表达式转换(中缀转后缀,带括号,负数,小数转换)

中缀表达式转换为后缀表达式(1042)

以最少的步骤转换为正确的后缀表示法

7-20 表达式转换