中缀表达式求值的思路分析与代码实现

一、问题与解决办法

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;
    }

}

三、运行结果

posted @ 2020-05-11 22:51  风和日暖  阅读(530)  评论(0编辑  收藏  举报