中缀表达式 转 (逆)波兰表达式

由于两者方法相近,所以直接放一起方便互相对比

方法参考相关大神的讲解,特此说明,代码为本人所写,转载请声明!

本人测试了五组数据,结果已附图如下,暂时没发现问题,如有问题,多谢指出。

 

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

 

posted @ 2016-10-08 20:32  nullxjx  阅读(15024)  评论(8编辑  收藏  举报