词条 | 前缀表达式 |
释义 | 前缀表达式就是前序表达式前缀表达式就是前序表达式。 什么是前缀表达式前缀表达式就是不含括号的算术表达式,而且它是将运算符写在前面,操作数写在后面的表达式,为纪念其发明者波兰数学家Jan Lukasiewicz也称为“波兰式”。例如,- 1 + 2 3,它等价于1-(2+3)。 前缀表达式如何求值对于一个前缀表达式的求值而言,首先要从右至左扫描表达式,从右边第一个字符开始判断,如果当前字符是数字则一直到数字串的末尾再记录下来,如果是运算符,则将右边离得最近的两个“数字串”作相应的运算,以此作为一个新的“数字串”并记录下来。一直扫描到表达式的最左端时,最后运算的值也就是表达式的值。例如,前缀表达式“- 1 + 2 3“的求值,扫描到3时,记录下这个数字串,扫描到2时,记录下这个数字串,当扫描到+时,将+右移做相邻两数字串的运算符,记为2+3,结果为5,记录下这个新数字串,并继续向左扫描,扫描到1时,记录下这个数字串,扫描到-时,将-右移做相邻两数字串的运算符,记为1-5,结果为-4,所以表达式的值为-4。 前缀表达式有什么用处前缀表达式是一种十分有用的表达式,它将中缀表达式转换为可以依靠简单的操作就能得到运算结果的表达式。例如,(a+b)*(c+d)转换为*,+,a,b,+,c,d。它的优势在于只用两种简单的操作,入栈和出栈就可以解决任何中缀表达式的运算。其运算方式为:如果当前字符(或字符串)为数字或变量,则压入栈内;如果是运算符,则将栈顶两个元素弹出栈外并作相应运算,再将结果压入栈内。当前缀表达式扫描结束时,栈里的就是中缀表达式运算的最终结果。 中缀表达式转换为前缀表达式的一些例子a+b ---> +,a,b a+(b-c) ---> +,a,-,b,c a+(b-c)*d ---> +,a,*,-,b,c,d a=1+3 ---> a=+,1,3 中缀表达式转换为前缀表达式的一般算法(1) 首先构造一个运算符栈(也可放置括号),运算符(以括号分界点)在栈内遵循越往栈顶优先级不降低的原则进行排列。 (2)从右至左扫描中缀表达式,从右边第一个字符开始判断: 如果当前字符是数字,则分析到数字串的结尾并将数字串直接输出。 如果是运算符,则比较优先级。如果当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),则将运算符直接入栈;否则将栈顶运算符出栈并输出,直到当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),再将当前运算符入栈。 如果是括号,则根据括号的方向进行处理。如果是右括号,则直接入栈;否则,遇左括号前将所有的运算符全部出栈并输出,遇左括号后将左右的两括号一起删除。 (3) 重复上述操作(2)直至扫描结束,将栈内剩余运算符全部出栈并输出,再逆缀输出字符串。中缀表达式也就转换为前缀表达式了。 实例分析将中缀表达式“1+((2+3)*4)-5”转换为前缀表达式。 中缀表达式 前缀表达式 (栈顶)运算符栈(栈尾) 说明 5 5 空 5,是数字串直接输出 - 5 - -,栈内无运算符,直接入栈 ) 5 -) ),直接入栈 4 5 4 -) 4,是数字串直接输出 * 5 4 -)* *,栈顶是括号,直接入栈 ) 5 4 - ) * ) ),直接入栈 3 5 4 3 - ) * ) 3,是数字串直接输出 + 5 4 3 - ) * ) + +,栈顶是括号,直接入栈 2 5 4 3 2 - ) * )+ 2,是数字串直接输出 ( 5 4 3 2+ - ) * (,参考① ( 5 4 3 2+* - (,参考① + 5 4 3 2+* -+ +,优先级大于等于栈顶运算符,直接入栈 1 5 4 3 2+*1 -+ 1,是数字串直接输出 空 5 4 3 2+*1+- 空 扫描结束,将栈内剩余运算符全部出栈并输出 空 - + 1 * + 2 3 4 5 空 逆缀输出字符串 各运算符及符号优先级):直接入栈 (:遇)前,将运算符全部出栈并输出;遇)后,将两括号一起删除① +、-:1 *、/、%:2 ^:3 用编程实现中缀表达式向前缀表达式的转换#include<stdio.h> #include<conio.h> #include<math.h> #include<string.h> #define MaxSize 99 char calc[MaxSize],expr[MaxSize]; int i,t; struct { char data[MaxSize]; int top; }Sym; struct { double data[MaxSize]; int top; }Num; double ston(char x[],int *p) { int j=*p-1,i; double n=0,m=0; while(x[j]>='0'&&x[j]<='9') { j--; } if(x[j]!='.') { for(i=j+1;i<=*p;i++) { n=10*n+(x[i]-'0'); } } else { for(i=j+1;i<=*p;i++) { m=m+pow(0.1,i-j)*(x[i]-'0'); } if(x[j]=='.') { *p=--j; while(x[j]>='0'&&x[j]<='9') { j--; } for(i=j+1;i<=*p;i++) { n=10*n+(x[i]-'0'); } } } *p=j; if(x[*p]=='-') return(-(n+m)); return(n+m); } void InitStack() { Sym.top=Num.top=-1; } void SymPush() { if(Sym.top<MaxSize-1) { Sym.data[++Sym.top]=calc[i--]; } else { printf("Sym栈满\"); return; } } void SymPop() { if(Sym.top>=0) { expr[++t]=Sym.data[Sym.top--]; } else { printf("Sym栈空\"); return; } } void NumPush() { if(Num.top<MaxSize-1) { Num.data[++Num.top]=ston(expr,&i); } else { printf("Num栈满\"); return; } } void NumPop() { if(Num.top>=0) { if(expr[i]!=' ') { switch(expr[i]) { case '+':Num.data[Num.top-1]=Num.data[Num.top]+Num.data[Num.top-1];break; case '-':Num.data[Num.top-1]=Num.data[Num.top]-Num.data[Num.top-1];break; case '*':Num.data[Num.top-1]=Num.data[Num.top]*Num.data[Num.top-1];break; case '/':Num.data[Num.top-1]=Num.data[Num.top]/Num.data[Num.top-1];break; case '^':Num.data[Num.top-1]=pow(Num.data[Num.top],Num.data[Num.top-1]);break; } Num.top--; } } else { printf("Num栈空\"); return; } } int main(void) { char ch; loop1: i=0,t=-1; system("cls"); printf("中缀表达式:"); InitStack(),gets(calc); while(calc[i]!='\\0') { i++; } while(i>=0) { if(calc[i]>='0'&&calc[i]<='9') { while((i>=0)&&((calc[i]>='0'&&calc[i]<='9')||(calc[i]=='.'))) { loop2: expr[++t]=calc[i--]; } if((i>=0)&&((i==0&&calc[i]!='(')||(calc[i]=='+'||calc[i]=='-')&&!(calc[i-1]>='0'&&calc[i-1]<='9')&&calc[i-1]!=')')) goto loop2; expr[++t]=' '; } else if(calc[i]==')') { SymPush(); } else if(calc[i]=='(') { while(Sym.data[Sym.top]!=')') { SymPop(); expr[++t]=' '; } Sym.data[Sym.top--]='\\0'; i--; } else if(calc[i]=='+'||calc[i]=='-') { while(Sym.top>=0&&Sym.data[Sym.top]!=')'&&Sym.data[Sym.top]!='+'&&Sym.data[Sym.top]!='-') { SymPop(); expr[++t]=' '; } SymPush(); } else if(calc[i]=='*'||calc[i]=='/') { while(Sym.top>=0&&Sym.data[Sym.top]=='^') { SymPop(); expr[++t]=' '; } SymPush(); } else if(calc[i]=='^') { SymPush(); } else { i--; } } while(Sym.top>=0) { SymPop(); expr[++t]=' '; } expr[++t]=Sym.data[++Sym.top]='\\0'; for(i=0;i<=(t-2)/2;i++) { ch=expr[i]; expr[i]=expr[(t-2)-i]; expr[(t-2)-i]=ch; } printf("前缀表达式:%s\",expr); for(i=t-2;i>=0;i--) { if((expr[i]>='0'&&expr[i]<='9')||((expr[i]=='+'||expr[i]=='-')&&(expr[i+1]>='0'&&expr[i+1]<='9'))) { NumPush(); } else { NumPop(); } } printf("运算结果为:%g\",Num.data[0]); printf("Continue(y/n)?"); ch=getch(); switch(ch) { case 'y':{system("cls");goto loop1;} case 'n': default :exit(0); } getch(); return(0); } 后缀表达式转前缀表达式var a:array[1..1000] of string; s:string; i,j,k,l,v:longint; begin readln(s); j:=0; l:=length(s); for i:=1 to l do begin if not(s[i]in['+','-','*','/']) then begin j:=j+1; a[j]:=s[i]; end else begin if (j>1)and(s[i]in['/'])and(s[i-1]in['*','/']) then a[j]:='('+a[j]+')'; j:=j-1; a[j]:=a[j]+s[i]+a[j+1]; if (i<l)and(s[i]in['+','-']) then begin k:=i; v:=0; repeat k:=k+1; if s[k]in['+','-','*','/'] then v:=v-1 else v:=v+1; until (k=l)or(v<1); if (k<l)and(s[k]in['*','/']) then a[j]:='('+a[j]+')'; end; end; end; writeln(a[1]); end. |
随便看 |
百科全书收录4421916条中文百科知识,基本涵盖了大多数领域的百科知识,是一部内容开放、自由的电子版百科全书。