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

栈(stack)
  • 栈是一个先入后出的有序列表。
  • 栈变化的一端是栈顶,不变的一端是栈底。
栈的实现

定义一个top来表示栈顶,初始化为-1
入栈:当有数据入栈,top++,stack[top]=data
出栈:value=stack[top],top- -


综合计算器的实现
计算器设计思路(含小括号)
  1. 先定义两个数组栈。一个用于存储数字,一个用于存储运算符号
  2. 在定义一个index用于读取传进来的算式
  3. 遇到数字,将其传入数字栈
  4. 遇到运算符号向符号栈存入,如果符号栈中没有符号就直接入栈;当遇见左括号‘(’时,直接入栈;当遇见右括号’)'时需要将括号中的算式全部运算完毕,直到遇见左括号,停止运算,将左括号出栈;如果将要入栈的符号优先级大于栈顶的符号直接入栈;如果将要入栈的符号优先级小于或等于栈顶符号,先出栈两个数字,先用要入栈的符号进行运算,将结果入数字栈。
  5. 当读完运算式,将栈中剩余的数字进行依次运算
  6. 运算规则:先出栈两个数字,再出栈一个符号,用后出栈的数字对先出栈的数字进行运算,将结果入数字栈
代码实现
package Stack;

/**
 * 含括号多位加减乘除计算器
 * 运用栈
 */

public class ArrayStackDemo {
    public static void main(String[] args) {
        Calculator cal = new Calculator();
        System.out.println(cal.start("((2+3*2)+1*5)-6/2="));
    }
}
  • 计算器类实现
/**
 * 计算器类(含括号,多位运算)
 */
class Calculator {
    //计算器运行入口,传入算式字符串(需要结尾带等号)
    public int start(String equation) {
        Calculator cal = new Calculator();
        char ch;//用于暂时存放从算式中取出的字符
        int index = 0;//用于标记读取到算式的哪个字符了
        String keepNum = "";//用于组成多位数
        ArrayStack numStack = new ArrayStack(999);//数字栈
        ArrayStack operStack = new ArrayStack(999);//符号栈

        //循环进行算式的拆分读取
        while (true) {
            //读取一个字符
            ch = equation.substring(index, index + 1).charAt(0);
            //先判断读入的是数字还是字符
            if (!cal.isOperation(ch)) {
                //传入的为数字
                //对其进行多位数拼接
                keepNum += ch;
                //当下一位是运算符号的时候
                if (cal.isOperation(equation.substring(index + 1, index + 2).charAt(0))) {
                    //将数字入数字栈
                    numStack.push(Integer.parseInt(keepNum));
                    //格式化keepNum
                    keepNum = "";
                }
            } else if (ch == '=') //当读取到等号时停止读取
            {
                break;
            } else {
                //传入的为运算符号
                //先判断是否为左括号
                if (ch == '(') {
                    //如果为左括号直接入符号栈
                    operStack.push((int) ch);
                } else if (ch == ')')//判断是不是右括号
                {
                    //如果是右括号需要将括号中的多有运算结束,直到遇见左括号
                    while (true) {
                        //当遇见左括号,将左括号出栈,结束括号内的运算
                        if ((char) operStack.showTop() == '(') {
                            operStack.pop();
                            break;
                        } else {
                            //循环进行运算,结果入栈,直到遇到括号
                            numStack.push(cal.count(numStack, operStack));
                        }
                    }
                } else {
                    //为运算符号
                    //先判断栈内是否有符号
                    if (operStack.isEmpty()) {
                        //栈内为空,直接入符号栈
                        operStack.push((int) ch);
                    } else {
                        //栈不为空,判断是否需要进行出栈运算
                        if (cal.comparePriority(ch, operStack)) {
                            //如果优先级大于栈顶符号,直接入栈
                            operStack.push(ch);
                        } else {
                            //如果优先级小于等于栈顶优先级,出栈两个数字,一个运算符进行运算
                            int result = cal.count(numStack, operStack);//获得计算结果
                            //将计算结果入数字栈,当前符号入符号栈
                            numStack.push(result);
                            operStack.push((int) ch);
                        }
                    }
                }
            }
            index++;
        }
        //所有的算式都拆分完成了,运算栈中剩下的数字
        while (true) {
            //判断符号栈是否为空,当符号栈空则表示运算结束,返回结果
            if (!operStack.isEmpty()) {
                //不为空,继续进行计算
                numStack.push(cal.count(numStack, operStack));
            } else {
                //栈空,结束运算,返回结果
                return numStack.pop();
            }
        }
    }


    //判断是不是运算符号(加,减,乘,除,括号,等号)
    public boolean isOperation(char ch) {
        return ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')' || ch == '=';
    }

    //对运算符号进行优先级分类
    //加减=1  乘除=2  左括号=0  右括号=3  等号=-1
    public int classifyOperation(char ch) {
        if (ch == '+' || ch == '-') {
            return 1;
        } else if (ch == '*' || ch == '/') {
            return 2;
        } else if (ch == '(') {
            return 0;
        } else if (ch == ')') {
            return 3;
        } else {
            return -1;
        }
    }

    //对比符号的优先级,ch为读取的当前运算符,operStack为当前符号栈
    //返回正确为当前符号优先级大于栈顶元素优先级;错误为当前符号优先级小于等于栈顶元素优先级;
    public boolean comparePriority(char ch, ArrayStack operStack) {
        Calculator cal = new Calculator();
        //获取当前栈顶运算符号
        char chpop = (char) operStack.showTop();
        //获取栈顶元素优先级
        int priority1 = cal.classifyOperation(chpop);
        //获取当前符号优先级
        int priority2 = cal.classifyOperation(ch);
        if (priority1 < priority2) {
            //正确为当前符号优先级大于栈顶元素优先级
            return true;
        } else {
            //错误为当前符号优先级小于等于栈顶元素优先级
            return false;
        }
    }

    //从数字栈和符号栈自动出栈进行运算
    //num1是先出栈的数字  num2是后出栈的数字  oper是运算符号  numStack是数字栈  operStack是符号栈
    public int count(ArrayStack numStack, ArrayStack operStack) {
        int num1 = numStack.pop();
        int num2 = numStack.pop();
        char oper = (char) operStack.pop();
        switch (oper) {
            case '+':
                return num2 + num1;
            case '-':
                return num2 - num1;
            case '*':
                return num2 * num1;
            case '/':
                return num2 / num1;
            default:
                return 999999999;
        }
    }
}
  • 栈类实现

/**
 * 栈类
 */
class ArrayStack {
    private int stack[];
    private int top;
    private int max;

    //初始化栈
    public ArrayStack(int max) {
        stack = new int[max];
        top = -1;
        this.max = max;
    }

    //判满
    public boolean isFull() {
        return top == max - 1;
    }

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

    //入栈
    public void push(int data) {
        //判满
        if (isFull()) {
            System.out.println("栈满,无法入栈");
            return;
        }
        top++;
        stack[top] = data;
    }

    //出栈
    public int pop() {
        //判空
        if (isEmpty()) {
            System.out.println("栈空");
            new RuntimeException("栈空");
        }
        int value = stack[top];
        top--;
        return value;
    }

    //显示栈
    public void showStack() {
        //从栈顶显示到栈底
        for (int i = top; i >= 0; i--) {
            System.out.println(stack[i]);
        }
    }

    //返回栈顶(栈顶不出栈)
    public int showTop() {
        return stack[top];
    }

}

``
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值