中綴表示式轉化為字尾表示式(逆波蘭表示式)
阿新 • • 發佈:2018-11-23
1.將中綴表示式轉化為字尾表示式
字尾表示式也叫作逆波蘭表示式,主要是運用棧的後進先出思想,下面就講講我自己的思考,
假設中綴表示式為:2*(2+1)-6(4-2)#,則字尾表示式為:2 2 1 + * 6 4 2 - / -;
首先依次遍歷中綴表示式,遇到運算元字元則直接輸出(數字字元大小區間在 ‘0’~‘9’),遇到操作符字元則依次入棧,其中操作符入棧條件:
- 若棧中沒有元素,即棧空,無條件入棧。
- 若為左括號“( ”,無條件入棧。
- 若為右括號" ) ",則依次輸出棧中的運算子,直到遇到左括號“(”為止。
- 若為非括號操作符,則比較此時遍歷到的操作符和棧頂元素,並判斷元素優先順序(優先順序和平常運算的先後一樣),如果棧頂的元素優先順序較高或者相等,則彈出棧頂元素並輸出,將遍歷到的操作符入棧。若遍歷的操作符優先順序較高,則直接入棧。
- 遍歷到“#”時,結束遍歷,判斷棧是否為空,若棧不為空,依次輸出棧頂元素,直至棧為空。
注意:右括號“)”不進棧,只是為了更好地表達,實際不進棧
也可以參考這篇,比較詳細:中綴表示式轉換為字尾表示式
附上自己寫的程式碼吧!!
// nibolanbiaodashi.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "stdlib.h" typedef char Elemtype; #define STACKINITSIZE 100 #define STACKINCREMENT 10 typedef struct SQSTACK{ Elemtype *top; Elemtype *base; int stacksize; }Sqstack; typedef struct{ Elemtype data[STACKINITSIZE]; int length; }SqList; void InitList(SqList *L) { (*L).length=0; } void InitStack(Sqstack *S) { (*S).base=(Elemtype *)malloc(STACKINITSIZE * sizeof(Elemtype)); (*S).top=(*S).base; (*S).stacksize=STACKINITSIZE; } void Push(Sqstack *S,Elemtype e) { if((*S).top-(*S).base>=(*S).stacksize) { (*S).base=(Elemtype *)realloc((*S).base,((*S).stacksize+STACKINITSIZE)*sizeof(Elemtype)); (*S).top=(*S).base+(*S).stacksize; (*S).stacksize=(*S).stacksize+STACKINCREMENT; } *((*S).top)=e; (*S).top++; } void Pop(Sqstack *S,Elemtype *e) { if((*S).top == (*S).base) return; e=(*S).top; (*S).top--; } void GetPop(Sqstack S,Elemtype *e) { if(S.base==S.top) return; *e=*(S.top-1); } int EmptyStack(Sqstack S) { if(S.base == S.top) return 1; return 0; } int Precede(Elemtype e,Elemtype a) { Elemtype book; if((e == '+'||e == '-') && (a == '+'||a == '-')) book='='; if((e == '+'||e == '-') && (a == '*'||a == '/')) book='<'; if((e == '*'||e == '/') && (a == '+'||a == '-')) book='>'; if((e == '*'||e == '/') && (a == '*'||a == '/')) book='='; if(e=='(') book='<'; return book; } void InversePolandExpression(Sqstack S,Elemtype str[],SqList *L)//逆波蘭 { int i=0,j=0; Elemtype book; Elemtype e; printf("逆波蘭表示式:\n"); while(str[i]!='#') { if(str[i]>='0' && str[i]<='9') { (*L).data[j]=str[i]; (*L).length++; j++; printf(" %c ",str[i]); } else { if(str[i]=='(') Push(&S,str[i]); if(str[i]==')') { GetPop(S,&e); while(e!='(') { Pop(&S,&e); (*L).data[j]=e; j++; (*L).length++; printf(" %c ",e); GetPop(S,&e); if(e=='(') Pop(&S,&e); } } if(str[i]=='+' || str[i]=='-' || str[i]=='*' || str[i]=='/') { if(EmptyStack(S)) Push(&S,str[i]); else { GetPop(S,&e); book=Precede(e,str[i]); switch(book) { case '<' : Push(&S,str[i]); break; case '=' : Pop(&S,&e); (*L).data[j]=e; j++; (*L).length++; printf("%c",e); Push(&S,str[i]); break; case '>' : Pop(&S,&e); (*L).data[j]=e; j++; (*L).length++; printf("%c",e); Push(&S,str[i]); break; } } } } i++; } while(!EmptyStack(S)) { GetPop(S,&e); (*L).data[j]=e; j++; (*L).length++; printf(" %c ",e); Pop(&S,&e); } printf("\n"); } /*void print(SqList *L) { int i=0; while(i<(*L).length) { printf("%c",(*L).data[i]); i++; } printf("\n"); }*/ int Calculate(Elemtype a,Elemtype b,Elemtype OPTR) { int n; if(OPTR=='+') { n=(a-48)+(b-48); } if(OPTR=='-') { n=(b-48)-(a-48); } if(OPTR=='*') { n=(a-48)*(b-48); } if(OPTR=='/') { n=(b-48)/(a-48); } return n; } void calvalInverPoland(SqList L)//字尾表示式求值 { int i=0; int n; Elemtype ch; Elemtype a,b,e; Sqstack OPND; InitStack(&OPND); printf("逆波蘭表示式求值 : "); while(i<L.length) { if(L.data[i]>='0' && L.data[i]<='9') { Push(&OPND,L.data[i]); } else { GetPop(OPND,&a); Pop(&OPND,&a); GetPop(OPND,&b); Pop(&OPND,&b); n=Calculate(a,b,L.data[i]); ch=n+48; Push(&OPND,ch); } i++; } GetPop(OPND,&e); printf("%c",e); printf("\n"); } int main(int argc, char* argv[]) { Sqstack S; SqList L; char str[20]="2*(2+1)-6/(4-2)#"; printf("Please end with '#'\n"); //scanf("%s",str); InitList(&L); InitStack(&S); InversePolandExpression(S,str,&L); calvalInverPoland(L); return 0; }
後面因為臨時加入了字尾表示式求值,就用了一個線性表來儲存字尾表示式。