zoukankan      html  css  js  c++  java
  • 中缀表达式求值的思路分析与代码实现

    一、问题与解决办法

    1.问题

    ​ 输入一个任意给定的合理包含四则运算的表达式字符串,求解出其结果;

    ​ 例如:1)“7*2*2-5+1-5+3-4

    ​ 求解出结果为:18

    2.思路

    1. 设置两个栈,一个数字栈numStack,用于存储表达式中涉及到的数字,operatorStack用于存储表达式中涉及到的运算符
    2. 逐个字符分析表达式,直到全部字符都已分析完
      1. 若当前字符为数字,则判断是否后续字符也为数字,若为数字则进行拼接,直到下一个数字为运算符为止,此时将拼接好的多位数字压入数字栈中。(如果已经是最后一个字符则直接压入栈)
      2. 若当前字符为算数运算符
        1. 如果运算符栈为空则直接压入栈中
        2. 运算符不为空,则对运算符优先级进行判断
          1. 如果当前运算符优先级大于等于栈顶运算符则直接压入栈中
          2. 如果优先级低于栈顶运算符,则,从数字栈中取出两个数据,将当前栈顶运算符弹出进行运算,将结果压入数字栈中,将当前运算符压入运算符栈中。
    3. 此时数字与运算符都已经压入栈中,此时运算符栈中均为优先级相同的运算符,需要进行收尾操作,如果运算符栈不为空,则依次从数字栈中弹出两个数据,与当前栈顶的运算符进行运算。将结果压入数字栈中。最后数字栈中的数字就是所要求解的结果。

    二、代码实现

    所用的数据结构栈:

    class CalculatorStack {
    
        private int maxSize;//栈的容量
        private int top;//栈顶
        private int [] data;//用来存放数据的区域
    
        public CalculatorStack(int maxSize){
            top=-1;
            this.maxSize=maxSize;
            data=  new int[maxSize];
        }
        public void push(int obj){
            if (isFull()){
                System.out.println("栈已满");
                return;
            }
            data[++top]=  obj;
        }
        public int pop(){
            if (isEmpty()){
                throw new RuntimeException("栈为空");
            }
            return data[top--];
        }
        public int peek(){
            if (isEmpty()){
                throw new RuntimeException("栈为空");
            }
            return data[top];
        }
        public boolean isEmpty(){
            return top==-1;
        }
    
        public boolean isFull(){
            return top==maxSize-1;
        }
    
    
    
        //用来判断该字符是否是运算符
        public boolean isOperator(char val){
            return val=='+' ||val=='-' ||val=='*' ||val=='/' ;
        }
    
        /**
         *
         * @param oper  待判断的运算符
         * @return 运算符的优先级
         */
        public int getPriority(char oper){
            if (oper=='/' ||oper=='*')
                return 1;
            else if (oper=='+'||oper=='-')
                return 0;
            else
                return -1;//假定表达式只有四则运算
        }
    
        /**
         *
         * @param num1 先出栈的数据
         * @param num2 后出栈的数据
         * @param oper  运算符
         * @return
         */
        public int calculate(int num1,int num2,int oper){
            int res =0;//用于存放计算结果
            switch (oper){
                case '+':
                    res=num1+num2;
                    break;
                case '-':
                    res=num2-num1;
                    break;
                case '*':
                    res=num1*num2;
                    break;
                case '/':
                    res=num2/num1;
                    break;
            }
            return res;
        }
    }
    

    具体算法:

    public class Calculator {
    
        public static void main(String[] args) {
            Calculator cal = new Calculator();
            System.out.println(cal.Calculate("7*2*2-5+1-5+3-4"));//问题是不能处理多位数据
        }
    
        public int Calculate(String expression){
            CalculatorStack numStack = new CalculatorStack(12);//数字栈
            CalculatorStack operStack =new CalculatorStack(12);//符号栈
            int res = 0;//存放结果
            int num1 = 0;//存放先弹出的数字
            int num2 = 0;//存放后弹出的数字
            String tempNum = "";//用于拼接多位数字
            int oper =0;//存放弹出的运算符
            int index = 0;//扫描表达式的游标
            char ch=' ';//保存扫描得到的字符
            char [] expre= expression.toCharArray();
            while(true){
                //1.获取当前的字符
                ch = expre[index];
                //2.判断字符类型
                if (operStack.isOperator(ch)){//若为运算符
                    //判断符号栈中是否为空,为空进栈
                    if (operStack.isEmpty()){
                        operStack.push(ch);
                    }else{//不为空比较优先级,优先级高,入栈
                        if (operStack.getPriority((char) operStack.peek())<operStack.getPriority(ch)){
                            operStack.push(ch);
                        }else{//待入栈算符优先级低于栈顶元素,开始计算
                            num1=numStack.pop();
                            num2=numStack.pop();
                            oper=(char)operStack.pop();
                            res = operStack.calculate(num1,num2,oper);//进行计算
                            numStack.push(res);
                            operStack.push(ch);
                        }
                    }
                }else {//若为数字则应查看下一位是否也是数
                    tempNum+=ch;
                    if (index==expre.length-1){
                        numStack.push(Integer.parseInt(tempNum));
                    }
                    else if (operStack.isOperator(expre[index+1])){
                        numStack.push(Integer.parseInt(tempNum));
                        tempNum="";
                    }
                }
                index++;
                if (index>=expre.length){
                    break;
                }
            }
            //上述步骤仅代表字符串扫描完毕,可能仍存在剩余
            while (true){
                if (operStack.isEmpty()){
                    break;
                }
                num1=numStack.pop();
                num2=numStack.pop();
                oper=(char)operStack.pop();
                res = operStack.calculate(num1,num2,oper);//进行计算
                numStack.push(res);
            }
            return  res;
        }
    
    }
    

    三、运行结果

  • 相关阅读:
    explicit for ctors taking more than one argument
    Python 的 encode 和 decode
    Tripwire配置和运行
    man twadmin
    Tripwire策略说明
    Tripwire安装
    [部分翻译] tripwire(8)
    snort-2.9.3.1安装
    [转载] snort中文手册
    wireshark_1.2.11安装
  • 原文地址:https://www.cnblogs.com/polary/p/12872841.html
Copyright © 2011-2022 走看看