逆波兰(后缀)计算器(实现代码)

逆波兰(后缀)计算器


一、实现原理

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、实现代码(java)

mport java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * 逆波兰(后缀)计算器
 */
public class InversePolishCalculator {
    public static void main(String[] args) {
        //测试(只需提供中缀表达式)
        String expression = "(3+4)*5-20";
        //得到中缀表达式的list
        List<String> list = infixList(expression);
        System.out.println(list);
        //得到逆波兰表达式的list
        List<String> list2 = suffixExpressionList(list);
        System.out.println(list2);
        //逆波兰计算
        int i = calCalculator(list2);
        System.out.println(expression + " = " + i);
    }


    //方法:为了方便操作,我们提供一个方法将中缀表达式=>中缀表达式的list(即将中缀表达式存如集合)
    public static List<String> infixList(String infixExpression) {   //传入一个中缀表达式
        //定义一个集合,作为中缀表达式的list
        List<String> list = new ArrayList<>();
        //用于扫描,指向中缀表达式字符位置
        int index = 0;
        //解决多位数,用于拼接
        String str;
        //接收遍历的每个字符
        char ch;
        //遍历中缀表达式,并将其转换为集合
        while (index < infixExpression.length()) {
            //获取每个字符
            ch = infixExpression.charAt(index);
            //如果ch是非数字,直接加入集合中
            if (ch < 48 || ch > 57) {   //数字的ASCII码是在48~57之间
                list.add(ch + "");   //转字符串
                index++;
            } else {   //如果出是数字,那么就要考虑多位数
                str = "";
                //循环每次获得ch,将连续的数字字符拼接成多位数
                while (index < infixExpression.length() && (ch=infixExpression.charAt(index)) >= 48 && (ch=infixExpression.charAt(index)) <= 57) {
                    str += ch;   //拼接多位数
                    index++;
                }
                list.add(str);
            }
        }
        //返回结果
        return list;
    }


    /**
     * 方法:将中缀表达式的list转换为后缀表达式思路:
     */
    //为了方便,将中缀表达式的list转换为后缀表达式的list
    public static List<String> suffixExpressionList(List<String> list){
        //初始化一个栈,用来暂存运算符
        Stack<String> s1 = new Stack<>();
        //初始化一个集合s2用来存储中间结果,不用栈是因为,中途没有出栈操作,使用集合更方便
        List<String> list2 = new ArrayList<>();
        //遍历中缀表达式的list
        for (String item : list){
            //如果item是数(包含多位数),就存入集合list2中
            if (item.matches("\\d+")){
                list2.add(item);
            }else if (item.equals("(")){   //如果item是"(" ,入栈s1
                s1.push(item);
            }else if (item.equals(")")){   //如果是“)”,操作5.(2)
                //在找到“(”之前,将s1中的运算符取出,存入集合list2中
                while (!s1.peek().equals("(")){   //s1.peek()方法是查看栈顶元素
                    list2.add(s1.pop());
                }
                //去掉“( ”
                s1.pop();
            }else {
                //当item的优先级不大于栈顶运算符的优先级时,操作4.(3),s1栈顶出栈,加入的list2中
                //调用自定义的运算符优先级比较类
                while (s1.size()!=0 && MyPriority.priority(item) <= MyPriority.priority(s1.peek())){
                    list2.add(s1.pop());
                }
                //当s1为空,或item优先级大于栈顶优先级后,item入栈s1
                s1.push(item);
            }
        }
        //遍历结束后,将s1栈中的剩下的运算符存入list2集合中
        while (s1.size()!=0){
            list2.add(s1.pop());
        }
        //返回结果
        return list2;
    }


    /**
     * 计算器
     * 思路:
     * 例如: (3+4)×5-6 对应的后缀表达式就是 3 4 + 5 × 6 - , 针对后缀表达式求值步骤如下:
     * 1.从左至右扫描,将3和4压入堆栈;
     * 2.遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈;
     * 3.将5入栈;
     * 4.接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
     * 5.将6入栈;
     * 6.最后是-运算符,计算出35-6的值,即29,由此得出最终结果
     */
    public static int calCalculator(List<String> list){
        //创建一个栈,用来存储数字
        Stack<String> stack = new Stack<>();
        //遍历集合
        for (String str : list){
            //通过正则表达式来获取数字
            if (str.matches("\\d+")){   //匹配多位数
                //数字就入栈
                stack.push(str);
            } else {   //是符号
                //定义一个数,保存计算结果
                int res = 0;
                //取出栈顶的两个数
                int num1 = Integer.parseInt(stack.pop());
                int num2 = Integer.parseInt(stack.pop());
                if (str.equals("+")){
                    res = num1 + num2;
                }else if (str.equals("-")){
                    res = num2 - num1;   //注意顺序:后出栈的-先出栈的
                }else if (str.equals("*")){
                    res = num1 * num2;
                }else if (str.equals("/")){
                    res = num2 / num1;   //注意顺序:后出栈的 / 先出栈的
                }else {
                    throw new RuntimeException("运算符错误");
                }
                //运算结束后,将运算结果入栈
                stack.push(res + "");   //这样写的目的是讲数字res转换为字符串入栈
            }
        }
        //运算结束后,栈中只有一个数,也就是结果
        return Integer.parseInt(stack.pop());
    }
}


//自定义一个比较运算符优先级的类
//数字越大,优先级越高
class MyPriority{
    public static int priority(String operator){
        int res = 0;
        switch (operator){
            case "+":
                res = 1;
                break;
            case "-":
                res = 1;
                break;
            case "*":
                res = 2;
                break;
            case "/":
                res = 2;
                break;
        }
        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值