栈的应用——四则表达式求值

假如现在设计一个计算器,接收用户输入,计算相应结果并输出。当用户输入为“9 + (3 - 1) * 3 + 10 / 2”时,你怎么设计使其能够输出正确的结果“20”?

后缀表达式

上述表达式中,由于我们是一个一个数字和符号输入给程序的,故如何让程序知道运算优先级是个问题(比如,程序怎么知道要先算括号里面的内容)。

我们可以通过将上面正常的表达式(中缀表达式)转换为后缀表达式,然后经过相应的操作即可获得最终结果“20”。具体的后缀表达式为:“9 3 1 - 3 * + 10 2 / +”。由于其所有的符号都在要运算的数字的后面,故为后缀表达式。

转换规则:从左到右遍历表达式的每个数字和符号,若是数字就输出,成为后缀表达式的一部分;若为符号,则判断其与栈顶符号的优先级,是“)”或优先级不高于栈顶符号,则栈顶元素依次出栈并输出(括号不必写入输出),并将当前符号进栈,一直到最终输出后缀表达式为止。最后将栈中所有元素依次出栈。

举例: 假设输入表达式为“9 + ( 3 - 1) * 3 + 10 / 2”。

  1. 遍历表达式,得到第一个元素为“9”,根据规则(数字直接输出),则输出“9”。输出为:9
  2. 第二个元素为“+”,此时栈为空,故将“+”进栈。输出为:9
    在这里插入图片描述
  3. 接着遍历,第三个元素是“(”,则进栈。输出为:9
    在这里插入图片描述
  4. 接下来的是数字“3”,直接输出。输出为:9 3
  5. 然后是“-”,进栈。输出为:9 3
    在这里插入图片描述

6.数字“1”,直接输出。输出为:9 3 1
7.接下来是“)”,注意,根据规则,栈顶符号依次出栈,直到“(”出栈为止。输出为:9 3 1 -
在这里插入图片描述

8.接下来是“*”,由于乘法的优先级高于加法,故进栈。输出为:9 3 1 -
在这里插入图片描述

9.数字“3”,直接输出。输出为:9 3 1 - 3
10.接下来是“+”,由于加法的优先级低于乘法,则“*”出栈。出栈后,栈顶元素此时为最先进去的“+”,外面的“+”和里面的“+”优先级相等,根据规则(外面符号的优先级不高于栈顶符号,故满足要求),则里面的“+”出栈。此时栈为空,则外面的“+”进栈。输出为:9 3 1 - 3 * +
在这里插入图片描述

11.接着输出数字“10”。输出为:9 3 1 - 3 * + 10
12.接着为“/”,由于除法的优先级高于加法,故进栈。输出为:9 3 1 - 3 * + 10
在这里插入图片描述

13.最后一个为数字“2”,直接输出。输出为:9 3 1 - 3 * + 10 2
14.最后所有元素依次出栈,则输出为:9 3 1 - 3 * + 10 2 / +,即为后缀表达式。

Java代码:输入为9+(3-1)*3+10/ 2,输出为9 3 1 - 3 * + 10 2 / +

public class Transfer {
/*中缀表达式转后缀表达式*/

    public static void main(String[] args) {

        Stack t = new Stack();  //初始化一栈
        Scanner s = new Scanner(System.in);

        System.out.println("请输入表达式:");
        String str = s.next();
        char[] c = str.toCharArray();  //将输入的字符串表达式转成字符数组


        for(int i = 0;i < c.length;i++){

            if(c[i] >= '0' && c[i] <= '9'){  //判断是否为数字字符
                String c1 = String.valueOf(c[i]);  //将c[i]转成字符串类型
                int result = Integer.parseInt(c1);  //再将字符串类型的数字转成整型
                while(i < c.length - 1 && c[i+1] >= '0' && c[i+1] <= '9') {
                    /*判断数字是否为两位或多位数字,若是则按照上面方法将其转为整型,
                      并依次乘10转成真正的数字,并直接输出。例如:23。c[i]=2,c[i+1]=3,
                      将其都转为数字后,2*10+3=23。*/
                        String c2 = String.valueOf(c[i + 1]);
                        int c3 = Integer.parseInt(c2);
                        result = result * 10 + c3;
                        i = i + 1;
                }
                System.out.println(result);
            }else if(c[i] == ')'){  //若为),则出栈,出到(出来为止
                char a = (char) t.pop();
                while (a != '('){  //输入为右括号,出栈,直到左括号出现
                    System.out.println(a);
                    a = (char)t.pop();
                }
            }else if(c[i] == '+' || c[i] == '-'){  //输入为+-
                if(t.empty()){ // 栈若为空,则直接进栈
                    t.push(c[i]);
                }else {
                    do{
                        char p = (char)t.pop();  //先取出栈顶元素
                        if(p == '('){
                            t.push(p);   //如果栈顶元素是(,则再把它放进去
                        }else{
                            System.out.println(p);  //+-的优先级低于*/,若栈顶为*/,则出栈
                        }
                    }while (!t.empty() && '(' != (char)t.peek()); //栈非空且栈顶元素不是(
                    t.push(c[i]);
                }
            }else if('*' == c[i] || '/' == c[i] || '(' == c[i]){  //*/(优先级高于任何,进栈
                t.push(c[i]);
            }else{
                System.out.println("输入错误");
            }
        }
        while (!t.empty()){
            System.out.println(t.pop());  //最后将所有元素弹出
        }
    }
}


表达式计算

规则: 从左到右遍历后缀表达式,若是数字则进栈,若是符号则将栈顶的两个数字出栈,进行计算后将计算结果入栈。最后栈中存的数字即为结果。

举例: 输入后缀表达式为:9 3 1 - 3 * + 10 2 / +

  1. 前面三个均为数字,故都进栈。
    在这里插入图片描述

  2. 接下来为“-”,故将栈顶两个元素(1,3)出栈,3-1=2,入栈。
    在这里插入图片描述

  3. 接着是数字“3”,进栈。
    在这里插入图片描述

  4. 后面是“*”,则3和2出栈计算,结果6进栈。
    在这里插入图片描述

  5. 接着是“+”,则6和9出栈计算,结果为15,进栈。
    在这里插入图片描述

  6. 接着是数字10和2,进栈。

  7. 接下来是“/”,则2和10出栈计算,得到5,进栈。
    在这里插入图片描述

  8. 最后是“+”,5和15出栈,得到20,即为开头所求结果。

Java代码:输入为9,3,1,-,3,*,+,10,2,/,+ 输出为20

public class Computer {
/*输入一个后缀表达式,计算(**数与数,数与符号,符号与符号之间用,隔开**)*/
    public static void main(String[] args) {

        Scanner s = new Scanner(System.in);
        Stack t = new Stack();
        System.out.println("请输入后缀表达式:");
        String str = s.next();
        char[] c = str.toCharArray();

        for (int i = 0; i < c.length; i++) {

            if(c[i] == ','){
                continue;
            }else if(c[i] >= '0' && c[i] <= '9'){
                /*同Transfer的方法,判断一个数字为几位,并入栈*/
                String c1 = String.valueOf(c[i]);
                int result = Integer.parseInt(c1);
                while(i < c.length - 1 && c[i+1] >= '0' && c[i+1] <= '9') {
                    String c2 = String.valueOf(c[i + 1]);
                    int c3 = Integer.parseInt(c2);
                    result = result * 10 + c3;
                    i = i + 1;
                }
                t.push(result);
            /*加减乘除均将栈顶的两个元素出栈并进行相应计算*/
            }else if('+' == c[i] ){
                int a1 = (int)t.pop();
                int a2 = (int)t.pop();
                int a3 = a2 + a1;
                t.push(a3);
            }else if('-' == c[i] ){
                int a1 = (int)t.pop();
                int a2 = (int)t.pop();
                int a3 = a2 - a1;
                t.push(a3);
            }else if('*' == c[i] ){
                int a1 = (int)t.pop();
                int a2 = (int)t.pop();
                int a3 = a2 * a1;
                t.push(a3);
            }else if('/' == c[i] ){
                int a1 = (int)t.pop();
                int a2 = (int)t.pop();
                int a3 = a2 / a1;
                t.push(a3);
            }else{
                System.out.println("输入错误");
            }
        }
        System.out.println(t.pop());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值