由於兩者方法相近,所以直接放一起方便互相對比
方法參考相關大神的講解,特此說明,代碼為本人所寫,轉載請聲明!
本人測試了五組數據,結果已附圖如下,暫時沒發現問題,如有問題,多謝指出。
以下摘自@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 }