中缀表达式转后缀表达式:
假定有中缀表达式1 + (( 2 + 3)* 4 ) – 5,请将它转化为后缀表达式。
方法一:利用表达式树
首先将中缀表达式转换为表达式树,然后后序遍历表达式树,所得结果就是后缀表达式。
将中缀表达式转化为表达式树方法:表达式树的树叶是操作数,而其他的节点为操作符,根节点为优先级最低且靠右的操作符(如上述表达式优先级最低的是- 和+,但 + 更靠右,所以根为+),圆括号不包括。如上述中缀表达式转换后的表达式树如下:
经过后序遍历表达式树后得到的后缀表达式为:12 3 + 4 * + 5 -
方法二:利用辅助栈
从左到右遍历中缀表达式的每个操作数和操作符。当读到操作数时,立即把它输出,即成为后缀表达式的一部分;若读到操作符,判断该符号与栈顶符号的优先级,若该符号优先级高于栈顶元素,则将该操作符入栈,否则就一次把栈中运算符弹出并加到后缀表达式尾端,直到遇到优先级低于该操作符的栈元素,然后把该操作符压入栈中。如果遇到”(”,直接压入栈中,如果遇到一个”)”,那么就将栈元素弹出并加到后缀表达式尾端,但左右括号并不输出。最后,如果读到中缀表达式的尾端,将栈元素依次完全弹出并加到后缀表达式尾端。
利用辅助栈后缀表达式与用表达式树的结果一样,都为:1 2 3 + 4 * + 5 –
以上内容转载自:https://blog.csdn.net/walkerkalr/article/details/22798365
下面是方法二的C语言代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define MAXSIZE 100
//顺序栈的存储定义
typedef struct stack
{
char *base;//栈底指针
char *top;//栈顶指针
int stacksize;//栈分配的存储空间大小
}SqStack;
typedef struct stack2
{
int *base;//栈底指针
int *top;//栈顶指针
int stacksize;//栈分配的存储空间大小
}SqStack2;
SqStack op;//顺序栈op用来存储运算符
SqStack2 st;//st用来存放数值
void Menu();
void InitStack();
void trans(char str[], char rpn[]);
int value(char rpn[]);
int Match(char *p);
//*****************************************************************************
void Menu()
{//界面函数
printf("*********表达式求值(只能包含+、-、*、/、()和正整数)********* ******\n");
printf("请选择:1.输入表达式 2.括号匹配检查 3.转换后缀表达式 4.表达式计算5.退出\n");
}
//*****************************************************************************
void InitStack()
{//初始化栈op、st
op.base = op.top = (char *)malloc(MAXSIZE * sizeof(char));
if (op.base == NULL) exit(-2);
st.base = st.top = (int *)malloc(MAXSIZE * sizeof(int));
if (st.base == NULL) exit(-2);
op.stacksize = st.stacksize = MAXSIZE;
}
//*****************************************************************************
int Match(char *p)
{//检查表达式中小括号是否匹配
int flag = 0;
SqStack s;
s.base = s.top = (char*)malloc(MAXSIZE * sizeof(char));
if (!s.base) exit(-2);
s.stacksize = MAXSIZE;
while (*p != '\0')
{
if (*p == '(')
{
if (s.top - s.base == s.stacksize) exit(-1);
else {
*s.top = *p;
s.top++;//将所有的左括号入栈
}
}
if (*p == ')')
{
if (s.top != s.base&&*(s.top - 1) == '(') {
s.top--;
flag = 1;
}
else flag = 2;
}
p++;
}//while
if ((flag == 1 || flag == 0) && s.top == s.base)
{
s.top = s.base;//将栈清空
return 1;
}
else if (flag == 2) {
s.top = s.base;//将栈清空
return 0;
}
}//Match
//*****************************************************************************
void trans(char str[], char rpn[])
{//将中缀表达式转换为后缀表达式
char ch;
int i = 0, t = 0;
ch = str[i];
i++;
while (ch != '\0')
{
switch (ch)
{
case '(': *op.top++ = ch; break;
case ')':
while (*(op.top - 1) != '(')
{
rpn[t] = *(op.top - 1);
op.top--;
t++;
}
op.top--;//此处必须再次进行--运算,才能忽略已经进入的'('
break;
case '+':
case '-':
while (op.top != op.base && *(op.top - 1) != '(')
{
rpn[t] = *(op.top - 1);
op.top--;
t++;
}
*op.top++ = ch;
break;
case '*':
case '/':
while (*(op.top - 1) == '*' || *(op.top - 1) == '/')
{
rpn[t] = *(op.top - 1);
op.top--;
t++;
}
*op.top++ = ch;
break;
case ' ':break;
default:
while (ch >= '0'&&ch <= '9')
{
rpn[t] = ch;
t++;
ch = str[i];
i++;
}
i--;
rpn[t] = '#'; t++;
}//switch
ch = str[i];
i++;
}//while
while (op.top != op.base)
{
rpn[t] = *(op.top - 1);
t++;
op.top--;
}//while
rpn[t] = '\0';
}//trans
//*****************************************************************************
int value(char rpn[])
{//后缀表达式求值
int d;
char ch;
int t = 0;
ch = rpn[t];
t++;
while (ch != '\0')
{
switch (ch)
{
case '+':
*(st.top - 2) = *(st.top - 2) + *(st.top - 1);
st.top--;
break;
case '-':
*(st.top - 2) = *(st.top - 2) - *(st.top - 1);
st.top--;
break;
case '*':
*(st.top - 2) = *(st.top - 2) * *(st.top - 1);
st.top--;
break;
case '/':
if (*(st.top - 1) != 0)
*(st.top - 2) = *(st.top - 2) / *(st.top - 1);
else
{
printf("\n除0错误!\n");
exit(0);
}
st.top--;
break;
default:
d = 0;
while (ch >= '0'&&ch <= '9')
{
d = 10 * d + ch - '0';
ch = rpn[t];
t++;
}
*(st.top++) = d;
}//switch
ch = rpn[t]; t++;
}//while
return *(st.top - 1);
}//value
//*****************************************************************************
int main()
{//主函数
char str[MAXSIZE], rpn[MAXSIZE], g, f;
//str数组用来存储接收到的字符串,rpn用来存放转换出来的后缀表达式
int i, j = 0;
InitStack();
Menu();
while (1)
{
scanf("%d", &g);
switch (g)
{
case 1: printf("请输入表达式:");
scanf("%s", str);
i = Match(str);
break;
case 2: if (i == 1) printf("匹配成功!\n");
else printf("匹配失败!\n");
break;
case 3: if (i == 1)
{
trans(str, rpn);
printf("后缀表达式为:%s\n", rpn);
j = 1;
}
else { j = 0; printf("表达式中括号匹配错误!\n"); }
break;
case 4: if (j) printf("计算结果为:%d\n", value(rpn));
else printf("后缀表达式转换遇到问题!\n");
break;
case 5: printf("确定要退出系统吗?(y/n)\n");
getchar(); f = getchar();
if (f == 'y' || f == 'Y') exit(0);
else { printf("请重新选择!\n"); break; }
default:printf("输入错误!\n");
exit(1);
}//switch
}//while
return 0;
}//main