中綴表達式轉換成波蘭表達式和逆波蘭表達式【代碼】


由於兩者方法相近,所以直接放一起方便互相對比

方法參考相關大神的講解,特此說明,代碼為本人所寫,轉載請聲明!

本人測試了五組數據,結果已附圖如下,暫時沒發現問題,如有問題,多謝指出。

 

以下摘自@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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM