中缀表达式改后缀表达式
一、我们先看看中缀改表达式改成后缀表达式的规则:
下面我们来举个例子:
将中缀表达式
9+(3-1)*3+10/2 转成后缀表达式;
1.从左往右遍历,
第一个字符是数字9,输出9,后面是符号“+”,进
栈
。
2. 第三个字符是“(”,依然是符号,因其只是左括号,还未配对,故进栈。
3. 第四个字符是数字3,输出,总表达式为9 3,接着是“-”进栈。
4. 接下来是数字1,输出,总表达式为9 3 1,后面是符号“)”,此时,我们需要去匹配此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”,因此输出“-”,总的输出表达式为9 3 1 -
6. 接着是数字3,输出,总的表达式为9 3 1 - 3 。紧接着是符号“*”,因为此时的栈顶符号为“+”号,优先级低于“*”,因此不输出,进栈。
7. 之后是符号“+”,此时当前栈顶元素比这个“+”的优先级高,因此栈中元素出栈并输出(没有比“+”号更低的优先级,所以全部出栈),总输出表达式为 9 3 1 - 3 * +.然后将当前这个符号“+”进栈。也就是说,前6张图的栈底的“+”是指中缀表达式中开头的9后面那个“+”,而下图中的栈底(也是栈顶)的“+”是指“9+(3-1)*3+”中的最后一个“+”。
8. 紧接着数字10,输出,总表达式变为9 3 1-3 * + 10。
9. 最后一个数字2,输出,总的表达式为 9 3 1-3*+ 10 2
10. 因已经到最后,所以将栈中符号全部出栈并输出。最终输出的后缀表达式结果为 9 3 1-3*+ 10
二、下面是转成后缀表达式之后计算的过程
上面的例子转后缀了之后的结果是9 3 1 - 3 * + 10 2 / +
遍历后缀表达式,遇到数字字符则入栈,遇到符号则从数栈里取出两个操作数进行计算,再将结果压入栈中
三、源代码:
#include
#include
#define maxLength 200
typedef struct
{
char data[maxLength];
int top = 0;
}Stack;
typedef struct
{
float data[maxLength];
int top = 0;
}StackC;
int Empty(Stack S) //判断栈是否为空
{
if(S.top < 0)
return 1;
else
return 0;
}
char Top(Stack S) //返回字符栈的栈顶元素
{
if(Empty(S) == 1)
return NULL;
else
return (S.data[S.top]);
}
void push(char x,Stack & S) //将元素压入字符栈中
{
if(S.top == maxLength)
printf("stack is full\n");
else{
S.top = S.top + 1;
S.data[S.top] = x;
}
}
void pushF(float x,StackC & S) //将元素压入数值栈中
{
if(S.top == maxLength)
printf("stack is full\n");
else{
S.top = S.top + 1;
S.data[S.top] = x;
}
}
bool IsData(char a) //判断是否为数字或小数点
{
if((a>=48 && a<=57)||a==46)
return 1;
else
return 0;
}
bool IsOper(char s) //判断是否为运算操作符
{
if(s == '+' || s=='-' || s=='*' || s == '/' || s == '%' || s == '(' || s == ')')
return 1;
else
return 0;
}
int toBack(char str[],char str2[][maxLength],Stack S) //中缀表达式转后缀表达式
{
int i,j=0,k=0;
int num;
for(i=0;str[i]!='\0';i++){
if(IsData(str[i]))
str2[j][k++] = str[i]; //如果是数字或小数点则放到字符数组里
else if(IsOper(str[i])){
k=0; //如果是操作符,说明已经读到最后一位小数了
j++; //开始存下一个字符
if(Empty(S)==1){
push(str[i],S); //如果栈为空,则进栈
}
else if(str[i]=='*' || str[i] == '/' || str[i] == '%'){
if(S.data[S.top] == '*' || S.data[S.top] == '/' || S.data[S.top] == '%'){
str2[j++][0] = S.data[S.top]; //如果优先级跟栈顶元素一样,则栈里的所有元素全部出栈
S.top = S.top -1;
}
push(str[i],S);
}
else if(str[i] == '('){ //如果是左括号,则直接入栈
push(str[i],S);
}
else if(str[i] == '+' || str[i] == '-'){
if(S.data[S.top] != '('){ //如果是+,-,只要栈顶不是左括号就取出栈顶元素
str2[j++][0] = S.data[S.top];
S.top = S.top -1;
}
push(str[i],S);
}
else if(str[i] == ')'){ //如果是有括号,则把栈里左括号之前的全部弹出
do{
str2[j++][0] = S.data[S.top];
S.top = S.top - 1;
}while(S.data[S.top] != '(');
S.top = S.top - 1;
}
}
num = j;
}
do{
str2[++num][0] = S.data[S.top]; //最后将栈里的元素全部弹出来
S.top = S.top -1;
}while((Empty(S))==0);
return num;
}
float calculation(char str[][maxLength],int n) //计算后缀表达式的值
{
StackC digtS;
int i;
float x;
float ans;
for(i=0;i<=n;i++){
if(IsData(str[i][0])){ //如果是数字字符,则压入数字栈中
x = atof(str[i]);
pushF(x,digtS);
}
else if(IsOper(str[i][0])){ //如果是操作符,则取出两个操作数
float a = digtS.data[digtS.top];
digtS.top = digtS.top - 1;
float b = digtS.data[digtS.top];
digtS.top = digtS.top - 1;
char op = str[i][0];
switch(op){
case '+':
ans = b+a;
pushF(ans,digtS);
break;
case '-':
ans = b - a;
pushF(ans,digtS);
break;
case '*':
ans = b*a;
pushF(ans,digtS);
break;
case '/':
ans = b/a;
pushF(ans,digtS);
break;
case '$': //如果是$。则只需要一个操作数,将后取出的操作数压入栈中
pushF(b,digtS);
ans = -a;
pushF(ans,digtS);
break;
case '%':
int ansI = (int)b % (int)a;
ans = float(ansI);
pushF(ans,digtS);
break;
}
}
}
return ans;
}
int main()
{
int i,j,k=0;
Stack operS;
char input_str[maxLength],output_str[maxLength][maxLength];
printf("请输入要求的表达式:\n");
gets(input_str); //得到中缀表达式
int num=toBack(input_str,output_str,operS);
printf("转成的后缀表达式为:\n");
for(i=0;i<=num;i++){
for(j=0;output_str[i][j]!='\0';j++){
printf("%c",output_str[i][j]);
}
printf(" ");
k++;
}
if(num == 1){
printf("\n计算结果为:");
puts(output_str[0]);
}
else
printf("\n计算结果为:%.2f\n",calculation(output_str,num+k));
return 0;
}