栈实现综合计算器

栈实现综合计算器

输入一个表达式并计算结果。例:3+2*6-2=13

思路分析

  1. 定义一个index指针来遍历表达式

  2. 创建一个数栈、一个符号栈 ;当遍历到的是数字时直接入数栈。

  3. 当遍历到符号栈时,若符号栈为空,则直接入符号栈;若遍历到的符号小于等于栈中符号时,则从数栈中取出两个数,符号栈中取出一个符号进行运算,将运算后的结果入数栈,最后将遍历到的当前符号入符号栈。

  4. 当表达式遍历完毕时,顺序从数栈和符号栈中依次取出

  5. 当数栈中只有一个数字时,就是表达式的结果


代码实现

package 栈;

public class 栈实现计算器功能 {
    public static void main(String[] args) {
        //要计算的表达式
        String expression = "7*2*2-5+1-5+3-4";

        //创建一个遍历指针,一个数栈,一个符号栈
        int index = 0;
        Stack0 numstack = new Stack0(10);
        Stack0 operastack = new Stack0(10);

        //定义需要的变量
        char ch = ' ';//将扫描到的字符保存到ch中
        int num1 = 0;//数字栈中取出的第一个数
        int num2 = 0;//数字栈中取出的第二个数
        int opera = 0;//符号栈中取出的符号
        int res = 0;//运算结果
        String keepnum = " ";//用于拼接多位数

        //利用while循环扫描表达式
        while (true) {
            //依次得到表达式的每一个字符
            ch = expression.substring(index, index + 1).charAt(0);
            //判断ch是什么做相应的处理
            if (operastack.isopera(ch)) {//如果是运算符
                //判断符号栈是否为空
                if (!operastack.isEmpty()) {
                    if (operastack.priority(ch) <= operastack.priority(operastack.peek())) {//若遍历到的符号小于等于栈中符号时
                        // 则从数栈中取出两个数,符号中取出一个符号
                        num1 = numstack.pop();
                        num2 = numstack.pop();
                        opera = operastack.pop();
                        //进行运算,将运算后的结果入数栈,
                        res = numstack.cal(num1, num2, opera);
                        numstack.push(res);
                        //当前符号入符号栈。
                        operastack.push(ch);
                    } else {//如果为空直接入符号栈
                        operastack.push(ch);
                    }
                } else {//如果是数字,直接入数字栈
                    //1、在入栈前需要判断是否为多位数
                    //2、在处理数时,需要向表达式的后面再看一位,如果是数进行扫描,当为符号时入栈
                    //3、定义一个字符串变量,用于拼接。
                    keepnum += ch;//处理多位数
                    //如果ch已经是表达式最后一位,直接入栈
                    if (index == (expression.length() - 1)) {
                        numstack.push(Integer.parseInt(keepnum));
                    } else {//判断下一位是否为数字,如果是数字则继续扫描,如果是符号则入栈
                        if (numstack.isopera(expression.substring(index + 1, index + 2).charAt(0))) {
                            numstack.push(Integer.parseInt(keepnum));
                            //记得入栈以后一定要清空 keepnum清空,不然一直在后面拼接
                            keepnum = " ";
                        }
                    }
                }
                index++;
                if (index >= expression.length() - 1) {
                    break;
                }
            }
            //当表达式扫描完成,顺序从数栈和符号栈中pop出相应的数和符号,并运行。
            while (true) {
                //如果符号栈为空,则计算到最后的结果,数栈中只有一个数字【结果】
                if (operastack.isEmpty()) {
                    break;
                }
                num1 = numstack.pop();
                num2 = numstack.pop();
                opera = operastack.pop();
                res = numstack.cal(num1, num2, opera);
                numstack.push(res);//入栈
            }
            //将数栈中的最后数,pop出,就是结果
            int res2 = numstack.pop();
            System.out.println(res2);
        }
    }
}
    class Stack0 {
        public int[] stack;
        public int maxsize;
        public int top = -1;

        //构造方法
        public Stack0() {
        }

        public Stack0(int maxsize) {
            this.maxsize = maxsize;
            stack = new int[this.maxsize];
        }

        //栈满
        public boolean isfull() {
            return top == maxsize - 1;
        }

        //栈空
        public boolean isEmpty() {
            return top == -1;
        }

        //入栈
        public void push(int num) {
            if (isfull()) {
                System.out.println("栈满");
                return;
            }
            top++;
            stack[top] = num;
        }

        //出栈
        public int pop() {
            if (isEmpty()) {
                throw new RuntimeException("栈空,无数据");
            }
            int value = stack[top];
            top--;
            return value;
        }

        //显示栈
        public void show() {
            if (isEmpty()) {
                System.out.println("栈空");
                return;
            }
            //需要从栈顶开始显示数据
            for (int i = top; i >= 0; i--) {
                System.out.println(stack[i]);
            }
        }

        //返回栈顶值
        public int peek() {
            return stack[top];
        }

        //判断是否为运算符
        public boolean isopera(char ch) {
            return ch == '+' || ch == '-' || ch == '*' || ch == '/';
        }

        //定义符号优先级
        public int priority(int oper) {
            if (oper == '*' || oper == '/') {
                return 1;
            } else if (oper == '+' || oper == '-') {
                return 0;
            } else {
                return -1;
            }
        }

        //定义运算法方法
        public int cal(int num1, int num2, int opera) {
            int res = 0;//用于存放计算的结果
            switch (opera) {
                case '+':
                    res = num1 + num2;
                    break;
                case '-':
                    res = num2 - num1;
                    break;//注意顺序
                case '*':
                    res = num1 * num2;
                    break;
                case '/':
                    res = num2 / num1;
                    break;
                default:
                    break;
            }
            return res;
        }
    }

代码分析

变量定义

定义表达式,字符串类型

定义数字栈,符号栈,遍历指针

定义辅助变量,数字栈取出的数字num1,num2;符号栈取出运算符opera

定义栈类

数组模拟栈:成员变量要有 maxsize表示栈的大小,数组,top栈顶指针;

集合模拟栈:则不用考虑数组的大小,因为集合可以自动扩容。

定义栈的成员方法

是否为空

是否为满

出栈

入栈

栈的显示(从栈顶开始遍历)

返回栈顶元素

是否为运算符

运算符优先级

计算方法

主程序

将字符串表达式转换为每个字符

 ch = expression.substring(index, index + 1).charAt(0);

判断每个字符是否为运算符(符号栈不为空,优先级小于等于栈中优先级,数栈中取数,符号栈中取符号运算,计算结果入数栈,遍历的当前符号入符号栈;否则直接入符号栈)

若符号为数字,需要判断是否为多位数,定义字符串变量keepnum+=ch用来拼接。若为最后一个数字直接入数栈(需要将字符串表达式转换为十进制数),否则判断下一位是否为符号。

if (numstack.isopera(expression.substring(index + 1, index + 2).charAt(0))) {
                            numstack.push(Integer.parseInt(keepnum));
                            //记得入栈以后一定要清空 keepnum清空,不然一直在后面拼接
                            keepnum = " ";
                        }

这时候一个字符的判断已经结束,index++判断下一个字符。这样将表达式遍历以后,顺序从数栈,符号栈中取出;如果符号栈中不为空,则数栈中取数,符号栈中取符号,得到计算结果,存入数栈;若符号栈为空;则得到计算的结果。将结果pop出即可。

posted @ 2021-01-03 19:39  胡木杨  阅读(140)  评论(0)    收藏  举报