栈与队列 | 常见习题总结(下)

4.模拟计算器 实现四则运算
(1)中缀表达式转后缀表达式
  • 什么是中缀表达式呢?
    我们平时做数学题所列的标准四则运算表达式,例如:“9+(3-1)×3+10÷2” 就是一个中缀表达式
  • 中缀表达式转后缀表达式的结果又是什么样子的呢?
    “9 3 1 - 3 × + 10 2 ÷ +”
  • 栈的作用: 进出运算符号

转换规则:
从左到右遍历中缀表达式的每一个数字和符号,若是数字,直接输出成为后缀表达式的一部分,若是运算符号,首先判断其与栈顶元素的优先级,如果是右括号或是优先级高于栈顶元素(乘除优于加减)的符号,直接入栈,否则,则将栈顶元素依次出栈并输出,并将当前符号入栈,直到栈空即输出后缀表达式为止。

以“9+(3-1)×3+10÷2”为例,挑选其中最复杂的两个步骤进行动图说明:
输出9,“+”入栈,“(” 直接入栈 <优先级最高>,输出3,“-”入栈,下一个符号为“)”,我们需要去找与之对应的左括号“(”,所以栈顶元素依次出栈,直至“(” 出栈为止,即输出“-”。
Alt
输出8,""入栈,输出2,“÷”、“+”依次出栈。
最终后缀表达式的输出结果为:“9 3 1 - 3 × + 10 2 ÷ +”

(2)后缀表达式计算结果
  • 栈的作用: 进出运算数字

转换规则:
从左到右遍历后缀表达式的每个数字和符号,若为数字则进栈,若为符号,则将处于栈顶的两个数字出栈,进行相对应的加减乘除运算,将运算结果入栈,直到栈空得到最终计算结果。

仍然以“9 3 1 - 3 × + 10 2 ÷ +”后缀表达式为例简单描述这个过程:
9、3、1依次入栈,下一符号为“-”,则将3、1出栈进行3-1操作,将结果2入栈,同理继续进行3×2操作,将结果6入栈,直至得到最后结果20,将结果输出。

(3)附代码如下:
class Calculate {
    //获取字符优先级:乘除优先于加减
    private static int getPriority(char value) {
        int result = 0;
        switch (value) {
            case '+':
            case '-':
                result = 1;
                break;
            case '*':
            case '/':
                result = 2;
                break;
        }
        return result;
    }

    //加减乘除运算
    private static int operator(int item1, int item2, char operate) {
        int result = 0;
        switch (operate) {
            case '+':
                result = item2 + item1;
                break;
            case '-':
                result = item2 - item1;
                break;
            case '*':
                result = item2 * item1;
                break;
            case '/':
                result = item2 / item1;
                break;
        }
        return result;
    }
    //中缀表达式转后缀表达式
    public static String infixToPostfix(String str) {  //9+(3-1)*3+10/2
        String result = "";//返回最终结果
        String split = " ";//空格分隔,用来区分数字的位数问题(可能存在多位情况)
        boolean flag = false;//以空格对数据进行分割
        Stack<Character> stack = new Stack<>();//Character类型的stack栈用于存放字符
        for (int i = 0; i < str.length(); i++) {
            char value = str.charAt(i);//获得str字符串中的每个字符
            if(value>='0'&&value<='9'){
                result+=value;
                flag=true;
            }else if(value==')'){//如果是'(',则下一位必然为字符,故无需判断flag
                while (!(stack.peek()=='(')) {
                    result+=stack.pop();
                }
                stack.pop();
            }else{//其他字符
                if(flag==true){
                    result+=split;//以空格分隔数字与字符
                    flag=false;
                }
                //若栈空或运算符为'(',直接入栈
                if (stack.isEmpty()||value=='(') {
                    stack.push(value);
                    continue;
                }
                //否则判断优先级后进行相关操作
                //将优先级高的运算符直接入栈
                if (getPriority(stack.peek()) < getPriority(value)) {
                    stack.push(value);
                } else {//遇到栈顶符号比当前符号优先级高时,一直出栈直至当前符号优先级最高即可
                    while (!stack.isEmpty() && getPriority(stack.peek()) >= getPriority(value)) {
                        result += stack.peek();
                        stack.pop();
                    }
                    //将当前符号入栈操作
                    stack.push(value);
                }
            }
        }
        while (!stack.isEmpty()) {
            result += stack.peek();
            stack.pop();
        }
        return result;
    }
    //后缀表达式计算结果
    public static int cal(String str) {
        str=infixToPostfix(str);
        Stack<Integer> stack = new Stack<>();//Integer类型的stack栈用于存放数字
        for (int i = 0; i < str.length(); ) {
            String subNumber = "";//保存数字
            char value = str.charAt(i);
            if (value == ' ') {
                i++;
                continue;
            }
            if (value >= '0' && value <= '9') {
                while (value >= '0' && value <= '9') {//判断两位数或以上数字
                    subNumber += value;
                    i++;
                    value = str.charAt(i);//当前字符
                }
                stack.push(Integer.valueOf(subNumber));
                if(value==' '){
                    i++;
                }
            } else {
                int item1 = stack.pop();
                int item2 = stack.pop();
                int result=operator(item1,item2,value);
                stack.push(result);
                i++;
            }
        }
        return stack.pop();
    }
}
public class Calculater {
    public static void main(String[] args) {
        Calculate c=new Calculate();
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("请输入要计算的表达式:");
            String str = scanner.next();
            int result = c.cal(str);
//            System.out.println(c.infixToPostfix(str));
            System.out.println("计算结果:" + result);
        }
    }
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值