逆波兰式(后缀表达式)的计算 & 中缀表达式转后缀表达式(逆波兰式)【java实现】

一.逆波兰式(后缀表达式)计算

思路:

*  1.遍历逆波兰式的集合
*  2.当遍历的元素为数字时,入栈 stack
*  3.当遍历的元素为运算符时,stack栈弹出两个数,num2 num1,并用该运算符计算着两个数的值
*  4.把计算结果再次压栈
*  5.最后栈中的元素就是后缀表达式的结果

代码

传入的 逆波兰表达式为: 4 5 * 8 - 60 + 8 2 / +         中缀表达式  4 * 5 - 8 + 60 + 8 / 2

结果:76

逆波兰表达式转化为逆波兰集合

/**
     * 后缀表达式转为集合
     * @param express 逆波兰表达式(后缀表达式)
     * @return
     */
    public static List<String> expressToArrayLisy(String express){
        String[] split = express.split(" ");
        List<String> list = new ArrayList<>();
        for (String s : split) {
            list.add(s);
        }
        return list;
    }

 

逆波兰式的计算

 /**
     * 逆波兰表达式的计算
     * 思路:
     *  1.遍历逆波兰式的集合
     *  2.当遍历的元素为数字时,入栈 stack
     *  3.当遍历的元素为运算符时,stack栈弹出两个数,num2 num1,并用该运算符计算着两个数的值
     *  4.把计算结果再次压栈
     *  5.最后栈中的元素就是后缀表达式的结果
     *   stack.pop()出来结果
     * @param list 逆波兰表达式的集合
     * @return
     */
    public static int polandCal(List<String> list){
        Stack<String> stack = new Stack();
        for (String item : list) {
            // 若果匹配到数字,则直接入栈
            if(item.matches("\\d+")){
                stack.push(item);
            }else{
                // 如果为运算符
                Integer num2 = Integer.parseInt(stack.pop());
                Integer num1 = Integer.parseInt(stack.pop());
                int res = 0;
                if(item.equals("+")){
                    res = num2 + num1;
                }else if(item.equals("-")){
                    res = num1 - num2;
                }else if(item.equals("*")){
                    res = num1 * num2;
                }else if(item.equals("/")){
                    res = num1 / num2;
                }else{
                    throw new RuntimeException("运算符有误...");
                }
                stack.push(res+"");
            }
        }
        return Integer.parseInt(stack.pop());
    }

二.中缀表达式转后缀表达式(逆波兰式)

中缀表达式:1+((2+3)*4)-5 

中缀表达式集合: [1, +, (, (, 2, +, 3, ), *, 4, ), -, 5]

后缀表达式:[1, 2, 3, +, 4, *, +, 5, -]

后缀表达式计算结果:16

思路:

1.先将中缀表达式转为中缀表达式集合。这里转化的时候注意多位数的处理

2.遍历中缀表达式集合。准备一个运算符栈stack,一个存储结果的集合list

3.从左往右遍历时,当为数字时,则加入到集合中

4.当为括号时,分两种情况

    4.1 如果是(左括号,则直接入栈;

    4.2如果是)右括号,则依次弹出stack中的元素,加入到list中,直到遇到(左括号,此时将这一对括号丢掉

5.当为运算符时,分为以下情况

    5.1 如果stack为空,或栈顶元素为(左括号,则直接入栈;

    5.2 如果此时的运算符的优先级大于栈顶元素运算符的优先级,则直接入栈;

    5.3 如果此时的运算符的优先级小于等于栈顶元素运算符的优先级,则将stack的栈顶元素pop弹出,加入到list中。直到栈为空或者此时的运算符的优先级大于栈顶元素运算符的优先级,入栈。

6.重复3--5,直到表达式的最右边

7.将stack中的元素全部弹出,加入到list中。

8.此时list结合,就是后缀表达式(逆波兰式)

 

代码

中缀表达式字符串转中缀表达式集合

 /**
     * 将中缀表达式字符串转为一个中缀表达式集合
     * @param express 中缀表达式
     * @return
     */
    public static List<String> toInfixExpressionList(String express){
        List<String> list = new ArrayList<>();
        int length = express.length();
        int i = 0;
        char c ;
        String str = "";
        do{
            if(( c = express.charAt(i)) < 48 || ( c = express.charAt(i)) > 57){
                list.add(c+"");
                i++;
            }else{
                // 注意多位数的处理
                str = "";// 清空
                // 根据ASII码,48的值是 数字0 57的值是数字9
                while(i < length && (c = express.charAt(i)) >=48 && (c = express.charAt(i)) <= 57){
                    str+=c;
                    i++;
                }
                list.add(str);
            }
        }while(i < length);
        return list;
    }

获取运算符的优先级

// 运算符的类,可以返回运算符的优先级
class Operation{
    private static int ADD = 1;
    private static int SUB = 1;
    private static int MUL = 2;
    private static int DIV = 2;

    public static int getValue(String operation){
        int result = 0;
        switch (operation){
            case "+":
                result = ADD;
                break;
            case "-":
                result = SUB;
                break;
            case "*":
                result = MUL;
                break;
            case "/":
                result = DIV;
            default:
                System.out.println("不存在的运算符");
                break;
        }
        return result;
    }
}

中缀表达式转后缀表达式

/**
     * 中缀表达式转为后缀表达式
     * @param infixExpressionList 中缀表达式的集合
     * @return 后缀表达式
     */
    public static List<String> parseSuffixExpressionList(List<String> infixExpressionList){
        Stack<String> stack = new Stack<>();
        List<String> list = new ArrayList<>();

        for (String item : infixExpressionList) {
            // 当item为数字时,直接加入集合
            if(item.matches("\\d+")){
                list.add(item);
            }else if(item.equals("(")){
                // 当item为 ( 左括号时,压入栈中
                stack.push(item);
            }else if(item.equals(")")){
                // 遇到括号时
                // 当item为)右括号时,则依次弹出stack栈顶的运算符,并加入list中,直到遇到(左括号为止,此时将这一对括号丢弃
                while(!stack.peek().equals("(")){
                    list.add(stack.pop());
                }
                stack.pop();// 将(左括号丢弃
            }else{
                // 当遇到运算符时
                while(stack.size() != 0 && Operation.getValue(item) <= Operation.getValue(stack.peek())){
                    list.add(stack.pop());
                }
                stack.push(item);
            }
        }
        // 将stack中的元素全部加入到list中
        while(stack.size() > 0){
            list.add(stack.pop());
        }
        return list;
    }

 

最后放一道题,从别处借鉴来的,https://blog.csdn.net/fascinatingGirl/article/details/52447647?utm_source=blogxgwz9

中缀表达式X=A+B*(C-(D+F))/E转后缀表达式之后是什么?

A.ABCDF+-*E/+
B.ABDF+C-*E/+
C.ABDF+C*-E/+
D.ABDF+C*-E+/

正确答案:A

A+B*(C-(D+F))/E

1,读到A,直接输出A

2,读到+,放入栈中

3,读到B,直接输出,此时栈中有+ ,输出AB

4,读到*,因为*的优先级高于+,入栈,栈中有+ *(右边为栈顶)

5,读到(,优先级最高,遇到)才出,入栈,栈中有+ * (

6,读到C,输出ABC

7,读到-,入栈,栈中有+ *  ( —

8,读到(,入栈,栈中有+  *  (  —(

9,读到D,输出ABCD

10,读到+,入栈,栈中有+  *  (  —( +

11,读到F,输出ABCDF

12,读到),出栈+,输出ABCDF+,栈中有+  *  ( —

13,读到),出栈—。输出ABCDF+-,栈中有+  *

14,读到/,出栈*,入栈/,输出ABCDF+-*,栈中有+ /

15,读到E,输出ABCDF+-*E

15,出栈/,输出ABCDF+-*E/

16,出栈+,输出ABCDF+-*E/+

所以后缀表达式为ABCDF+-*E/+

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值