数据结构——栈实现计算器(中缀表达式)

栈实现综合计算器(中缀表达式)

问题提出:

使用栈实现综合计算器,能够实现输入有一个表达式,计算出来表达式最终结果,支持四则运算

实现思路(图解):

在这里插入图片描述

实现要求:

  1. 先实现一位数的运算
  2. 实现多位数的运算:要判断index下面是否还是一个数字,但是一定一定一定不能够改变index的值

代码:

package cn.littleworm.ArrayExperssion;

/*
            peek(): 显示当前栈顶元素,是显示,不是将这个元素pop出来
            priority(int oper):返回运算符的优先级,优先级由程序员来定
            isOpera(char oper):判断是否是一个运算符
            cal(int num1,int num2,int oper):计算方法
 */

public class ArrayStrack {


    //定义全局属性:栈顶指针
    private int top = -1;
    private int maxsize;
    private int[] stack;

    //创建构造器
    public ArrayStrack(int maxsize){    //maxsize是数组的长度

        this.maxsize = maxsize;
        //创建数组
        stack = new int[this.maxsize];
    }

    //判断栈是否为空
    public boolean isEmpty(){
        return top == -1;
    }

    //判断栈是否已满
    public boolean isFull(){
        return top == maxsize-1;
    }

    //压栈
    public void push(int value){
        //判断是否已满
        if (isFull()){
            System.out.println("栈已满");
            return;
        }
        top++;
        stack[top] = value;
    }

    //弹栈
    public int pop(){
        //判读是否为空
        if (isEmpty()){
            //抛出异常
            System.out.println("栈为空,请先输入数据");
            return 0;
        }
        //用来接收数据
        int value;
        value = stack[top];
        //将top减一
        top--;
        return value;
    }

    //显示栈中数据
    public void showList(){
        //判断栈中是否有数据
        if (isEmpty()){
            System.out.println("栈为空,请先输入数据");
            return;
        }
        //循环遍历
        for (int i=top;i>=0;i--){
            System.out.println(stack[i]);
        }

    }

    //显示栈顶元素,并不是将这个元素pop出去,而是单纯的显示
    public int peek(){
        return stack[top];
    }

    //priority():返回运算符的优先级,优先级由程序员来定,数字越大,优先级越高
    public int priority(int oper){
        if (oper == '*'||oper == '/'){
            return 1;
        }else if (oper == '+'|| oper == '-'){
            return 0;
        }else {
            return -1;
        }
    }

    // isOpera():判断是否是一个运算符
    public boolean isOpera(char opera){
        if (opera == '+'||opera=='-'||opera=='*'||opera=='/'){
            return true;
        }else {
            return false;
        }
    }

    //cal():计算方法
    public int cal(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;
    }

}
package cn.littleworm.ArrayExperssion;


/*
    实现效果:计算表达式:3+4*2-5;(中缀表达式)
        实现思路:
            1、有两个栈,一个用来存放数据,一个用来存放运算符号
            2、有一个index(索引)指针,来遍历我们的表达式
            3、当进行扫描时,如果发现是一个数,那么就直接将数据放到数栈中
            4、如果时一个运算符,那么分成以下几种情况讨论
                1、如果符号栈为空,那么直接进栈
                2、如果符号栈不为空,对符号进行比较又分为两种情况
                    1、如果当前符号,优先级不大于符号栈中符号的优先级,那么就从数栈中pop
                    两个数,从符号栈中pop一个符号,然后进行运算,将运算获得的数据push进
                    数栈中,然后将当前运算符号push进符号栈中
                    2、如果当前符号,优先级大于符号栈中的优先级,直接将符号push进符号栈
            5、当以上步骤进行 完毕之后,依次从数栈和符号栈中取出数据,进行运算,并将结果放到数栈中。
            6、最后数栈中只有一个数据,就是最后运行的结果,符号栈中没有数据


        根据以上思路,对于栈(ArrayStrack)需要增加一下扩展方法
            peek(): 显示当前栈顶元素,是显示,不是将这个元素pop出来
            priority(int oper):返回运算符的优先级,优先级由程序员来定
            isOpera(char oper):判断是否是一个运算符
            cal(int num1,int num2,int oper):计算方法


 */

public class Calcluator {

    public static void main(String[] args) {

        //表达式
        String expression = "7*2+10/3-5";
        //创建两个栈:一个符号栈,一个数栈
        ArrayStrack numStrack = new ArrayStrack(10);
        ArrayStrack operStrack = new ArrayStrack(10);
        //定义相关变量
        int index = 0;  //用于扫描表达式
        int num1 = 0;
        int num2 = 0;
        int oper = 0;
        int res = 0;
        char ch = ' ';  //每次扫描得到的字符都放在ch中
        String keepNum = "";    //用来处理多位数

        while (true){
            //截取表达式字符串,并将截取的字符串转换成为char类型数据
            ch = expression.substring(index,index+1).charAt(0);

            //判断ch是什么,在进行相对应的操作
            if (operStrack.isOpera(ch)){
                //判断符号栈是否为空
                if (operStrack.isEmpty()){
                    //直接将符号push进栈中
                    operStrack.push(ch);
                }else {
                    //如果不为空
                    //比较当前运算符与栈中运算符的优先级
                    if (operStrack.priority(ch)<=operStrack.priority(operStrack.peek())){
                        //如果当前运算符优先级大于栈中运算符优先级
                        //分别从数栈和符号栈中取出两个数和一个运算符
                        num1 = numStrack.pop();
                        num2 = numStrack.pop();
                        oper = operStrack.pop();
                        //进行计算
                        res = numStrack.cal(num1,num2,oper);
                        //将运算的结果压入栈中
                        numStrack.push(res);
                        //将当前的符号压入栈中
                        operStrack.push(ch);
                    }else {
                        operStrack.push(ch);
                    }
                }
            }else { //如果是数字
               // numStrack.push(ch-48);  //注意对照ASCII码表

                /*
                    如果是数字这时又有一个问题:这个数字是一位数字还是多为数字
                    所以这时候需要进行判断:
                        1、向当前index的位置向后看一位,但并不改变index的值,并不改变index的值,并不改变index的值
                        2、如果后面一位是一个运算符,就将数据push进数栈中

                 */
                //将数据拼接到keepNum中
                keepNum+=ch;

                //判断index是否是最后一位,如果是最后一位就没有要判断下一位的必要了
                if (index == expression.length()-1){
                    numStrack.push(Integer.parseInt(keepNum));
                }else {
                    //判断index的下一位是否是运算符
                    if (operStrack.isOpera(expression.substring(index+1,index+2).charAt(0))){
                        //如果是运算符,就将keepNum转成int类型并加到数栈中
                        numStrack.push(Integer.parseInt(keepNum));
                        //一定要清空keepNum,因为不清空下一次会继续拼接
                        keepNum = "";

                    }
                }

            }

            //判断是否到达最后
            if (index>=expression.length()-1){
                break;
            }
            index++;
        }

        //当扫描完毕之后,就按照顺序从数栈和符号栈中取出数据和符号,进行运算
        while (true){
            //当符号栈中的数据为空的时候,就证明运算到了最后,数栈中只有一个数据,就是最终结果
            if (operStrack.isEmpty()){
                break;
            }
            num1 = numStrack.pop();
            num2 = numStrack.pop();
            oper = operStrack.pop();
            res = numStrack.cal(num1, num2, oper);
            //数入栈
            numStrack.push(res);
        }

        //最后将数据从数栈中pop出来
        int pop = numStrack.pop();
        System.out.println(expression+"="+pop);
    }
}
发布了24 篇原创文章 · 获赞 5 · 访问量 2073

猜你喜欢

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