表達式求值(無括號)
阿新 • • 發佈:2018-10-14
code ESS truct alc expr 計算 利用 一個 一次
對於自然數的表達式求值,操作有加、減、乘、除和冪運算,分別用+,-, *, /,^來表示,為方便運算,加入#運算符,其運算優先級最低,由於運算符優先級不一樣,可以利用棧實現此操作。
算法思想
(1)規定運算符的優先級表
(2)設置兩個棧:OVS(運算數棧)和OPTR(運算符棧),為了操作方便可以先在OPTR棧中先放一個#運算符
(3)自左向右掃描,進行如下處理:
若遇到運算數則金OVS棧;若遇到運算符則與OPTR棧頂運算符進行比較:
?如果當前運算符的優先級大於OPTR棧頂運算符的優先級,則當前運算符進入OPTR棧;
?如果當前運算符的優先級大於等於OPTR棧頂運算符的優先級,則OPTR退棧一次,得到棧頂運算符op, 連續退棧OVS兩次,得到運算數a和b,執行op運算,得到結果T,將T進OVS棧。
可以自己畫一個表達式兩個棧的變化圖,有助於理解
#include<stdio.h> #include<stdlib.h> #include<math.h> #include<stdbool.h> typedef struct node{ int data;//無論對於運算符還是運算數,都用int型變量來保存 node *next; }LinkStackNode, *LinkStack; void InitStack(LinkStack *S){//初始化鏈棧 *S = (LinkStack)malloc(sizeof(LinkStackNode)); (*S)->next = NULL; } int Push(LinkStack top, int x){// 進棧操作 LinkStackNode *temp; temp = (LinkStackNode*)malloc(sizeof(LinkStackNode)); if(temp == NULL) return 0; temp->data = x; temp->next = top->next; top->next = temp; return 1; } intPop(LinkStack top, int *x){//出棧操作 LinkStackNode *temp; temp = top->next; if(temp == NULL) return 0; *x = temp->data; top->next = temp->next; free(temp); return 1; } int GetNum(char ch){//返回字符對應的數字 return ch - ‘0‘; } bool IsEmpty(LinkStack top){//棧為空返回假 if(top->next == NULL) return false; return true; } int GetTop(LinkStack top){//返回棧頂元素 if(top->next == NULL) return 1; return top->next->data; } char Compare(char ch1, char ch2){//實現運算符優先級比較 switch(ch1){ case ‘#‘: switch(ch2){ case ‘#‘: return ‘=‘; case ‘+‘: case ‘-‘: case ‘*‘: case ‘/‘: case ‘^‘: return ‘<‘; } case ‘+‘: switch(ch2){ case ‘#‘: return ‘>‘; case ‘+‘: case ‘-‘: return ‘=‘; case ‘*‘: case ‘/‘: case ‘^‘: return ‘<‘; } case ‘-‘: switch(ch2){ case ‘#‘: return ‘>‘; case ‘+‘: case ‘-‘: return ‘=‘; case ‘*‘: case ‘/‘: case ‘^‘: return ‘<‘; } case ‘*‘: switch(ch2){ case ‘#‘: case ‘+‘: case ‘-‘: return ‘>‘; case ‘*‘: case ‘/‘: return ‘=‘; case ‘^‘: return ‘<‘; } case ‘/‘: switch(ch2){ case ‘#‘: case ‘+‘: case ‘-‘: return ‘>‘; case ‘*‘: case ‘/‘: return ‘=‘; case ‘^‘: return ‘<‘; } case ‘^‘: switch(ch2){ case ‘#‘: case ‘+‘: case ‘-‘: case ‘*‘: case ‘/‘: return ‘>‘; case ‘^‘: return ‘=‘; } } } int Calculate(int a, char op, int b){//計算 a op b 的值 int c; switch(op){ case ‘-‘: c = a - b; break; case ‘+‘: c = a + b; break; case ‘*‘: c = a * b; break; case ‘/‘: c = a / b; break; case ‘^‘: c = pow(a, b); break; default : c = 0; } return c; } int ExpEvaluation(){//實現 LinkStack ovs, optr; InitStack(&ovs); InitStack(&optr); Push(optr, (int)‘#‘); printf("\n\nPlease input an expression(Ending with ‘#‘):\n"); char ch = getchar(); int num = 0, a, b, t, op, zan; while(ch != ‘#‘ || (char)GetTop(optr) != ‘#‘){ while(ch >= ‘0‘ && ch <= ‘9‘){//如果數字不是一位數字,便把字符轉化為數字 num = num * 10 + GetNum(ch); ch = getchar(); } if(num != 0){//如果num不為0便進OVS棧 Push(ovs, num); num = 0;//把num置零 } else{ switch(Compare(ch, (char)GetTop(optr))){//對運算符優先級進行比較,實現對應三種關系的操作 case ‘>‘: Push(optr, (int)ch); ch = getchar(); break; case ‘=‘: case ‘<‘: Pop(optr, &op); Pop(ovs, &a); Pop(ovs, &b); t = Calculate(a, (char)op, b); Push(ovs, t); break; } } } t = GetTop(ovs);//取棧頂元素,返回值 return t; } int main(){ int ans = ExpEvaluation(); printf("%d\n", ans); return 0; }
表達式求值(無括號)