![47064672f34cafe1a2b72f28c0634489.png](https://i-blog.csdnimg.cn/blog_migrate/0a2dd343b8306ed2442a5ec499c7b2c0.png)
在表达式求值的过程中,常用到将中缀表达式转化为后缀表达式或前缀表达式的过程
我们常见的表达式形式为中缀表达式,对于简单的中缀表达式可以很容易转化为前缀表达式或后缀表达式
例如,中缀表达式a+b,其前缀表达式为+ab,后缀表达式为ab+
较复杂的表达式则不易直接得出结果,这里我们将通过栈来实现相应的转化
示例表达式:[(A+B)*C]-[E-F]
转化为前缀表达式:
- 先计算A+B,转化为+AB
- +AB作为整体与C运算,转化为*+ABC
- 运算E-F,转化为-EF
- 将*+ABC与E-F都作为整体执行-运算,转化为-*+ABC-EF
转化为后缀表达式:
- 先计算A+B,转化为AB+
- AB+作为整体与C运算,转化为AB+C*
- 运算E-F,转化为EF-
- 将AB+C*与EF-作为整体执行-运算,转化为AB+C*EF--
用栈实现中缀表达式转化为后缀表达式
算法思想
如果检测到数字,则直接加入到后缀表达式中
如果检测到运算符时:
- 若为‘(’,入栈
- 若为‘)’,则依次将栈中的运算符加入后缀表达式,直到出现‘(’,并从栈中删除‘(’
- 若为‘+’,‘-’,‘*’,‘/’
- 栈空,入栈
- 栈顶元素为‘(’,入栈
- 高于栈顶元素优先级,入栈
- 否则,依次弹出栈顶运算符,直到一个优先级比它低的运算符或‘(’为止
遍历完成,若栈非空,依次弹出栈中所有元素
该算法使得栈顶运算符处于较高优先级,并先弹出栈,进入后缀表达式
过程分析
示例:((A+B)*C)-(E-F)
1.连续两个'(',入栈
(当前后缀表达式: )
![3336a7c2aea356b0a7223c07c3141117.png](https://i-blog.csdnimg.cn/blog_migrate/aa1c2e793053ed18b5658b8a86cce238.png)
2.遍历到数字A,加入到后缀表达式
(当前后缀表达式:A)
![42f61d4102e86faf44844c7b10800fc4.png](https://i-blog.csdnimg.cn/blog_migrate/0767afba9f269933d5a842eced7e4193.png)
3.遍历到运算符+,由于栈顶元素为‘(’,直接入栈。
(当前后缀表达式:A)
4.接着遍历数字B,加入到后缀表达式
(当前后缀表达式:AB)
![3a958f93dac186546ad637dc3e60f839.png](https://i-blog.csdnimg.cn/blog_migrate/625a1badd3bc6b38217ac831b3d38e44.png)
5.遍历‘)’,依次将栈中的运算符加入后缀表达式,直到出现‘(’,并删除栈顶的‘(’
(当前后缀表达式:AB+)
注:括号是不会出现在后缀表达式或前缀表达式中的
![d238615928ff78121d24703de4ffc488.png](https://i-blog.csdnimg.cn/blog_migrate/01b62f849c73d1c19c37a72ea2a2ce1b.png)
6.遍历到*,栈顶为‘(’,直接入栈
7.接着遍历数字C,直接加入到后缀表达式中
(当前后缀表达式:AB+C)
![614f061b70b47d5367022c5dd85d7a46.png](https://i-blog.csdnimg.cn/blog_migrate/b5ce8fc144094d87923f9b881dc5f515.png)
8.继续遍历到‘)’,依次将栈中的运算符加入后缀表达式,直到出现‘(’,并删除栈顶的‘(’
【当前后缀表达式:AB+C*】
![c5774aacf367cd5e7c243da5acdc5db3.png](https://i-blog.csdnimg.cn/blog_migrate/611c77ceca6cc5d2a819c7485d6ab08a.png)
9.接着遍历到-,栈空,入栈
【当前后缀表达式:AB+C*】
![ed13a0d57fe77e48f36a21bc79d50672.png](https://i-blog.csdnimg.cn/blog_migrate/67e2bba9f8efdd5cb06014d8a847a044.png)
10.遍历‘(’,直接入栈
【当前后缀表达式:AB+C*】
![a411bc8d849bbab887f3372045f7a100.png](https://i-blog.csdnimg.cn/blog_migrate/83926919176599e14098c287587a1a1e.png)
11.遍历到数字E,直接加入到后缀表达式
【当前后缀表达式:AB+C*E】
12.遍历到-,栈顶元素为‘(’,入栈
【当前后缀表达式:AB+C*E】
13.遍历到F,加入到后缀表达式
【当前后缀表达式:AB+C*EF】
![2a6131a9c69246ab0969f0c1af09807d.png](https://i-blog.csdnimg.cn/blog_migrate/9273c9b99704905007df061b5fe81cd0.png)
14.遍历到‘)’,依次将栈中的运算符加入后缀表达式,直到出现‘(’,并删除栈顶的‘(’
【当前后缀表达式:AB+C*EF-】
![75a77ee86cf4067a2b976c2e115909a8.png](https://i-blog.csdnimg.cn/blog_migrate/41243caab61054362d581a2dd6f465ba.png)
15.遍历完毕,栈非空,将栈中元素依次弹出
【当前后缀表达式:AB+C*EF--】
![436085cc569720a657841234717decb0.png](https://i-blog.csdnimg.cn/blog_migrate/68d0d6381cb5ae72dd15fe0938c97e2f.png)
成功得到后缀表达式!!!
代码实现
#include<stdio.h>
#define ElemType char
#define MaxSize 50
typedef struct {
ElemType data[MaxSize];
int top;
}SqStack;
void initStack(SqStack& S)
{
S.top = -1; //初始化栈顶指针
}
bool StackEmpty(SqStack S)
{
if (S.top == -1) //栈空
return true;
else
return false; //栈不空
}
bool Push(SqStack& S, ElemType x)
{
if (S.top == MaxSize - 1) //栈满 不能执行入栈操作
return false;
S.top++; //指针先加1,再入栈
S.data[S.top] = x;
return true;
}
bool Pop(SqStack& S, ElemType& x)
{
if (S.top == -1) //栈空 不能执行出栈操作
return false;
x = S.data[S.top]; //先出栈 指针再减1
S.top--;
return true;
}
bool GetPop(SqStack S, ElemType& x)
{
if (S.top == -1) //栈空报错
return false;
x = S.data[S.top]; //用x存储栈顶元素
return true;
}
int main()
{
SqStack S;
initStack(S);
char NifixExpression[] = { '(','(','A','+','B',')','*','C',')','-','(','E','-','F',')','0' };
char PostfixExpression[60]; //在字符数组最后添加'0',作为结束标志
int index = 0;
char* p = NifixExpression;
while (*p!='0')
{
if (*p == '(') //如果为左括号,直接入栈
{
Push(S, *p);
p++;
}
else if (*p == ')')//若为右括号,依次弹出栈中运算符,直到'(',并删除'('--用出栈不保存数据实现
{
while (S.data[S.top] != '(')
{
char temp;
Pop(S, temp);
if (temp == '+' || temp == '-' || temp == '*' || temp == '/')
{
PostfixExpression[index] = temp;
index++;
}
}
char temp;
Pop(S, temp); //把左括号也出栈
p++;
}
else if (*p >= 'A' && *p <= 'Z') //这里用大写字母代替表达式中的数字,为大写字母则直接进入后缀表达式
{
PostfixExpression[index] = *p;
index++;
p++;
}
else
{
if (*p == '+' || *p == '-')
{
if (S.data[S.top] == '('||StackEmpty)//如果遍历到'+''-',且栈为空或栈顶为'(',直接入栈
{
Push(S, *p);
p++;
}
else {
while (S.data[S.top] != '('&&!StackEmpty)//依次弹出较高优先级运算符,直到'('
{
char temp;
Pop(S, temp);
PostfixExpression[index] = temp;
index++;
}
}
}
else
{
Push(S, *p);
p++;
}
}
}
if (!StackEmpty(S)) //若栈不为空,依次弹出其中的运算符
{
while (S.top != -1)
{
char temp;
Pop(S,temp);
PostfixExpression[index] = temp;
index++;
}
}
PostfixExpression[index] = '0'; //在字符数组后加'0',作为结束标志
printf("中缀表达式为:%s",NifixExpression);
printf("n");
printf("后缀表达式为:%s", PostfixExpression);
}
测试结果
![76a753d278e4b20376725ecc64f8a093.png](https://i-blog.csdnimg.cn/blog_migrate/73cd8a5bd07ec8b6760d1ad22d58b3b3.png)