C语言实现中缀表达式转换前缀表达式和后缀表达式
基本思想
人们习惯的运算方式是中缀表达式,而碰到前缀,后缀方式就变迷茫。其实仅仅是一种表达式的方式而已(不被你习惯的方式),我这里教你一种也许你老师都没跟你讲的简单转换方式。
一个中缀式到其他式子的转换方法:
这里我给出一个中缀表达式a+b*c-(d+e)
第一步:按照运算符的优先级对所有的运算单位加括号,式子变成:((a+(b*c))-(d+e))
第二步:转换前缀与后缀表达式
前缀:把运算符号移动到对应的括号前面
则变成:-( +(a *(bc)) +(de))
,把括号去掉:-+a*bc+de
前缀式子出现
后缀:把运算符号移动到对应的括号后面
则变成拉:((a(bc)* )+ (de)+ )-
,把括号去掉:abc*+de+-
后缀式子出现
发现没有,前缀式,后缀式是不需要用括号来进行优先级的确定的。
转自:https://zhuanlan.zhihu.com/p/47372892
程序实现原理:
-
中缀转换前缀:
(1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
(2) 从右至左扫描中缀表达式;
(3) 遇到操作数时,将其压入S2;
(4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
(4-1) 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈;
(4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1;
(4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
(5) 遇到括号时:
(5-1) 如果是右括号“)”,则直接压入S1;
(5-2) 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃;
(6) 重复步骤(2)至(5),直到表达式的最左边;
(7) 将S1中剩余的运算符依次弹出并压入S2;
(8) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。 -
中缀转换后缀:
(1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
(2) 从左至右扫描中缀表达式;
(3) 遇到操作数时,将其压入S2;
(4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
(4-1) 如果S1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
(4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1;
(4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
(5) 遇到括号时:
(5-1) 如果是左括号“(”,则直接压入S1;
(5-2) 如果是右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃;
(6) 重复步骤(2)至(5),直到表达式的最左边;
(7) 将S1中剩余的运算符依次弹出并压入S2;
(8) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。
C语言实现
#include <stdio.h>
#include <string.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;
}
// 转换为前缀表达式
void PolishNotation(SqStack S, char NifixExpression[])
{
char PostfixExpression[60]; //在字符数组最后添加'\0',作为结束标志
int index = 0;
// 从右至左运算
char *p = &NifixExpression[strlen(NifixExpression) - 1];
// printf("长度为:%c\n", *(p));
for (int i = strlen(NifixExpression) - 1; i >= 0; i--)
{
// printf("值为:%c\n", *(p--));
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(S)) //如果遍历到'+''-',且栈为空或栈顶为')',直接入栈
{
Push(S, *p);
p--;
}
else
{
while (S.data[S.top] != ')' && !StackEmpty(S)) //依次弹出较高优先级运算符,直到')'
{
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("前缀表达式为:");
for (int i = strlen(NifixExpression) - 1; i >= 0; i--)
{
printf("%c", PostfixExpression[i]);
}
printf("\n");
}
// 转换为后缀表达式
void RPN(SqStack S, char NifixExpression[])
{
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(S)) //如果遍历到'+''-',且栈为空或栈顶为'(',直接入栈
{
Push(S, *p);
p++;
}
else
{
while (S.data[S.top] != '(' && !StackEmpty(S)) //依次弹出较高优先级运算符,直到'('
{
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", PostfixExpression);
}
int main()
{
SqStack S;
initStack(S);
char NifixExpression[] = {'(', '(', 'A', '+', 'B', ')', '*', 'C', ')', '-', '(', 'E', '-', 'F', ')', '\0'};
// char NifixExpression[] = {'A', '*', '(', 'B', '+', 'C', ')', '-', 'D', '\0'};
printf("中缀表达式为:%s", NifixExpression);
printf("\n");
PolishNotation(S, NifixExpression);
RPN(S, NifixExpression);
}
运行结果: