中缀转后缀
#include <stdio.h>
#include <ctype.h> //提供isalpha原型
/*比较运算符a、b的优先级 */
int Priority(char a, char b){
switch(a){
case '*':
case '/':
return 1; //a>b
break;
case '+':
case '-':
if(b=='+' || b=='-')
return 1; //a>b
else
return 0; //a<b
break;
}
}
/* 中缀式变后缀式(带括号) */
/* 逆波兰式:即后缀表达式,将运算符写在操作数之后 */
/* 如"(a+b*c)/d-e"将转化为:"abc*+d/e-" */
/* 假设表达式变量为单字母,操作符有'+'、'-'、'*'、'/'、'('、')' */
/*
转换规则
1、如果遇到操作数,我们就直接将其存入暂存逆波兰式的数组c
2、如果遇到左括号,我们也将其直接放入栈中
3、如果遇到右括号,则将栈元素弹出存入数组c,直到遇到左括号为止。注意:【左括号只弹出并不存入数组c】
4、如果遇到运算符,如:“+”,“-” “*”,“/”
(1)若栈中运算符优先级高,将栈中优先级高的运算符弹出并送入数组c,直到出现情况(2)为止
(2)若栈中运算符优先级低或栈为空,将读取到的字符压入栈
(3)有一点需要注意,只有在遇到")"的情况下我们才弹出"(",其他情况我们都不会弹出"("
5、如果读到了中缀式的末尾,则将栈中所有元素依次弹出存入数组c
6、最终后缀表达式就存储在了数组c中,将其输入即可
*/
void Algo_1(char *s, char c[]){ //用一个足够大的数组暂存逆波兰式
int i, j;
char e; //char和int类型可直接比较
char stack[100]; //栈中临时存储操作符
int top=-1;
i = j = 0;
while(s[i]!='\0'){ //如果还没有读到中缀式的末尾
if(isalpha(s[i])) //读到单字母
c[j++] = s[i]; //字母直接送入数组
else if(s[i]=='('){
stack[++top]=s[i]; //如果遇到左括号,将其入栈
}
else if(s[i]==')'){ //如果遇到右括号,将栈中元素出栈并送入数组,直到遇到左括号
while(stack[top]!='('){
e=stack[top--];
c[j++] = e;
}
stack[top--]; //将左括号出栈,不加入数组【后缀表达式不包含左右括号】
}
else{ //读到的是运算符
while(top!=-1){
e=stack[top]; //获取栈顶元素
/*
注意栈中也会存储左括号,因此获取的栈顶元素可能是左括号
由于左括号优先级小于+、-、*、/,因此碰到'('时不用出栈,直接break即可
*/
if(e!='('&&Priority(e, s[i])){ //栈中运算符优先级高【这里的运算符只包含+、-、*、/】
e=stack[top--]; //将栈中优先级高的运算符送入数组
c[j++] = e;
}
else //遇到栈中运算符优先级低时,结束循环
break;
}
stack[++top]=s[i]; //将读取到的优先级高的字符压入栈
}
i++; //继续读取
}
while(top!=-1){
e=stack[top--]; //出栈
c[j++] = e;
}
c[j] = '\0'; //数组中转换后的逆波兰式以"\0"标记结束
}
int main(int argc, char *argv[]){
char *s = "(a+b*c)/d-e";
char c[100];
printf("中缀表达式为:");
printf("%s\n",s);
printf("\n");
Algo_1(s, c);
printf("生成的后缀表达式:");
printf("%s\n",c);
printf("\n");
return 0;
}
后缀表达式求值
#include <stdio.h>
#include <ctype.h> //提供isdigit原型
/*
后缀表达式具有和前缀表达式类似的好处,没有优先级的问题【无括号】
1、直接读取表达式,如果遇到数字就压栈
2、如果遇到运算符,就弹出两个数进行运算,随后再将运算结果压栈
*/
/* 计算a<oper>b */
char Operate(char a, char oper, char b){
char c;
switch(oper){
case '+': c = (a-48)+(b-48)+48;
break;
case '-': c = (a-48)-(b-48)+48;
break;
case '*': c = (a-48)*(b-48)+48;
break;
case '/': c = (a-48)/(b-48)+48;
break;
}
return c;
}
/* 对逆波兰表达式求值 */
/*预设操作符为'+','-','*','/',变量为单数字 */
int Algo_2(char c[], char *Value){
int i=0;
int top=-1; //栈顶指针
int stack[100]; //设栈的容量为00
char a, b;
while(c[i]){
if(isdigit(c[i])) //遇到数字
stack[++top]=c[i];
else{
b=stack[top--];
a=stack[top--]; //先弹出来的在操作数后边
stack[++top]=Operate(a, c[i], b);
}
i++;
}
*Value=stack[top--];
if(top!=-1) //栈不为空时
return 0;
else
return 1;
}
int main(int argc, char *argv[]){
/*中缀表达式:(a+b*c)/d-e【(3+3*4)/3-2】
后缀表达式:abc*+d/e-【334*+3/2-】*/
char c[] = "334*+3/2-";
char value;
printf("已知逆波兰式为:");
printf("%s\n", c);
Algo_2(c, &value);
printf("逆波兰式的计算结果为:%d\n", value-48);
printf("\n");
return 0;
}