• 中缀表达式转后缀表达式


      先看几个中缀表达式和它们对应的后缀表达式的例子

      可以看到操作数a, b, c 在中缀表达式中的顺序和在后缀表达式中的顺序是一致的,但操作符的顺序可能不一致,因为在中缀表达式中操作符有优先级,括号也能改变运算的优先级,这些都要在后缀表达式中体现出来,后缀表达式中没有括号。那怎么转化呢?

      1,创建一个变量,初始化为空的字符串,来表示要完成的后缀表达式,创建一个字符栈,用来存储操作符

      2,从左向右依次扫描中缀表达式,

        遇到操作数,直接加到后缀表达式的后面 ,因为,在中缀表达式和后缀表达式中,操作数的顺序是一样的,

        遇到操作符,要先存起来,存到栈中,因为操作符有优先级,它要和后面的操作符比较优先级,然后才能决定把它放到什么哪个位置。

          如果栈为空,直接把操作符放入栈中

          如果栈不为空,比较优先级。

            如果遇到的操作符比栈顶中的操作符优先级高,把遇到的操作符放入栈中。

            如果遇到的操作符和栈顶操作符的优先级相等,这要考虑操作符的结合性,它是从左到右结合,还是从右到左结合。

              从左到右接合,就是操作数属于它前面的操作符而不是它后面操作符。+, - , * , / 就是从左向右结合,比如a-b+c中的b是-的操作数,而不是+的操作数,整个表达式,也是从左向右计算的。

              从右向左结合,操作数属于它前面的操作符而不是它后面操作符,比如阶乘。a ^ b ^ c, b是第二个^的操作数,而不是第一个^的操作数,整个表达式也是从右向左计算,a ^ (b ^ c)。

              如果从左向右接合,那就弹栈,把操作符放到后缀表达式中,如果从右向左结合,则把遇到的操作符放入栈中(和优先级高的情况一致)

            如果遇到的操作符比栈顶中的操作符优先级低,那就弹栈,把操作符放到后缀表达式中

        遇到(,放到字符栈,因为要等到)才能知道怎么操作。

        遇到),依次从字栈中弹栈,放到后缀表达式中,直到遇到(,  遇到(, 要把它弹栈,然后舍弃掉。

      3,循环完毕,如果字符栈中还有操作符,依次弹栈放到后缀表达式中,最终栈为空,得到完整的后缀表达式。

      举几个例子,来理解一下转化过程,如果遇到的操作符比栈顶的操作符优先级高,比如把a + b * c。先创建空字符串作为后缀后达式,再从左到右扫描中缀表达式,把a放到新建后缀表达式后面,把+存到栈中,然后把b放到后缀表达式后面,这时遇到了*,*号的优先级比栈中的+高,也就是说,操作数b并不是+的第二个操作数,而是乘号的操作数,+的操作数要等待*的运算结果,这时把*放入到栈中,再把c放到后缀表达式中,中缀表达式扫描完毕,这时把操作符从栈中pop()出来,依次放到后缀表达式的后面,得到整个后缀表达式是abc*+

     

      遇到的操作符和栈顶操作符的优先级相等,但是从左向右结合,比如a-b+c。创建空字符串表示后缀表达式,ab放到空字符中,-放入到字符栈中,此时遇到+,+和-的优先级相等,+的操作要等它左边表达式的结果,也就是说,要先算减的结果,a,b属于-,所以把-弹栈,放到后缀表达式中,此时栈为空,再把+放入到栈中。把c放到后缀表达式,弹栈+,把+放到表达式中。最终,a-b+c的后缀表达式为ab-c+

       遇到的操作符和栈顶操作符的优先级相等,但是从右向左结合,比如a ^ b ^ c, 创建空字符串表示后缀表达式,ab放到空字符中,^放入到字符栈中,此时又遇到^,它和栈顶中的^优先级相等,但^是从右向左接合,要先计算后边的结果,所以还是把^入栈,c放到后缀表达式,依次弹栈^,放到表达式中。最终,a ^ b ^ c的后缀表达式为a b c ^ ^

     

      综上所述,中缀表达式转化为后缀表达式,步骤如下:

      从左向右依次扫描中缀表达式,

        如果遇到操作数,就放入到后缀表达式字符串中,默认是空字符串。

        如果遇到^,就入字符栈。

        如果遇到+, -, *, /,  如果栈不为空并且新来的操作符比栈项的操作符优先级低,就不停弹栈,添加到后缀表达式中,然后把新的操作符入栈。

        如果遇到 (,入字符栈。

        如果遇到 ),依次弹字符栈,添加到后缀表达式中,直到遇到(,然后把它舍弃掉。

      扫描完毕后,如果字符栈不为空,再依次弹字符栈,添加到后缀表达式中。

    import java.util.Stack;
    
    public class InfixToPostfix {
        public static String convertToPostfix(String infixExpression){
    
            // 创建字符栈
            Stack<Character> operators = new Stack<>();
    
            // 创建将要实现的后缀表达式,初始为空
            StringBuilder postfix = new StringBuilder();
    
            for (int i = 0; i < infixExpression.length(); i++) {
    
                char c = infixExpression.charAt(i);
    
                // 如果中缀表达式中有空格
                if (c == ' ') {
                    continue;
                } else if (c == '^'){
                    operators.push(c);
                } else if (c == '+' || c == '-' || c == '*' || c == '/' ){
                    while (!operators.isEmpty() && priority(c) <= priority(operators.peek())){
                        postfix.append(operators.pop());
                    }
    
                    operators.push(c);
                } else if (c == '('){
                    operators.push(c);
                } else if(c == ')'){
                    while (operators.peek() != '('){
                        postfix.append(operators.pop());
                    }
                    operators.pop();
                } else {
                    postfix.append(c);
                }
            }
    
            while (!operators.isEmpty()){
                postfix.append(operators.pop());
            }
    
            return postfix.toString();
    
        }
    
        private static int priority(char operator) {
            if(operator == '*' || operator == '/' ) {
                return 1;
            } else if (operator == '+' || operator == '-' ) {
                return 0;
            } else {
                return -1;
            }
        }
    }

      调用 convertToPostfix("a  / b  * (c  + (d  - e))"),得到后缀表达式为"a  / b  * (c  + (d  - e))"。 

  • 相关阅读:
    栈及其在.NET FrameWork中的源码分析
    《高性能网站建设指南》读书笔记
    九宫格数独问题
    队列及其在.NET FrameWork中的源码分析
    《web标准之道》读后感(书评)
    SharePoint中的权限体系
    关于异步方法调用
    WF4.0 Beta2:关于动态保存和装载XAML工作流
    Lotus Symphony介绍及试用
    Node.js 0.8.18 / 0.9.7 发布
  • 原文地址:https://www.cnblogs.com/SamWeb/p/15669761.html
Copyright © 2020-2023  润新知