• 栈的应用-逆波兰式


    普通的计算方式,也叫中缀表达式。计算机识别及正确运用需要耗费大量的资源

    如:23+45*2-(8+2)

    计算机想要正确计算出此时的结果需要十分复杂,更何况情况十分多变。

    逆波兰式:又叫做后缀表达式,它能去除中缀表达式的括号。十分符合计算机的计算思维,能极大提高效率

    表达式不能用字符串进行存储,因为这将无法分辨,应用集合(ArrayList,LinkedList存储)

    如:23 45 2 * 8 2 + - +

    那么中缀表达式是如何变成后缀表达式的呢?原则如下:

        1.首先把普通的表达式按照运算符分离出来放在一个集合E中,比如1+2*3 分离后集合里的元素就是 1 + 2 * 3 五个元素

        2.再定义一个集合R(最好是字符串类型的集合,免得后面要转类型),主要是用来存放逆波兰表达式的,还有定义一个堆栈(存储运算符用),最后从左到右遍历集合E     

        3.遍历E的规则如下:

             3.1如果该元素是数字,直接把它添加到集合R中

             3.2否则它肯定是运算符,那么再进行判断

                  3.2.1如果该元素是左括号,或者当时栈为空,那么直接入栈

                  3.2.2如果该元素是右括号,则把栈内的运算符出栈并添加到集合R中,直到遇到第一个左括号结束(左括号也出栈但不添加到R)

                  3.2.3否则该元素是普通的运算符(也就是+-*/之类的),那么用该运算符和栈内的运算符号比较优先级,如果该运算符的优先级比栈内的运算符

                    优先级高 或者 栈为空,则直接入栈,否则把栈内的运算符出栈并添加到R中,再判断下个栈内的运算符优先级,直到遇栈内的运

              算符优先级<=该运算符或者栈为空时再把该运算符入栈

             3.3整个过程完成后,再把栈内的所有运算符出栈并添加到R中

    成功得到后缀表达式,但计算机又是如何通过后缀表达式计算出结果的呢?

    这就需要运用到数据结构栈的特点

      1. 把上面的数值依次压入栈,若遇到运算符,则依次拿出栈顶的两个元素用该运算符进行运算,把结果在压入栈
      2. 直到后缀表达式全部读完,栈顶的数就是运算结果

    上式具体流程就是;

      1. 依次把23 45 2 压入栈
      2. 计算45*2=90,90压入栈
      3. 依次把8 2 压入栈
      4. 计算8+2=10 10压栈
      5. 计算90-10=80 80压入栈
      6. 计算23+80=103 103压入栈
      7. 提取栈顶103

    代码如下;

    import java.util.ArrayList;
    import java.util.ListIterator;
    import java.util.Scanner;
    import java.util.Stack;
    
    public class test {
    
         /** 
         * 将字符串转换为中序表达式 
         */  
        public static ArrayList<String> toZhong(String s){
            ArrayList<String> arrayList=new ArrayList();//存贮中缀表达式
            for(int i=0;i<s.length();i++){
                String str="";
                if(s.charAt(i)<48||s.charAt(i)>57){//48:0,57:9
                    str=str+s.charAt(i);
                    arrayList.add(str);
                }
                else{
                    while(i<s.length()&&s.charAt(i)>=48&&s.charAt(i)<=57){
                        str=str+s.charAt(i);
                        i++;
                    }
                    arrayList.add(str);
                    i--;
                }
            }
            return arrayList;
        }
    ---------------------------------------------------------------------------------------
        /*
         * 把中缀表达式转成逆波兰式
         */
        public static ArrayList<String> toNishi(ArrayList<String> list){
            ArrayList<String> arr=new ArrayList();//用表存储逆波兰式
            Stack<String> timeStack=new Stack();//临时存储操作符
            for(String s:list){
                if(s.matches("\d+")){
                    arr.add(s);
                }
                else if(s.equals("(")){
                    timeStack.push(s);
                }
                else if(s.equals(")")){
                    while(!(timeStack.peek().equals("("))){
                        arr.add(timeStack.pop());
                    }
                }
                else{
                    while(timeStack.size()!=0&&getValue(s)<getValue(timeStack.peek())){
                        arr.add(timeStack.pop());
                    }
                    timeStack.push(s);
                }
            }
            while(timeStack.size()!=0){
                arr.add(timeStack.pop());
            }
            return arr;
        }
             public static int getValue(String ss) {  
                    if (ss.equals("+")) {  
                        return 1;  
                    } else if (ss.equals("-")) {  
                        return 1;  
                    } else if (ss.equals("*")) {  
                        return 2;  
                    } else if (ss.equals("\")) {  
                        return 2;  
                    }  
                    return 0;  
                } 
    ------------------------------------------------------------------------------------------
            //计算逆波兰式结果
        public static int jisuan(ArrayList<String> arr){
             Stack<Integer> jieguo=new Stack<Integer>();
             for(String s:arr){
                 if(s.matches("\d+")){
                     jieguo.push(Integer.parseInt(s));
                 }
                 else if(jieguo.size()>=2){
                     Integer a=jieguo.pop();
                     Integer b=jieguo.pop();
                 if(s.equals("+")){
                     jieguo.push(b+a);
                 }
                 else if(s.equals("-")){
                     jieguo.push(b-a);
                 }
                 else if(s.equals("*")){
                     jieguo.push(b*a);
                 }
                 else if(s.equals("//")){
                     jieguo.push(b/a);
                 }
             }
             }
             return jieguo.pop();
        }
    花五年时间成为某个领域的专家
  • 相关阅读:
    C语言编程题
    boost-使用说明
    CButton控件
    sprintf()与sscanf()
    MFC中的几个虚函数
    CProgressCtrl进度条控件实现进度滚动效果
    移动窗口和根据条件查找指定窗口
    VC播放mp3的方法
    CEdit控件[转]
    关于鼠标的一些操作
  • 原文地址:https://www.cnblogs.com/sang-bit/p/10930037.html
Copyright © 2020-2023  润新知