《資料結構》嚴蔚敏 演算法3.4 用棧實現表示式求值
阿新 • • 發佈:2019-01-12
emmmm 我又偷懶了,看了一下書上的演算法,總感覺不是很好的演算法,我覺得可以類比前面的符號匹配來進行表示式求值,但是今天有點不想寫了,先copy一個答案吧
原文連結:https://blog.csdn.net/hello_sheep/article/details/75635777
輸入
以“#”結尾的表示式,運算數為正整數。每個表示式佔一行。
輸出
輸出表達式運算的結果。
置運算子棧為空棧,表示式的起始符’#‘為棧底元素
依次讀入表示式的每個字元,
若是運算元則進OPND棧,
若是運算子則和OPTR棧的棧頂元素比較優先權後進行相應操作,
直至整個表示式求值完畢(即OPTR棧的棧頂元素和當前讀入的字元均為’#’)
#include<stdio.h> #include<string.h> #include<stdlib.h> #define N 1000+10 #define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 #define OK 1 #define OVERFLOW 0 #define ERROR 0 char str[N]; typedef int Status; typedef int SElemType; typedef struct{ SElemType *base; SElemType *top; int stacksize; }SqStack; unsigned char prior[7][7] = { {'>','>','<','<','<','>','>'}, {'>','>','<','<','<','>','>'}, {'>','>','>','>','<','>','>'}, {'>','>','>','>','<','>','>'}, {'<','<','<','<','<','=',' '}, {'<','<','<','<','<',' ','>'}, {'<','<','<','<','<',' ','='}}; char OPSET[7] = {'+','-','*','/','(',')','#'}; Status InitStack(SqStack *s)//初始化棧 { s->base = (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType)); if(!s->base) exit(OVERFLOW); s->top = s->base ; s->stacksize = STACK_INIT_SIZE; return OK; } Status Push(SqStack *s,SElemType c)//入棧 { if((s->top - s->base ) >= s->stacksize ) { s->base = (SElemType*)realloc(s->base ,(s->stacksize +STACKINCREMENT)*sizeof(SElemType)); if(!s->base ) exit(OVERFLOW); s->stacksize += STACKINCREMENT; } *(s->top)++ = c; return OK; } Status GetTop(SqStack *s)//取棧頂元素 { SElemType e; if(s->base == s->top ) return ERROR; e = *(s->top-1) ; return e; } Status In(char c,char str[])//判斷是否為運算子 { int i = 0; while(c != str[i]) { i++; } if(i < 7) return OK; return ERROR; } void Strcat(char *str1,char *str2)//字串連線函式,把字串str2連線到str1後 { int i = 0, j = 0; while(str1[i]!='\0') { i++; } while(str2[j]!='\0') { str1[i++] = str2[j++]; } str1[i] = '\0'; } Status Atoi(char *c)//把字串轉為數字 { int data= 0,d = 0; int i = 0; while(c[i]!='\0') { data = data*10 + c[i]-'0'; i++; } return data; } Status precede(int a,char b)//判斷優先順序函式 { int i = 0,j = 0; while(OPSET[i] != a) { i++; } while(OPSET[j] != b) { j++; } return prior[i][j]; } Status Pop(SqStack *s)//脫括號函式 { int e; if(s->base == s->top ) return ERROR; e = *--(s->top); return e; } Status Opereta(int a,int b,int c)//運算函式 { switch(b) { case '+': return a+c; case '-': return a-c; case '*': return a*c; case '/': return a/c; } return OK; } int EvaluateExpression(char *MyExpression)//演算法3.4 {//算術表示式求值的算符優先演算法。 //設OPTR和OPND分別為運算子棧和運算數棧 SqStack OPTR;//運算子棧,字元元素 SqStack OPND;//運算數棧,實數元素 char TempData[20]; int data,a,b; char *c,Dr[2],e; int theta; InitStack(&OPTR); Push(&OPTR,'#'); InitStack(&OPND); c = MyExpression; TempData[0] = '\0'; while(*c != '#'|| GetTop(&OPTR) != '#') { if(!In(*c,OPSET))//不是運算子則進棧 { Dr[0] = *c; Dr[1] = '\0'; Strcat(TempData,Dr); c++; if(In(*c,OPSET))//是運算子時 { data = Atoi(TempData); Push(&OPND,data); TempData[0] = '\0'; } } else { switch(precede(GetTop(&OPTR),*c)) { case '<': Push(&OPTR,*c); c++; break; case '=': Pop(&OPTR); c++; break; case '>': a = Pop(&OPND); b = Pop(&OPND); theta = Pop(&OPTR); Push(&OPND,Opereta(b,theta,a)); break; } } } return GetTop(&OPND); } int main() { while(scanf("%s",str)!=EOF) { printf("%d\n",EvaluateExpression(str)); } return 0; }