逆波兰计算器原理

逆波兰计算器原理

1.计算器的几种形式

  1. 前缀表达式:符号在前左,数字在右。符号数字位置考虑运算优先级。
  2. 中缀表达式 :符号在数字中间(即正常书写的表式结构 “1+( (2+3) *4)-5”
  3. 后缀 表达式:将要进行的部分运算的数字在前运算符号在后,接着其它部分的运算。

2.计算表达式分析

​ 计算表达式一般包含数值运算符,括号,包括运算符的优先级计算,以及括号产生的优先级运算。

3.栈的特点

  • 先进后出
  • 存和取出数据的方式适合优先级符号的存取
  • 在while循环中,控制长度,栈的存和取可以使 迭代条件省去(i++)

4.不同显示的思路分析

4.1中缀实现的分析

  • 几个要素:

    1. 两个栈 符号栈与数字栈
    2. 扫描方式以及识别的方法(多位数与单位数的区别、符号、运算符)
    3. 分别存入两个栈的要求
    4. 优先级可考虑(与上一个存入符号栈的优先级的比较)
    5. 数字栈最后一个数为结构
  • 重点

    1. 符号栈必须要有一个符号,便于符号优先级的比较,通过比较扫描的与栈顶的符号优先级,如果栈顶优先级大于等于扫描到的,弹入数字栈。
    2. 遇到“( ” 与 “ )” 的区别,遇到“( ” 直接入栈,遇到” )“ ,将符号栈中符号依次弹出,直到”(“ 位置,将”(“ 消除即可。
  • /**
     * 中缀转后缀
     说明:list为ArrayList对象, 数字站也是ArrayList对象。
     * 1.一个符号栈,一个数字存储栈
     * 2.逐个配对list对象内的变量从左到右
     *  3.如果是数字 存入数字存储栈,
     *  4 .如果是括号
     *    > 1.如果符号栈空压入栈
     *    > 2.如果是"( "压入符号栈
     *    > 3.如果是括号")" ,一次弹出符号栈字符于数字存储栈,直到遇到"(",
     *    将"(" 弹出即可(删除,不用存入)
     *  5.如果是运算符
     *  1.符号栈空直接添加即可
     *  2.如果当前符号优先级小于等于栈顶优先级,将栈顶符号存入数字存储栈
     *  然后重新步骤5(对于扫描的符号)
     *  6.扫描到了最右,将剩余符号栈的符号存入数字存储栈
     */
    

5.代码

public class PolandNotation {
    public static void main(String[] args) {
        String suffixExpression = "30 4 + 5 * 6 -";
        List<String> list = getList(suffixExpression);
        System.out.println(list);
        //遍历数组
        int ans = caculate(list);
        System.out.println("结果是:" + ans);
        List<String> s1 = toInfixExpressionList("1*(2+3)*4-5");
        System.out.println(s1);
        List<String> s2 = toInfixExpressions(s1);
        System.out.println(s2);


    }
    
   public static List<String> toInfixExpressions(List<String > list){
       Stack<String> stack = new Stack<String>();
       List<String> numlist = new ArrayList<String>();


       for(String item : list){
           System.out.println(item);
           if(item.matches("\\d+")){//识别多位数
               numlist.add(item);
           }else if (item.equals("(")){
               stack.push(item);
           }else if (item.equals(")")){
               while (!stack.peek().equals("(") ){//字符串对比用equals
                   numlist.add( stack.pop());
               }
               stack.pop();//消掉"("
           }else {//由于符号类型多,可以放在else内

                   while (stack.size() != 0 && !stack.peek().equals("(") && Operation.getValue(stack.peek()) >= Operation.getValue(item)) {
                       numlist.add(stack.pop());
                   }
                   stack.push(item);

           }
       }
       //将剩余stack栈符号存入数字列表
       while(stack.size() != 0){
           numlist.add(stack.pop());
       }
       return numlist;
   }

   /**
     * 提取字符串为list
     * 1.字符串输入
     * 2.多位数的判断、符号的判断 48 - 57 字符'0' ---'9'
     * 3.使用do while结构
     */

    public static List<String> toInfixExpressionList(String s){
        List<String> list = new ArrayList<>();
        char c;
        int i = 0;
        String str;
        do{
            if(s.charAt(i) < 48 || s.charAt(i) > 57){//不为数字
                list.add(""+s.charAt(i));
                i++;
            }else {
                 str ="";
                while( i < s.length() && s.charAt(i) >= 48 && s.charAt(i) <= 57){
                    str += ""+s.charAt(i);
                    i++;
                }
                list.add(str);
            }
        }while(i < s.length());

        return list;
    }

    public static int caculate(List<String> list){
        Stack<String> stack = new Stack<>();
        int num1 = 0;
        int num2 = 0;
        int res = 0;
        for(String item : list ){
            if (item.matches("\\d+")){//比配多位数
                stack.push(item);
            }else {
                num2 = Integer.parseInt(stack.pop());
                num1 = Integer.parseInt(stack.pop());
                if (item.equals("*")){
                    res = num1 * num2;
                }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 res;
    }
    public static List<String> getList(String suffixExpression){
        List<String> list = new ArrayList<>();
        String[] str = suffixExpression.split(" ");
        for(String value : str){
            list.add(value);
        }
        return list;
    }
}
class Operation{

    private static int ADD = 1;
    private static int SUB = 1;
    private static int MUL = 2;
    private static int DEL = 2;


    public static int getValue(String operation){

        int res = 0;
        if(operation.equals("*")){
            res = MUL;
        }else if (operation.equals("/")){
            res = DEL;
        }else if (operation.equals("+")){
            res = ADD;
        }else if (operation.equals("-")){
            res = SUB;
        }else {
            System.out.println(operation);
            System.out.println("符号错误---");
        }
        return  res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值