0%

栈实现中缀表达式

栈实现中缀表达式

👉目的:实现计算一个计算式如(5 + 10 * 2 + 20 / 2)🕵️‍♂️🕵️‍♂️

👉思路:

  1. 通过一个 index 值(索引),来遍历我们的表达式
  2. 如果我们发现是一个数字, 就直接入数栈🗑🗑
  3. 如果发现扫描到是一个符号, 就分如下情况
    (1) 如果发现当前的符号栈为空,就直接入栈🗑🗑
    (2) 如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符, 就需要从数栈中pop出两个数,在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈🗑🗑,然后将当前的操作符入符号栈, 如果当前的操作符的优先级大于栈中的操作符, 就直接入符号栈.🗑🗑
  4. 当表达式扫描完毕,就顺序的从数栈和符号栈中pop出相应的数和符号,并运行.
  5. 最后在数栈只有一个数字,就是表达式的结果

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
System.out.println("请输入需要计算的表达式:");
Scanner scanner = new Scanner(System.in);
String expression1 = scanner.nextLine();
//String expression1 = "5 + 10 * 2 + 20 / 2";
//将全部空格替换掉
String expression = expression1.trim();
//先创建两个栈,
ArrayStack2 numStack = new ArrayStack2(100);
ArrayStack2 operStack = new ArrayStack2(100);

//定义相关变量
int index = 0; // 用于扫描
int num1 = 0;
int num2 = 0;
int oper = 0;
int res = 0;
char ch = ' '; //将每次扫描得到的char保存到ch
String keepNum = ""; //用于拼接多位数
//开始while循环的扫描expression
while (true) {
//依次得到expression 的每一个字符
ch = expression.substring(index, index + 1).charAt(0);
//判断字符是数字还是运算符,然后做相应的处理;
if ( operStack.isOper(ch)) { //如果是运算符
//判断当前符号栈是否为空
if (!operStack.isEmpty()){
//如果如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符,
// 就需要从数栈中pop出两个数,在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,
// 然后将当前的操作符入符号栈
if (operStack.priority(ch) <= operStack.priority(operStack.peek())) {
num1 = numStack.pop();
num2 = numStack.pop();
oper = operStack.pop();
res = numStack.cal(num1, num2, oper);
//把运算的结果入数栈
numStack.push(res);
//然后将当前操作符入符号栈
operStack.push(ch);
} else {
//如果当前的操作符的优先级大于栈中的操作符, 就直接入符号栈.
operStack.push(ch);
}
}else {
//如果为空直接入栈
operStack.push(ch);
}

} else {
// 如果我们发现是一个数字, 就直接入数栈
//numStack.push(ch - 48);
//1、当处理多位数时,不能发现一个数就立即入栈, 因为它可能是多位数
//2、在处理数时,需向expression的表达式的index 后再看一位, 如果是数字继续扫描,是符号才入栈
//3、定义字符串变量用于拼接
//处理多位数
keepNum += ch;
if (index == expression.length() - 1) {
numStack.push(Integer.parseInt(keepNum));
} else {
//判断下一个字符是不是数字,如果是数字继续扫描, 是符号入栈
//只是看后一位,不用index++
if (operStack.isOper(expression.substring(index + 1, index + 2).charAt(0))) {
//如果后一位是运算符, 则入栈keepNum
numStack.push(Integer.parseInt(keepNum));
//注意清空keepNum !!!
keepNum = "";
}
}


}
//让index + 1, 判断是否扫描到expression结尾
index++;
if (index >= expression.length()) {
break;
}
}
//当表达式扫描完毕,就顺序的从 数栈和符号栈中pop出相应的数和符号,并运行.
while (true) {
//如果符号栈为空,则计算到最后的结果,数栈中只有一个结果
if (operStack.isEmpty()) {
break;
} else {
num1 = numStack.pop();
num2 = numStack.pop();
oper = operStack.pop();
res = numStack.cal(num1, num2, oper);
//把运算的结果入数栈
numStack.push(res);
}
}
//最后在数栈只有一个数字,就是表达式的结果
System.out.println("表达式" + expression1 + " = " + numStack.pop());
}
}

//定义一个ArrayStack栈
class ArrayStack2 {
private int maxSize; //栈的大小
private int [] stack; //数组模拟栈,数据就放在该数组
private int top = -1; //top表示栈顶

public ArrayStack2(int maxSize) {
this.maxSize = maxSize;
stack = new int[maxSize];
}

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

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

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

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

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

//遍历栈,遍历时,需要从栈顶开始显示数据
public void list() {
if (isEmpty()) {
System.out.println("栈空");
return;
}
for (int i = top; i >= 0; i--) {
System.out.println("stack[" + i + "] = " + stack[i]);
}
}

//返回运算符的优先级, 优先级自己确定,优先级使用数字表示
//数字越大,则优先级就越高
public int priority(int oper) {
if (oper == '*' || oper == '/') {
return 1;
} else if (oper == '+' || oper == '-') {
return 0;
} else {
return -1; //假定目前的表达式只有+, -, *, /
}
}

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

//计算方法
public int cal(int num1, int num2, int oper) {
int res = 0; // res用于存放计算的结果
switch (oper) {
case '+':
res = num1 + num2;
break;
case '-':
res = num2 - num1; // 注意返回顺序
break;
case '*':
res = num1 * num2;
break;
case '/':
res = num2 / num1;
break;
default:
break;
}
return res;
}

}

结果展示:

1
2
3
请输入需要计算的表达式:
5 + 10 * 2 + 20 / 2
表达式5+10*2+20/2 = 35

加油!😘😘🎸🎸

北以晨光 wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
------ 本文结束感谢您的阅读 ------