8、栈-利用栈实现简单的计算器

来源:https://www.bilibili.com/video/BV1B4411H76f?p=33

一、思路

1、拿到一个表达式,当前默认只包含 加减乘除 。利用一个index参数遍历整个表达式,得到每一个数值和运算符。

2、设定两个栈,一个是存储数据的栈【数据栈】,另一个用来存储符号【符号栈】

3、如果当前遍历表达式得到的是一个数据,直接入【数据栈】

4、如果当前遍历表达式得到的是一个符号,分析一下【符号栈】的情况

  4.1、【符号栈】为空,直接入栈

  4.2、【符号栈】有操作符,比较当前符号与【符号栈】顶部符号的优先级,当前符号优先级比较低时,从【数据栈】pop两个数据,从【符号栈】pop一个符号,进行运算,得到的结果加入到【数据栈】,之后将当前遍历到的符号加入到【符号栈】。

  4.3、当前遍历到的符号优先级比较高时,当前符号直接入【符号栈】

5、扫描完成,顺序从【数据栈】和【符号栈】pop出内容进行运算,得到结果。

二、实现

1、首先要在原有的数组模拟栈的类中加入一个数据计算的方法。注意:出栈是先入的后出,所以减法和除法要num2在前num1在后。

 1     /**
 2      * 计算
 3      * @param num1 第一个数据
 4      * @param num2 第二个数据
 5      * @param oper 计算符号
 6      * @return
 7      */
 8     public int cal(int num1, int num2, int oper){
 9         int res = 0;
10         switch (oper){
11             case '+':
12                 res = num1 + num2;
13                 break;
14             case '-':
15                 res = num2 - num1;
16                 break;
17             case '*':
18                 res = num1 * num2;
19             case '/':
20                 res = num2 / num1;
21         }
22         return res;
23     }

测试

1         System.out.println(numStack.cal(1, 2, '+'));
2         System.out.println(numStack.cal(1, 2, '-'));
3         System.out.println(numStack.cal(1, 2, '*'));
4         System.out.println(numStack.cal(1, 2, '/'));

结果

3
1
2
2

这里犯了一个错误,开始执行的时候结果错才发现的,漏掉了break,要记住

1             case '*':
2                 res = num1 * num2;
3                 break;
4             case '/':
5                 res = num2 / num1;
6                 break;

 

2、因为需要比较符号的优先级,而且当遍历到的计算符号优先级高时直接入栈,所以之前的符号不能出栈,只能获取,需要一个获取栈顶内容的方法,还需要一个获取符号优先级的方法

 1     //获取栈顶的元素
 2     public int peek(){
 3         return arr[top];
 4     }
 5 
 6     //获取当前符号的优先级,返回值越大优先级越高
 7     public int properties(int oper){
 8         if(oper == '+' || oper == '-'){
 9             return 1;
10         }else if (oper == '*' || oper == '/'){
11             return 2;
12         }else {
13             return -1;//没有这个符号
14         }
15     }

3、遍历表达式的时候,还需要一个判断当前是数据还是计算符号的方法,因为不能保证这个数据是几位的。

1     public boolean isOper(int val){
2         return val == '+' || val == '-' || val == '*' || val == '/';
3     }

4、在主程序进行计算

 1     public static void main(String[] args) {
 2         ArrayStack2 numStack = new ArrayStack2(10);//数据栈
 3         ArrayStack2 operStack = new ArrayStack2(10);//符号栈
 4         String expression = "30+2*6-2";//表达式
 5 
 6         int index = 0;
 7         int num1 = 0;
 8         int num2 = 0;
 9         int oper = 0;
10         char ch = ' ';//从表达式扫描出的内容
11         String keepNum = "";//如果是多位数,用于拼接
12 
13         int res = 0;
14 
15         while (true){
16             //取出位于index的内容
17             ch = expression.substring(index,index + 1).charAt(0);
18 
19             if(operStack.isOper(ch)){
20                 //如果是一个符号的话
21                 if(operStack.isEmpty()){
22                     //如果【符号栈】为空,符号入栈
23                     operStack.push(ch);
24                 }else {
25                     //【符号栈】不为空,看下优先级
26                     if(operStack.properties(ch) > operStack.properties(operStack.peek())){
27                         //当前的符号优先级大于【符号栈】顶部符号的优先级,直接入栈
28                         operStack.push(ch);
29                     }else {
30                         //当前的符号优先级小于等于【符号栈】顶部符号的优先级
31                         num1 = numStack.pop();
32                         num2 = numStack.pop();
33                         oper = operStack.pop();
34                         res = numStack.cal(num1,num2,oper);
35                         numStack.push(res);
36                         operStack.push(ch);
37                     }
38                 }
39             }else {
40                 //如果是一个数据的话,看一下,下一个是不是还是数据
41                 keepNum += ch;//先把当前的数据加入到keepNum
42                 if(index == expression.length() - 1){
43                     //已经走到最后一个位置了,下面没有东西了
44                     numStack.push(Integer.parseInt(keepNum));
45                 }else {
46                     if (operStack.isOper(expression.substring(index + 1,index + 2).charAt(0))){
47                         //下面是一个符号,需要把当前的数据直接加入栈,然后清空keepNum
48                         numStack.push(Integer.parseInt(keepNum));
49                         keepNum = "";
50                     }
51                 }
52             }
53             //保证循环运行下去
54             index++;
55             //循环结束的条件,index从0开始,等于就相当于没有内容了
56             if (index >= expression.length()){
57                 break;
58             }
59         }
60 
61         //全部入栈之后,将栈内的元素依次计算
62         while (true){
63             if (operStack.isEmpty()){
64                 break;
65             }else {
66                 num1 = numStack.pop();
67                 num2 = numStack.pop();
68                 oper = operStack.pop();
69                 res = numStack.cal(num1,num2,oper);
70                 numStack.push(res);
71             }
72         }
73         System.out.println("计算结果为:"+res);
74 
75 
76     }

结果

计算结果为:40

 

你可能感兴趣的:(8、栈-利用栈实现简单的计算器)