逆波兰式Java 代码实现
  anLrwkgbyYZS 2023年12月30日 15 0


把正常的表达式看做表达式的中序遍历,那么逆波兰式(Reverse Polish notation,RPN)就是该表达式的后序遍历,即将运算符放在操作数之后,波兰式则是该表达式的前序遍历。

1. 算法基本实现 

需要一个栈s1 和 一个数组 s2;

栈 s1 用来存放存储临时运算符,标志着开始 ,初始里面有一个#号,#号是最低优先级。

s2数组存储转换后的表达式。

不断从表达式中取出数据,逆波兰式生成思想如下所示:

(1)若取出的字符是数字,则分析出完整的运算数,该运算数直接添加到S2中,操作数使用&隔开。

(2)若取出的字符是运算符(+,-,*,/) 则将该运算符与S1栈栈顶元素比较;

如果该算符优先级(不包括括号运算符)大于S1栈栈顶运算符优先级,则将该运算符进S1栈,

否则,将S1栈的栈顶运算符弹出,送入S2栈中,直至S1栈栈顶运算符低于(不包括等于)该运算符优先级,最后将该运算符送入S1栈。

(3)若取出的字符是“(”,则直接送入S1栈顶。

(4)若取出的字符是“)”,则将距离S1栈栈顶最近的“(”之间的运算符,逐个出栈,依次送入S2,此时抛弃“(”。

(5)取出 # , S1栈中所有的运算符添加到S2中。

举一个例子,一个表达式 (88+7)-9*6#,#号代表着结束,逆波兰生成过程如下所示。

读入的字符

栈 s1 

数组 s2(生成的逆波兰式)

(

#(

 

8

#(

8

8

#(

88&

+

#(+

 

7

#(+

88&7

)

#

88&7+

-

#-

 

9

#-

88&7+9

*

#-*

88&7+9 

6

#-* 

88&7+9&6

#

#

88&7+9&6*-

逆波兰式的计算比较简单,如果当前字符为数字,计算出一个运算数压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。

读入的字符

栈 

88

88

7

88 7

+

95

9

95  9

6

95 9 6

*

95 54

-

41

最终结果 41 。

2. 代码实现

package reversePolishnotation;

import java.util.*;

/**
 * 逆波兰式代码实现
 */
public class MyRPN {
    private Stack<Character> s1;
    private String s2;
    private ArrayList<Integer> number;

    public MyRPN() {
        s1 = new Stack<>();
        this.s1.push('#');
        s2 = new String("");
    }

    public boolean isOperation(char op) {
        if (op == '+' || op == '-' || op == '*' || op == '/') {
            return true;
        }
        return false;
    }

    public void makeRPN(String expression) {
        int length = expression.length();
        for (int i=0; i<length; i++) {
            char now = expression.charAt(i);
            // 处理数字
            if (Character.isDigit(now)) {
                if (!s2.isEmpty()) {
                    if (Character.isDigit(s2.charAt(s2.length()-1))) {
                        s2 += "&";
                    }
                }
                s2 += expression.charAt(i);
                while(Character.isDigit(expression.charAt(i+1))) {
                    s2 += expression.charAt(++i);
                }
            }
            // 处理 (
            else if (now == '(') {
                s1.push('(');
            }
            // 处理 )
            else if (now == ')') {
                while (s1.peek() != '(') {
                    char temp = s1.pop();
                    s2 += temp;
                }
                s1.pop();
            }
            // 处理 #
            else if (now == '#'){
                break;
            }
            // 处理运算符
            else {
                if (!this.isOperation(s1.peek())) {
                    s1.push(now);
                }
                else if (this.compareOperator(now, s1.peek())) {
                    s1.push(now);
                } else {
                    while (this.isOperation(s1.peek()) && !this.compareOperator(now, s1.peek())) {
                        s2 += s1.pop();
                    }
                    s1.push(now);
                }
            }
        }
        while (s1.peek() != '#') {
            s2 += s1.pop();
        }
    }

    /**
     * 结算逆波兰式
     */
    public Integer calculateRPN() {
        Stack<Integer> calculateStack = new Stack<>();
        int length = this.s2.length();
        for (int i=0; i<length; i++) {
            if (Character.isDigit(s2.charAt(i))) {
                int temp = 0;
                temp = temp*10 + s2.charAt(i)-'0';
                while(Character.isDigit(s2.charAt(i+1))) {
                    temp = temp*10 + s2.charAt(++i)-'0';
                }
                if (s2.charAt(i+1) == '&') {
                    ++i;
                }
                calculateStack.push(temp);
            } else {
                int b = calculateStack.pop();
                int a = calculateStack.pop();
                switch (s2.charAt(i)) {
                    case '+' : calculateStack.push(a+b); break;
                    case '-' : calculateStack.push(a-b); break;
                    case '*' : calculateStack.push(a*b); break;
                    case '/' : calculateStack.push(a/b); break;
                }
            }
        }
        return calculateStack.pop();
    }

    /**
     * 比较运算符的优先级
     * @param a:运算符A
     * @param b:运算符B
     * @return 比较结果
     */
    public boolean compareOperator(char a, char b) {
        boolean flag = false;
        if ((a == '*' || a == '/') && (b == '+' || b == '-')){
            flag = true;
        }
        return flag;
    }

    public String getS2() {
        return s2;
    }

    public static void main(String[] args) {
        String str = new String("((10*(6/(9-3)*11))+17)+5#");
        MyRPN myRPN = new MyRPN();
        myRPN.makeRPN(str);
        System.out.println(myRPN.getS2());
        System.out.println(myRPN.calculateRPN());
    }
}

测试数据,((10*(6/(9-3)*11))+17)+5# , 表达式的逆波兰式为: 10&6&9&3-/11**17+5+,计算结果:132。

逆波兰式Java 代码实现_逆波兰式

测试数据,1+5+6*9-9/3# , 表达式的逆波兰式为 :1&5+6&9*+9&3/-,计算结果:57。

逆波兰式Java 代码实现_逆波兰式_02

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月30日 0

暂无评论

推荐阅读
anLrwkgbyYZS