由于两者方法相近,所以直接放一起方便互相对比
方法参考相关大神的讲解,特此说明,代码为本人所写,转载请声明!
本人测试了五组数据,结果已附图如下,暂时没发现问题,如有问题,多谢指出。
以下摘自@wanghetao http://www.cnblogs.com/wanghetao/archive/2012/04/23/2466580.html
一、 将中缀表达式转换成后缀表达式算法:
1、从左至右扫描一中缀表达式。
2、若读取的是操作数,则判断该操作数的类型,并将该操作数存入操作数堆栈
3、若读取的是运算符
(1) 该运算符为左括号"(",则直接存入运算符堆栈。
(2) 该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为止。
(3) 该运算符为非括号运算符:
(a) 若运算符堆栈栈顶的运算符为括号(只可能是左括号),则直接存入运算符堆栈。
(b) 若比运算符堆栈栈顶的运算符优先级高,则直接存入运算符堆栈。
(c) 若比运算符堆栈栈顶的运算符优先级低或相等,则不断输出栈顶运算符到操作数堆栈,直到栈顶没有运算符的优先级大于或者等于当前预算符(即栈顶存在运算符的话,优先级一定是小于当前运算符),最后将当前运算符压入运算符堆栈。
4、当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空。
二、逆波兰表达式求值算法:
1、从左到右依次扫描语法单元的项目。
2、如果扫描的项目是操作数,则将其压入操作数堆栈,并扫描下一个项目。
3、如果扫描的项目是一个二元运算符,则对栈的顶上两个操作数执行该运算。
4、如果扫描的项目是一个一元运算符,则对栈的最顶上操作数执行该运算。
5、将运算结果重新压入堆栈。
6、重复步骤2-5,堆栈中即为结果值。
-------------------------------------------------分界线-------------------------------------------------
以下摘自@unixfy http://www.cnblogs.com/unixfy/p/3344550.html
一、 将中缀表达式转换成前缀表达式算法:
1、首先设定一个操作符栈,从右到左顺序扫描整个中缀表达式,如果是操作数,则直接归入前缀表达式;
2、如果是操作符,则检测器是否是右括号,如果是右括号,则直接将其入栈;
3、如果是左括号,则将栈中的操作符依次弹栈,归入前缀表达式,直至遇到右括号,将右括号弹栈,处理结束;
4、如果是其他操作符,则检测栈顶操作符的优先级与当前操作符的优先级关系,
5、如果栈顶操作符优先级大于当前操作符的优先级,则弹栈,并归入前缀表达式,直至栈顶操作符优先级小于等于当前操作符优先级,这时将当前操作符压栈。
6、当扫描完毕整个中缀表达式后,检测操作符栈是否为空,如果不为空,则依次将栈中操作符弹栈,归入前缀表达式。最后,将前缀表达式翻转,得到中缀表达式对应的前缀表达式。
二、波兰表达式求值算法:
1、从右到左依次扫描语法单元的项目。
2、如果扫描的项目是操作数,则将其压入操作数堆栈,并扫描下一个项目。
3、如果扫描的项目是一个二元运算符,则对栈的顶上两个操作数执行该运算。
4、如果扫描的项目是一个一元运算符,则对栈的最顶上操作数执行该运算。
5、将运算结果重新压入堆栈。
6、重复步骤2-5,堆栈中即为结果值。
|
中缀转前缀 |
中缀转后缀 |
栈 |
操作符栈 |
操作符栈 |
扫描顺序 |
从右到左 |
从左到右 |
遇到操作数 |
直接归入 |
直接归入 |
遇到右括号 |
直接入栈 |
将栈中操作符依次弹栈,归入,直至遇到左括号,将左括号弹栈,处理完毕 |
遇到左括号 |
将栈中操作符依次弹栈,归入,直至遇到右括号,将右括号弹栈,处理完毕 |
直接入栈 |
遇到其他操作符 |
检测栈顶操作符优先级与当前操作符优先级关系,如果栈顶大于当前,则出栈,归入,直至栈顶小于等于当前,并将当前操作符入栈 |
检测栈顶与当前优先级关系,如果栈顶大于等于当前则出栈,归入,直至栈顶小于当前,并将当前操作符入栈 |
操作符栈中的优先级 |
从栈底到栈顶操作优先级:非递减。即:栈顶可以大于或等于下面的 |
从栈底到栈顶优先级:递增。即:栈顶必须大于下面的 |
是否翻转 |
翻转 |
无需翻转 |
运行结果如下:
-------------------------------------------------代码区-------------------------------------------------
1 #include <iostream> 2 #include<stdlib.h> 3 4 using namespace std; 5 6 #define STACK_INIT_SIZE 100 7 #define STACKINCREASE 10 8 9 //为了简化问题,数字和符号统一当成字符看待 10 //由此导致的后果是接下来所有的运算过程中不允许出现小数,而且由于是利用ASCII表来储存整数, 11 //所以每个运算数都只能取0-9的一位数,暂时没有考虑负数问题. 12 //暂时没有考虑非法输入 13 14 typedef struct 15 { 16 char *base; 17 char *top; 18 int stacksize; 19 }SqStack; 20 21 22 int InitStack(SqStack &S) 23 { 24 S.base=(char *)malloc(STACK_INIT_SIZE*sizeof(char)); 25 if(!S.base) 26 { 27 cout<<"分配空间失败!"; 28 exit(-1); 29 } 30 S.top=S.base; 31 S.stacksize=STACK_INIT_SIZE; 32 return 0; 33 } 34 35 36 int Push(SqStack &S,char e) 37 { 38 if((S.top-S.base)>=STACK_INIT_SIZE) 39 { 40 S.base=(char *)realloc(S.base,(STACK_INIT_SIZE+STACKINCREASE)*sizeof(char)); 41 if(!S.base) 42 { 43 cout<<"分配空间失败!"; 44 exit(-1); 45 } 46 S.top=S.base+STACK_INIT_SIZE; 47 S.stacksize=STACK_INIT_SIZE+STACKINCREASE; 48 } 49 *(S.top)=e;//结构体 50 S.top++; 51 return 0; 52 } 53 54 55 int Pop(SqStack &S,char &e) 56 { 57 if(S.base==S.top) 58 { 59 cout<<"栈为空!"; 60 exit(0); 61 } 62 S.top--; 63 e=*(S.top); 64 return 0; 65 } 66 67 int GetTop(SqStack &S,char &e) 68 { 69 if(S.base==S.top) 70 { 71 cout<<"栈为空!"; 72 return 0; 73 } 74 else 75 { 76 e=*(S.top-1); 77 return 1; 78 } 79 } 80 81 82 int EmptyStack(SqStack &S) 83 { 84 if(S.base==S.top) return 1;//stack is empty! 85 else return 0;//stack is not empty! 86 } 87 88 89 int Precede(char a,char b)//a为符号栈栈顶元素,b为待插入的元素 90 { 91 int i;//i=1入栈,i=0弹出操作符以及操作数进行计算 92 if((a=='+'||a=='-')&&(b=='*'||b=='/')) i=1; 93 if((a=='+'||a=='-')&&(b=='+'||b=='-')) i=0; 94 if((a=='*'||a=='/')&&(b=='*'||b=='/')) i=0; 95 if((a=='*'||a=='/')&&(b=='+'||b=='-')) i=0; 96 if(a=='('||a==')') i=1; 97 return i; 98 } 99 100 101 int Nifix_To_Suffix(char *p) 102 { 103 char a,c,e; 104 int i; 105 SqStack S;//S为操作符栈,遇到操作数直接输出,所以不需要操作数栈 106 InitStack(S); 107 c=*p++; 108 cout<<"转换后的后缀表达式为:"<<endl; 109 while(c!='#') 110 { 111 if(c>=48&&c<=57) cout<<c;//输入为数字,直接输出 112 if(c=='(') Push(S,c); //输入为左括号 113 if(c==')')//输入为右括号 114 { 115 if(!EmptyStack(S)) GetTop(S,e); 116 while(e!='(') 117 { 118 Pop(S,a);cout<<a; 119 if(!EmptyStack(S)) GetTop(S,e);//直到遇到左括号 120 if(e=='(') Pop(S,e); 121 } 122 } 123 if(c=='+'||c=='-'||c=='*'||c=='/') 124 { 125 if(EmptyStack(S)) Push(S,c); 126 else 127 { 128 GetTop(S,e); 129 i=Precede(e,c); 130 if(i==1) Push(S,c); 131 if(i==0) 132 { 133 while(!i) 134 { 135 Pop(S,a); cout<<a; 136 if(!EmptyStack(S)) {GetTop(S,e); i=Precede(e,c);} 137 else break; 138 } 139 Push(S,c); 140 } 141 } 142 } 143 c=*p++; 144 } 145 if(!EmptyStack(S)) 146 { 147 while(!EmptyStack(S)) 148 { 149 Pop(S,a); 150 cout<<a; 151 } 152 } 153 cout<<endl; 154 return 0; 155 } 156 157 158 int Nifix_To_Prefix (char *p) 159 { 160 char a,c,d,e; 161 int i; 162 SqStack S,S1,S2;//S为操作符栈,S1为存储倒置后元素的栈,S2存储的是逆序的前缀表达式,最后依次弹出以实现最终的前缀表达式 163 InitStack(S);InitStack(S1);InitStack(S2); 164 //由于要从右到左依次读取表达式中的各个元素,所以这里利用一个栈S1将它们倒置 165 d='#'; 166 Push(S1,d); 167 while(*p!='#') 168 { 169 d=*p; 170 Push(S1,d); 171 p++; 172 if(*p=='#') break; 173 } 174 Pop(S1,c); 175 cout<<"转换后的前缀表达式为:"<<endl; 176 while(c!='#') 177 { 178 if(c>=48&&c<=57) Push(S2,c);//输入为数字,直接输出 179 if(c==')') Push(S,c); //输入为右括号 180 if(c=='(')//输入为左括号 181 { 182 if(!EmptyStack(S)) GetTop(S,e); 183 while(e!=')') 184 { 185 Pop(S,a);Push(S2,a); 186 if(!EmptyStack(S)) GetTop(S,e);//直到遇到左括号 187 if(e==')') Pop(S,e); 188 } 189 } 190 if(c=='+'||c=='-'||c=='*'||c=='/') 191 { 192 if(EmptyStack(S)) Push(S,c); 193 else 194 { 195 GetTop(S,e); 196 i=Precede(e,c); 197 if(i==1) Push(S,c); 198 if(i==0) 199 { 200 while(!i) 201 { 202 Pop(S,a); Push(S2,a); 203 if(!EmptyStack(S)) {GetTop(S,e); i=Precede(e,c);} 204 else break; 205 } 206 Push(S,c); 207 } 208 } 209 } 210 Pop(S1,c); 211 } 212 if(!EmptyStack(S)) 213 { 214 while(!EmptyStack(S)) 215 { 216 Pop(S,a); 217 Push(S2,a); 218 } 219 } 220 while(!EmptyStack(S2)) 221 { 222 Pop(S2,a); 223 cout<<a; 224 } 225 cout<<endl; 226 return 0; 227 } 228 229 230 231 232 int main() 233 { 234 //数据测试 235 char *p1="3+2*5#"; 236 char *p2="2*5+3#"; 237 char *p3="2+3*(5-1)#"; 238 char *p4="((3+5*2)+2)/5+6/3*2+3#"; 239 char *p5="2+(3+4)*5#"; 240 cout<<"3+2*5"<<endl; Nifix_To_Suffix(p1); Nifix_To_Prefix(p1);cout<<endl<<endl; 241 cout<<"2*5+3"<<endl; Nifix_To_Suffix(p2); Nifix_To_Prefix(p2);cout<<endl<<endl; 242 cout<<"2+3*(5-1)"<<endl; Nifix_To_Suffix(p3); Nifix_To_Prefix(p3);cout<<endl<<endl; 243 cout<<"((3+5*2)+2)/5+6/3*2+3"<<endl; Nifix_To_Suffix(p4); Nifix_To_Prefix(p4);cout<<endl<<endl; 244 cout<<"2+(3+4)*5"<<endl; Nifix_To_Suffix(p5); Nifix_To_Prefix(p5);cout<<endl<<endl; 245 return 0; 246 }