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

输入一个字符串类型的表达式,例如:7*2*2-5+1-5+3-3,计算出结果。

1. 思路分析

①通过一个index值(索引),来遍历表达式;

②如果发现是一个数字,就直接入数栈;

③如果发现扫描到是一个符号,就分如下情况;

④如果发现当前的符号栈为空,就直接入栈

⑤如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符,就需要从数栈中pop出两个数,再从符号栈中pop出一个符号,进行运算,将得到的结果入数栈,然后将当前的操作符入符号栈;

⑥如果当前的操作符的优先级大于栈中的操作符,就直接入符号栈;

⑦当表达式扫描完毕,就顺序的从数栈和符号栈中pop出相应的数和符号,并运算;

⑧最后在数栈中只有一个数字,就是表达式的结果。

2. 代码实现

数组实现栈

在我上一篇文章中,写了数组模拟实现栈类ArrayStack,在这个类的其他方法的基础上,再加入以下方法:

//返回运算符的优先级,数字越大,优先级越高
public int priority(int op) {
    //目前只计算+、-、*、/
    if (op == '*' || op == '/') {
        return 1;
    } else if (op == '+' || op == '-') {
        return 0;
    } else {
        return -1;
    }
}

//判断是不是运算符
public boolean isOp(char val) {
    return val == '+' || val == '-' || val == '*' || val == '/';
}

//计算方法
public int cal(int num1, int num2, int op) {
    int res = 0; //计算结果
    switch (op) {
        case '+':
            res = num1 + num2;
            break;
        case '-':
            //用后面的减前面的
            res = num2 - num1;
            break;
        case '*':
            res = num1 * num2;
            break;
        case '/':
            //用后面的除前面的
            res = num2 / num1;
            break;
    }
    return res;
}

//返回当前栈顶的值,但没有出栈
public int peek() {
    return stack[top];
}

在main方法中的其它逻辑:

public static void main(String[] args) {
    String expression = "300+7-4-30";
    //创建两个栈:一个数栈,一个符号栈
    ArrayStack2 numStack = new ArrayStack2(10);
    ArrayStack2 opStack = new ArrayStack2(10);

    int index = 0;//指针
    int num1 = 0;//取出的第一个数
    int num2 = 0;//取出的第二个数
    int op = 0;//取出的当前符号
    int res = 0;//运算出的结果
    char ch = ' ';//保存每次扫描算式得到的结果
    String keepNum = "";//用于拼接多位数

    //遍历expression
    while (true) {
        //使用substring方法得到当前位置的字符,并使用charAt方法把字符串类型转为字符型
        ch = expression.substring(index, index + 1).charAt(0);

        //判断ch是什么
        //如果是运算符
        if (opStack.isOp(ch)) {
            //判断当前的符号栈是否为空
            if (!opStack.isEmpty()) {
                //如果符号栈有符号,将当前符号与栈顶的符号进行比较
                if (opStack.priority(ch) <= opStack.priority(opStack.peek())) {
                    //取出前数栈的后两个数,和符号栈最后面的一个符号
                    num1 = numStack.pop();
                    num2 = numStack.pop();
                    op = opStack.pop();
                    //进行运算
                    res = numStack.cal(num1, num2, op);
                    //把运算结果加入数栈
                    numStack.push(res);
                    //把当前的符号入符号栈
                    opStack.push(ch);
                } else {
                    //优先级大于栈顶的符号,直接入栈
                    opStack.push(ch);
                }
            } else {
                //符号栈为空,直接加入符号栈
                opStack.push(ch);
            }
        } else {
            //处理多位数字时,需要判断下一个字符是不是数字
            keepNum += ch;

            //如果当前的字符是expression的最后一位,则直接入栈
            if (index == expression.length() - 1) {
                //将当前的keepNum转换为int类型加入数栈
                numStack.push(Integer.parseInt(keepNum));
            } else {
                //判断当前位置的后一位是不是数字
                if (opStack.isOp(expression.substring(index + 1, index + 2).charAt(0))) {//如果是运算符
                    //将当前的keepNum转换为int类型加入数栈
                    numStack.push(Integer.parseInt(keepNum));
                    //清空keepNum
                    keepNum = "";
                }
            }
        }
        index++;//指针递增
        if (index >= expression.length()) {
            break;
        }
    }

    //按顺序从数栈和符号栈取出数和符号进行运算
    while (true) {
        //如果符号栈为空,则得到最后的结果
        if (opStack.isEmpty()) {
            break;
        }
        //取出前数栈的后两个数,和符号栈最后面的一个符号
        num1 = numStack.pop();
        num2 = numStack.pop();
        op = opStack.pop();
        //进行运算
        res = numStack.cal(num1, num2, op);
        //把运算结果加入数栈
        numStack.push(res);
    }
    System.out.println("表达式 " + expression + " 结果为 " + numStack.pop());
}

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值