中缀转后缀
运算符优先级:
( > ^ > * / > + - > )
^为幂运算,例如
x
3
x^3
x3
左括号(
优先级最高,大于幂运算^
,大于乘除 * \
,大于加减+ -
,右括号优先级最低,遇到右括号)
时,弹出优先级大于等于右括号的所有运算符,即弹出(
前的所有运算符以及左括号(
(左括号不存入postfix数组)
实现步骤
- 遇到操作数:直接存入postfix数组
- 遇到界限符:遇到
(
直接入栈,遇到)
,依次弹出栈内运算符并加入后缀表达式,直到遇见(
为止,(
不加入后缀表达式中 - 遇到运算符:若栈空直接加入,栈非空则先弹出栈内优先级大于或等于当前运算符的所有运算符,最后将当前运算符存入栈
- infix遍历结束后,若栈S非空,则依次弹出并存入postfix
我们以例子来帮助理解:
求中缀表达式12+3*5+(2+10)*5的后缀表达式:(运算符与操作数之间以空格隔开)
S栈(底 → \rightarrow →顶) | postfix数组 | 操作 |
---|---|---|
12 | 操作数直接存入postfix数组 | |
+, | 12 | 若栈空直接加入 |
+, | 12 3 | 操作数直接存入postfix数组 |
+,* | 12 3 | +<*,栈顶不弹出 |
+,* | 12 3 5 | 操作数直接存入postfix数组 |
+ | 12 3 5 * + | 按顺序比较并弹出栈内所有 ≥ \geq ≥的运算符。* ≥ \geq ≥+,+ ≥ \geq ≥+。故都弹出,最后压入+ |
+,( | 12 3 5 * + | 遇到( 直接入栈 |
+,( | 12 3 5 * + 2 | 操作数直接存入postfix数组 |
+,(,+ | 12 3 5 * + 2 | +<(,栈顶不弹出 |
+,(,+ | 12 3 5 * + 2 10 | 操作数直接存入postfix数组 |
+ | 12 3 5 * + 2 10 + | 遇到) ,依次弹出栈内运算符并加入后缀表达式,直到遇见( 为止,( 不加入后缀表达式中 |
+,* | 12 3 5 * + 2 10 + | +<*,栈顶不弹出 |
+,* | 12 3 5 * + 2 10 + 5 | 操作数直接存入postfix数组 |
12 3 5 * + 2 10 + 5 * + | 栈S非空,则依次弹出并存入postfix |
代码易错点
5. 处理负数与减号冲突的问题,用空格隔开,与数字无间隔的即为负数的符号,有间隔的为运算符减号
6. 输入数字不止一位,比如12,20,2003 。在for循环内用while解决,若当前字符与下一字符均为数字时,进入while循环,不断将字符读入postfix,直至下一字符不为数字跳出循环
输入样例1
4+2*3-10/5
输出结果
4 2 3 * + 10 5 / -
输入样例2
12+3*5+(2+10)*5
输出结果
12 3 5 * + 2 10 + 5 * +
代码实现
#include<bits/stdc++.h>
#define MaxSize 20
typedef struct S1 { //转换用
char data[MaxSize] = {0};
int top;
} SqStack;
void InitStack(SqStack &S) {
S.top = -1;
}
void change(char infix[MaxSize], char postfix[MaxSize]) { //中缀转后缀
SqStack S;
InitStack(S);
int i, j;
for (i = 0, j = 0; i < strlen(infix); i++) {
if (isdigit(infix[i])) { //若为操作数,直接存入
while (isdigit(infix[i]))
postfix[j++] = infix[i++];
postfix[j++] = ' ';
}
if (infix[i] == '(') { //若为左界限符,存入栈
S.data[++S.top] = infix[i]; //'('存
}
if (infix[i] == ')') { //若为右界限符,开始向右扫描
while (S.data[S.top] != '(') {
postfix[j++] = S.data[S.top--];
postfix[j++] = ' ';
if (S.data[S.top] == '(') { //'('不存
S.top--;
break;
}
}
}
if (infix[i] == '+' || infix[i] == '-' || infix[i] == '*' || infix[i] == '/') { //若为运算符
if (infix[i] == '+' || infix[i] == '-') {
while (1) { //弹出优先级高于或等于当前运算符的所有运算符
if (S.data[S.top] == '(' || S.top == -1) {
break;
}
postfix[j++] = S.data[S.top--];
postfix[j++] = ' ';
}
S.data[++S.top] = infix[i]; //最后存入当前运算符
} else if (infix[i] == '*' || infix[i] == '/') {
while (1) {
if (S.data[S.top] == '(' || S.data[S.top] == '+' || S.data[S.top] == '-' || S.top == -1) {
break;
}
postfix[j++] = S.data[S.top--]; //依次存入输出数组
postfix[j++] = ' ';
}
S.data[++S.top] = infix[i]; //最后存入当前运算符
}
}
}
while (S.top != -1) {
postfix[j++] = S.data[S.top--];
postfix[j++]=' ';
}
for(int i=0;i<j;i++)
printf("%c",postfix[i]);
}
int main() {
float pre, last;
char infix[MaxSize] = {0};
char postfix[MaxSize] = {0};
printf("请输入表达式: ");
scanf("%s", infix);
change(infix, postfix);
return 0;
}