栈应用:后缀表达式求值
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                栈应用:后缀表达式求值
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                在上一篇博客?棧應用:中綴表達式轉后綴表達式?中我們知道如何通過棧將中綴表達式轉為后綴表達式,這次我們繼續用棧 來實現后綴表達式求值,結合上一篇博客。
上一篇博客中是用c語言實現的,由于c語言中不支持模板函數模板類,當我們遇到不同數據類型那么我們用結構體定義棧結構需要同時定義多個,那么對應的棧操作也需要定義多個,為了方便,我們將棧的實現用c++ 來實現,因為c++中有模板呀,可以很方便的構造不同數據類型的棧。
后綴表達式計算規則
摘自 大話數據結構中的定義。后綴表達式計算規則:從左到右遍歷表達式的每個數字和符號,遇到數字就進棧,遇到是符號,就將處于棧頂2個數字出棧,進行運算,運算結果進棧,一直到最終獲取結果。
后綴表達式規則分析
比較中綴表達式轉后綴表達式的規則,后綴表達式的計算規則簡單的多,就是后綴表達式中數值的入棧出棧問題。
遇到數字就進棧,遇到符號,就將棧頂2個元素進行彈棧,然后進行相應的符號計算,將計算結果入棧。
當整個表達式計算完畢,此時值棧中的只有1個數值,它就是整個表達式的值。
后綴表達式值計算局部代碼
/* 通過棧對后綴表達式進行求值 */ double GetResultAfterExp(const char* afterExp) {if (NULL == afterExp){return 0;}// a b 是表達式中的2個操作數double a = 0;double b = 0;int k = 0;// afterExp 下標char ch = 0;//后綴表達式中的字符char numBuf[10] = { 0 };//連續的數字不能超過10位,也就是后綴表達式中數字不能超過10位int numIndex = 0;//numBuf 下標SeqStack<double> stack;InitStack(&stack);while (afterExp[k]){ch = afterExp[k++];//是數值if (ch >= '0'&&ch <= '9'){while (((ch >= '0'&&ch <= '9') || ch == '.') && numIndex < 10){numBuf[numIndex++] = ch;ch = afterExp[k++];}numBuf[numIndex] = 0;double num = atoi(numBuf);push(&stack, num);}//是符號或者空格if (ch< '0' || ch > '9'){numIndex = 0;//進入這個if 數字肯定不連續了,下標重置為0// 是空格if (' ' == ch){continue;}else{double c = 0;switch (ch){case '+':pop(&stack, &a);pop(&stack, &b);c = b + a;push(&stack,c);break;case '-':pop(&stack, &a);pop(&stack, &b);c = b - a;push(&stack, c);break;case '*':pop(&stack, &a);pop(&stack, &b);c = b * a;push(&stack, c);break;case '/':pop(&stack, &a);pop(&stack, &b);c = b / a;push(&stack, c);break;default://throw "后綴表達式錯誤";//printf("后綴表達式錯誤\n");return 0;break;}}}afterExp++;}//計算完畢 將計算結果從棧中彈出if (IsEmptyStack(&stack)){//throw "后綴表達式錯誤";printf("后綴表達式錯誤\n");return 0;}pop(&stack, &a);return a; }
后綴表達式值計算完整代碼
代碼結構和?棧應用:中綴表達式轉后綴表達式?中的代碼結構一致,將中綴表達式轉后綴表達式整合進來了,將c代碼改成c++代碼了。
#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstdlib> #include <math.h> #include <memory.h> #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define STACK_INIT_SIZE 20 // 棧初始容量 #define STACK_INCREMENT 10 //棧滿后,每次擴充的容量 #define EXPRESS_MAX 1024 //后綴表達式 長度不能超過1024 typedef int Status;template<class EleType> struct SeqStack {EleType* top;//棧頂指針EleType* base;//棧底指針int stackSize;//棧容量 };//初始化棧 template<class EleType> Status InitStack(SeqStack<EleType>* stack) {//開辟空間stack->base = stack->top = (EleType*)malloc(STACK_INIT_SIZE * sizeof(EleType));if (!stack->base){exit(0);}stack->stackSize = STACK_INIT_SIZE;return OK; } //壓棧 template<class EleType> Status push(SeqStack<EleType>* stack, EleType e) {if (stack == NULL){return ERROR;}//壓棧之前檢測容量是否足夠if (stack->top - stack->base == stack->stackSize){//超出容量 進行擴容,使用realloc函數,會拷貝原內存內容stack->base = (EleType*)realloc(stack->base, stack->stackSize + STACK_INCREMENT);if (!stack->base){exit(0);}stack->top = stack->base + stack->stackSize;stack->stackSize += STACK_INCREMENT;}*stack->top = e;stack->top++;return OK; } //彈棧 template<class EleType> Status pop(SeqStack<EleType>* stack, EleType *e) {if (stack == NULL || e == NULL){return ERROR;}//空棧if (stack->top == stack->base){return ERROR;}*stack->top--;*e = *stack->top;return OK; } /* 獲取棧頂元素 */ template<class EleType> Status GetTop(SeqStack<EleType>* stack, EleType *e) {if (NULL == stack) {return ERROR;}*e = *(stack->top - 1);return OK; } /* 判斷棧是否為空 */ template<class EleType> int IsEmptyStack(SeqStack<EleType>* stack) {if (NULL == stack) {return ERROR;}if (stack->top == stack->base) {return TRUE;}return FALSE; } /* 銷毀棧 */ template<class EleType> Status DestroyStack(SeqStack<EleType>* stack) {if (NULL == stack) {return ERROR;}//銷毀棧 是釋放棧在內存中占用的空間資源if (!stack->base){free(stack->base);}stack->top = stack->base = NULL;stack->stackSize = 0;return OK; }char* MidExpToAfterExp(const char* midExp) {//后綴表達式char* afterExp = (char*)malloc(sizeof(char)*EXPRESS_MAX);memset(afterExp, 0, EXPRESS_MAX);int j = 0;//afterExp下標int k = 0;//preExp下標SeqStack<char> stack;// + - * / ( )符號棧InitStack(&stack);char numBuf[10] = { 0 };//連續的數字不能超過10位,也就是中綴表達式中數字不能超過10位char ch = 0;int numIndex = 0;//numBuf 下標while (midExp[k]){ch = midExp[k++];//忽略中綴表達式中的空格if (ch == ' '){continue;}//回車代表中綴輸入完畢if ('\n' == ch){break;}//1、若是數字就輸出if (ch >= '0' && ch <= '9'){//如果輸入連續的數字,不是連續的數字 循環完畢 會走 2、非數字while (((ch >= '0' && ch <= '9') || '.' == ch) && numIndex < 10){numBuf[numIndex++] = ch;afterExp[j++] = ch;ch = midExp[k++];}numBuf[numIndex] = 0;afterExp[j++] = ' ';}//回車代表中綴輸入完畢if ('\n' == ch){break;}//忽略中綴表達式中的空格else if (' ' == ch){continue;}//2、非數字else if (ch < '0' || ch > '9'){numIndex = 0;//進入這個if 數字肯定不連續了,下標重置為0//右括號一定彈棧if (')' == ch){int flag = 1;//判斷中綴表達式中括號是否匹配,如果成對出現while (!IsEmptyStack(&stack)){pop(&stack, &ch);if ('(' == ch){flag = 0;//走到這里說明是()括號成對出現break;}afterExp[j++] = ch;afterExp[j++] = ' ';}if (flag){printf("中綴表達式輸入錯誤\n");//exit(0);return NULL;}}// + - 符號是優先級最低的,一定是先依次彈棧再壓棧。else if ('+' == ch || '-' == ch){char top;GetTop(&stack, &top);//棧空或者棧頂為左括號 直接壓棧if (IsEmptyStack(&stack) || '(' == top){push(&stack, ch);}else{char cur = ch;while (!IsEmptyStack(&stack)){pop(&stack, &ch);if ('(' == ch){//不是因為)右括號而彈棧,多彈的(左括號壓回去push(&stack, ch);break;}afterExp[j++] = ch;afterExp[j++] = ' ';}push(&stack, cur);}}// * / 符號優先級只比 + -高,棧空或棧頂為(+-符號棧才直接壓棧,其他情況先依次彈棧再壓棧else if ('*' == ch || '/' == ch){char top;GetTop(&stack, &top);//棧空或者棧頂為左括號同樣直接壓棧if (IsEmptyStack(&stack) || '(' == top || '-' == top || '+' == top){push(&stack, ch);}else if ('*' == top || '/' == top){char cur = ch;while (!IsEmptyStack(&stack)){pop(&stack, &ch);if ('(' == ch || '-' == ch || '+' == ch){//不是因為)右括號而彈棧 * / 優先級高于棧頂 + - 就不彈棧了,多彈的壓回去push(&stack, ch);break;}afterExp[j++] = ch;afterExp[j++] = ' ';}push(&stack, cur);}}else if ('(' == ch){push(&stack, ch);}else{printf("中綴表達式輸入錯誤\n");//exit(0);return NULL;}}}//符號棧內容不為空 依次出棧并打印while (!IsEmptyStack(&stack)){pop(&stack, &ch);afterExp[j++] = ch;afterExp[j++] = ' ';}return afterExp; } /* 通過棧對后綴表達式進行求值 */ double GetResultAfterExp(const char* afterExp) {if (NULL == afterExp){return 0;}// a b 是表達式中的2個操作數double a = 0;double b = 0;int k = 0;// afterExp 下標char ch = 0;//后綴表達式中的字符char numBuf[10] = { 0 };//連續的數字不能超過10位,也就是后綴表達式中數字不能超過10位int numIndex = 0;//numBuf 下標SeqStack<double> stack;InitStack(&stack);while (afterExp[k]){ch = afterExp[k++];//是數值if (ch >= '0'&&ch <= '9'){while (((ch >= '0'&&ch <= '9') || ch == '.') && numIndex < 10){numBuf[numIndex++] = ch;ch = afterExp[k++];}numBuf[numIndex] = 0;double num = atoi(numBuf);push(&stack, num);}//是符號或者空格if (ch< '0' || ch > '9'){numIndex = 0;//進入這個if 數字肯定不連續了,下標重置為0// 是空格if (' ' == ch){continue;}else{double c = 0;switch (ch){case '+':pop(&stack, &a);pop(&stack, &b);c = b + a;push(&stack,c);break;case '-':pop(&stack, &a);pop(&stack, &b);c = b - a;push(&stack, c);break;case '*':pop(&stack, &a);pop(&stack, &b);c = b * a;push(&stack, c);break;case '/':pop(&stack, &a);pop(&stack, &b);c = b / a;push(&stack, c);break;default://throw "后綴表達式錯誤";//printf("后綴表達式錯誤\n");return 0;break;}}}afterExp++;}//計算完畢 將計算結果從棧中彈出if (IsEmptyStack(&stack)){//throw "后綴表達式錯誤";printf("后綴表達式錯誤\n");return 0;}pop(&stack, &a);return a; }int main(int argc, char *argv[]) {while (1){printf("請輸入中綴表達式(#表示退出):");//中綴表達式char* midExp = (char*)malloc(sizeof(char)*EXPRESS_MAX);memset(midExp, 0, EXPRESS_MAX);fgets(midExp, 1024, stdin);//midExp 包含換行符if ('#' == midExp[0]){break;}SeqStack<char> charStack;//后綴表達式char* afterExp = MidExpToAfterExp(midExp);printf("對應的后綴表達式:%s\n", afterExp);double result = GetResultAfterExp(afterExp);printf("表達式計算結 果:%.2f\n", result);}return 0; }
驗證結果
總結
以上是生活随笔為你收集整理的栈应用:后缀表达式求值的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: PHP 图像编辑GD库的使用以及图像的压
- 下一篇: ag-grid 表格中添加图片
