数据结构——栈(逆波兰计算器)

栈——逆波兰计算器实现(后缀表达式)

实现步骤

  1. 将中缀表达式转换成后缀表达式
  2. 逆波兰表达式的计算方法

一:将中缀表达式转换成后缀表达式

思路和代码将下面一篇博客

中缀表达式转换成后缀表达式

二:计算方法

  1. 创建一个存放结果的栈
  2. 当中缀表达式转换之后存放在list集合中,所以遍历后缀表达式的集合,判断当时数字的时候入栈,当时运算符的时候,先从栈中弹出两个数字,与当前运算符进行运算,然后在九江运算结果压入栈中。
  3. 重复执行,最后在栈中的结果就是表达式计算的最终结果。

三:代码

package cn.littleworm.波兰计数器;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class PolandNotation {

    public static void main(String[] args) {
        String ex = "1+((2+3)*4)-5";
        List<String> list = toInfixExperssionList(ex);
        System.out.println(list);
        List<String> list1 = parseSuffixException(list);
        System.out.println(list1);
        int calclute = calclute(list1);
        System.out.println("计算结果是:"+calclute);

    }

    //首先将中缀表达式显示在list集合中
    public static List<String> toInfixExperssionList(String s){
        /*
            思路:
                1、传过来的是一个表达式字符串
                2、定义一个指针索引,用来遍历表达式
                3、要考虑的一个因素就是,如果数字,判断书是否是多位数

         */
        List<String> list = new ArrayList<>();
        int i = 0;  //定义指针索引
        String keeper;  //用于拼接字符串
        char ch;    //用来接收字符
        do {
            ch = s.charAt(i);
            //判断是否是符号
            if (ch<48||ch>57){  //证明不是数字
                list.add(ch+"");
                i++;
            }else {
                //先将keeper置为空
                keeper = "";
                while (i<s.length()&&(ch=s.charAt(i))>=48&&(ch=s.charAt(i))<=57){
                    keeper+=ch;
                    i++;    //自增
                }
                //加到集合中
                list.add(keeper);
            }

        }while (i<s.length());

        return list;
    }



    /*
        将中缀表达式转换成后缀表达式流程
            1、初始化两个栈,s1用来存放运算符,s2用来存放中间结果(用list集合来代替,比栈更方便)
            2、从左向右遍历集合
            3、当遇到操作数的时候,直接将数据放入s2集合中
            4、当遇到运算符的时候
                1、如果s1符号栈为空,那么直接将运算符压入栈中
                2、如果符号栈不为空,要判断当前符号与栈顶符号的优先级(优先级这里要自己定义)
                   1、如果当前运算符号优先级大于栈顶符号优先级,那么直接加入符号栈
                   2、如果当前运算符号优先级小于等于栈顶符号优先级,那么将符号栈中的运算符号
                      弹出,并加入s2集合中,然后再次比较,就是重复4步骤
            5、当遇到“(”时,直接压入栈中
            6、当遇到“)”时,依次弹出符号栈s1中的运算符,并压入到s2中,直到遇到右括号“(”
               将这一对括号全部丢掉。
            7、重复步骤2到6,直到最后
            8、最后将符号栈中的数据一次弹出,并加入到s2集合中
     */

    //将中缀表达式转换成后缀表达式
    public static List<String> parseSuffixException(List<String> listExc){
        //初始化符号栈
        Stack<String> s1 = new Stack<>();

        //创建一个list集合用来接收中间结果
        List<String> s2 = new ArrayList<>();

        //遍历listExc表达式
        for (String item : listExc) {
            //如果是一个数,直接加入
            if (item.matches("\\d+")){  //这里使用正则表达式,用来匹配多为数字
                s2.add(item);
            }else if (item.equals("(")){
                //如果是左括号,s1直接加入
                s1.push(item);
            }else if (item.equals(")")){
                //如果是左括号,依次弹出符号栈s1中的运算符,并压入到s2中,直到遇到右括号“(”
                // 将这一对括号全部丢掉
                while (!"(".equals(s1.peek())){
                    String pop = s1.pop();
                    s2.add(pop);
                }
                //当执行完上面的循环之后,栈顶指针就是指向左括号,所以要将左括号弹出去
                s1.pop();
            }else {
                //如果是符号
                //现在要判断当前符号的优先级是否小于等于栈顶符号,所以这时需一个比较优先级的方法
                while (s1.size()>0&&Operation.getValue(s1.peek())>=Operation.getValue(item)){
                    String pop = s1.pop();
                    s2.add(pop);
                }

                //如果当前运算符小于或者是符号栈为空
                s1.push(item);
            }

        }
        //当上面的循环都结束了,这时将符号栈中的数据依次pop出,并添加到s2中
        while (s1.size()!=0){
            String pop = s1.pop();
            s2.add(pop);
        }
        return s2;

    }

    //计算表达式
    public static int calclute(List<String> list){
        //创建一个栈
        Stack<String> stack = new Stack<>();

        //遍历集合
        for (String item : list) {
            //判断是数字还是运算符
            if (item.matches("\\d+")){  //使用正则表达式,匹配多为数字
                    //如果是数字,入栈
                stack.push(item);
            }else{
                //如果是运算符,从栈中pop出两个数进行运算,然后将结果在次压入栈中
                int num1 = Integer.parseInt(stack.pop());
                int num2 = Integer.parseInt(stack.pop());
                switch (item){
                    case "+":stack.push((num1+num2)+"");break;
                    case "-":stack.push((num2-num1)+"");break;
                    case "*":stack.push((num1*num2)+"");break;
                    case "/":stack.push((num2/num1)+"");break;
                    default:
                        System.out.println("运算符未找到");break;
                }
            }
        }

        //最后在栈中的数据就是最终结果
        return Integer.parseInt(stack.pop());
    }

}

//获取运算符号的优先级
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;break;
            default:
                System.out.println("不存在这样的运算符");
                break;
        }
        return result;
    }


}

四:结果显示

结果显示

发布了24 篇原创文章 · 获赞 5 · 访问量 2071

猜你喜欢

转载自blog.csdn.net/weixin_43288447/article/details/104006161