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

Posted polary

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了中缀表达式求值的思路分析与代码实现相关的知识,希望对你有一定的参考价值。

一、问题与解决办法

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

}

三、运行结果

技术图片

以上是关于中缀表达式求值的思路分析与代码实现的主要内容,如果未能解决你的问题,请参考以下文章

20165334 实验五 网络编程与安全

中缀表达式转后缀表达式(Java代码实现)

中缀表达式求值的方法—栈

C语言编一个实现简单的算术表达式求值的代码。

C语言 任意表达式求值。(栈的应用

波兰表达式与逆波兰表达式介绍及中缀表达式转逆波兰表达式代码实现