逆波兰计算器(使用一个栈)

1.先将中缀表达式转为后缀表达式

//中缀表达式转后缀表达式
public class Infix2Postfix {

    public static void main(String[] args) {
        String s = "1+((22+33)*4-5";
        List<String> list = in2List(s);
        System.out.println(list);
        /*String str = "1 + ( ( 2 + 3 ) * 4 ) - 5";
        String s = in2post(str);
        System.out.println(s);*/
    }

    //中缀表达式转List
    public static List<String> in2List(String str) {
        int index = 0;
        List<String> list = new ArrayList<>();
        while (index < str.length()) {
            Character c = str.charAt(index);
            if (c < 48 || c > 57) {
                //说明不是数
                list.add(c.toString());
                index++;
            } else {
                //是数字
                String s = c.toString();
                while (true) {
                    if (index == str.length() - 1 || str.charAt(index + 1) < 48 || str.charAt(index + 1) > 57) {
                        //到了最后一位或者下一位不是数字,放入集合中
                        list.add(s);
                        index++;
                        break;
                    } else {
                        s += str.charAt(index);
                        index++;
                    }
                }
            }
        }
        return list;
    }


    //中缀表达式转后缀表达式
    public static String in2post(String str) {
        //1+(2+3)*4-5 -> 1 2 3 + 4 * + 5 -
        String[] strArr = str.split(" ");
        //存放数和运算符(可以直接使用list代替,因为代码中没有pop操作,而且最后还需要逆序)
        Stack<String> numStack = new Stack<>();
        //临时存放运算符
        Stack<String> opeStack = new Stack<>();
        for (String s : strArr) {
            if (s.matches("\\d+")) {
                //若是数则直接放入,numStack
                numStack.push(s);
            } else {
                switch (s) {
                    case "+":
                    case "-":
                    case "*":
                    case "/":
                        if (opeStack.isEmpty() || opeStack.peek().equals("(")) {
                            //若栈中没有其他符号,或前一个符号是“(”,直接入栈
                            opeStack.push(s);
                        } else {
                            //和ope栈中的每个运算符比较,直到比其优先级高,或者栈为空时入栈
                            while (true) {
                                if (opeStack.isEmpty()) {
                                    //为空,说明已经和所有的栈中运算符进行了比较
                                    opeStack.push(s);
                                    break;
                                }
                                if (getPriority(s) > getPriority(opeStack.peek())) {
                                    //优先级大于栈顶运算符,入栈-->入栈后结束循环
                                    opeStack.push(s);
                                    break;
                                } else {
                                    //优先级小,将ope中的运算符,弹出压入num中
                                    String pop = opeStack.pop();
                                    numStack.push(pop);
                                }
                            }
                        }
                        break;
                    case "(":
                        opeStack.push(s);
                        break;
                    case ")":
                        //若为右括号
                        while (true) {
                            String pop = opeStack.pop();
                            if ("(".equals(pop)) {
                                //一直到左括号结束
                                break;
                            }
                            //将()期间的符号都弹出,压入num中
                            numStack.push(pop);
                        }
                        break;
                }
            }
        }
        while (!opeStack.isEmpty()) {
            String pop = opeStack.pop();
            numStack.push(pop);
        }
        StringBuilder sb = new StringBuilder();
        List<String> list = new ArrayList<>();
        while (!numStack.isEmpty()) {
            String pop = numStack.pop();
            list.add(pop);
        }
        for (int i = list.size() - 1; i >= 0; i--) {
            sb.append(list.get(i));
            if (i != 0) {
                sb.append(" ");
            }
        }
        return sb.toString();
    }

    //获取优先级
    public static int getPriority(String str) {
        int priority = 0;
        switch (str) {
            case "+":
            case "-":
                priority = 1;
                break;
            case "*":
            case "/":
                priority = 2;
                break;
            default:
                break;        }
        return priority;
    }

}

2.使用后缀表达式实现计算操作

 

//逆波兰实现计算器
public class PolandNotation {

    public static void main(String[] args) {
        //3 * 5 - 8 + 2 * 2 --> 3 5 * 8 - 2 2 * +
        String reStr = "3 * 5 - 8 + 2 * 2";
        //逆波兰表达式
        String str = "3 5 * 8 - 2 2 * +";
        //转换为数组
        String[] strArr = str.split(" ");
        int res = col(strArr);
        System.out.printf("%s的运算结果为:%d", reStr, res);
    }

    //运算
    public static int col(String[] strArr) {
        Stack<String> stack = new Stack<>();
        int res = 0;
        for (String str : strArr) {
            //若是一个数,直接压入栈中
            if (str.matches("\\d+")) {
                stack.push(str);
            } else {
                //若是一个符号,进行计算
                //栈顶数
                int num1 = Integer.parseInt(stack.pop());
                int num2 = Integer.parseInt(stack.pop());
                switch (str) {
                    case "+":
                        res = num1 + num2;
                        break;
                    case "-":
                        res = num2 - num1;
                        break;
                    case "*":
                        res = num1 * num2;
                        break;
                    case "/":
                        res = num2 / num1;
                        break;
                    default:
                        throw new RuntimeException("符号错误");
                }
                //将结果压入栈中
                stack.push("" + res);
            }
        }
        return Integer.parseInt(stack.pop());
    }

}

从B站韩顺平老师的Java数据结构与算法习得。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值