日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

栈应用:中缀表达式转后缀表达式

發布時間:2025/3/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 栈应用:中缀表达式转后缀表达式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

網上有很多關于中綴轉后綴的文章,很多文章或多或少都有bug,包括一些教學視頻,經過本人無數次測試,保證下面的代碼運算結果的正確性前提是你寫的中綴表達式是正確的哈,沒有做中綴表達式是否正確的的完整性校驗。采用的c語言編寫的哈。


中綴、后綴表達式區別

?

?

中綴表達式:(或中綴記法)是一個通用的算術或邏輯公式表示方法, 操作符是以中綴形式處于操作數的中間(例:3 + 4),中綴表達式是人們常用的算術表示方法

?

后綴表達式:后綴表達式,指的是不包含括號,運算符放在兩個運算對象的后面,所有的計算按運算符出現的順序,嚴格從左向右進行(不再考慮運算符的優先規則)

可以通過 2個表達式計算的結果,證明是否轉換正確

中綴、轉后綴規則

規則摘抄大話數據結構中的描述 ,中綴表達式轉后綴表達式規則:

從左到右遍歷中綴表達式的每個數字和符號,若是數字就輸出,即成為后綴表達式的一部分;
若是符號,則判斷其與棧頂符號的優先級,是右括號或者優先級低于棧頂符號(乘除優先加減,)

則棧頂元素依次出棧并輸出,并將當前符號進棧,一直到最終輸出后綴表達式為止

?

中綴、轉后綴規則分析

?

?

首先判斷字符是否是數字

?

  • 是數字直接輸出
  • 非數字再對字符進行分析
  • 右括號,依次彈棧并輸出符號,直到遇到(左括號
  • 字符優先級低于棧頂符號依次彈棧直到遇到字符優先級高于棧頂符號或者遇到左括號或者空棧,當前符號再才進(壓)棧(如果和棧頂符號優先級一樣也要先棧頂符號也要先彈棧,因為優先級一樣運算順序是從左往右!這一點很重要,很多網上的文章或者視頻 都是這一點出錯了!)
  • + ?- 符號是優先級最低的,一定是先依次彈棧再壓棧
  • * / 符號優先級只比 + - 高,棧空或棧頂為( + - 符號棧才直接壓棧,其他情況先依次彈棧再壓棧
  • 左括號,左括號(直接壓棧,如果棧頂元素為左括號(,該字符同樣直接壓棧!這點很重要!
  • 中綴、轉后綴函數局部代碼

    將用戶輸入放到一個字符串,將轉換得到后綴表達式同樣放到一個字符串中,方便封裝進行復用。

    ?

    /* 將中綴表達式轉成后綴表達式 */ 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 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);}}// + - 符號是優先級最低的,一定是先依次彈棧再壓棧。else if ('+' == ch || '-' == ch){EleType 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){EleType 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);}}}//符號棧內容不為空 依次出棧并打印while (!IsEmptyStack(&stack)){pop(&stack, &ch);afterExp[j++] = ch;afterExp[j++] = ' ';}return afterExp; }

    ?

    ?

    ?

    ?

    ?

    ?

    完整代碼

    ?

    #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.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; typedef char EleType;typedef struct SeqStack {EleType* top;//棧頂指針EleType* base;//棧底指針int stackSize;//棧容量 }SeqStack; //初始化棧 Status InitStack(SeqStack* stack) {//開辟空間stack->base = stack->top = (EleType*)malloc(STACK_INIT_SIZE * sizeof(EleType));if (!stack->base){exit(0);}stack->stackSize = STACK_INIT_SIZE;return OK; } //壓棧 Status push(SeqStack* 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; } //彈棧 Status pop(SeqStack* stack, EleType *e) {if (stack == NULL || e == NULL){return ERROR;}//空棧if (stack->top == stack->base){return ERROR;}*stack->top--;*e = *stack->top;return OK; } /* 獲取棧頂元素 */ Status GetTop(SeqStack* stack, EleType *e) {if (NULL == stack) {return ERROR;}*e = *(stack->top - 1);return OK; } /* 判斷棧是否為空 */ int IsEmptyStack(SeqStack* stack) {if (NULL == stack) {return ERROR;}if (stack->top == stack->base) {return TRUE;}return FALSE; } /* 銷毀棧 */ Status DestroyStack(SeqStack* 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 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);}}// + - 符號是優先級最低的,一定是先依次彈棧再壓棧。else if ('+' == ch || '-' == ch){EleType 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){EleType 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);}}}//符號棧內容不為空 依次出棧并打印while (!IsEmptyStack(&stack)){pop(&stack, &ch);afterExp[j++] = ch;afterExp[j++] = ' ';}return afterExp; }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;}//后綴表達式char* afterExp= MidExpToAfterExp(midExp);printf("對應的后綴表達式:%s\n", afterExp);}return 0; }

    ?

    ?

    ?

    ?

    ?

    ?

    ?

    驗證結果

    進行復雜性驗證哈,確保程序正確性。如何驗證正確性呢?請看 后綴表達式運算規則,如果根據后綴表達式 的計算結果和中綴表達式計算結果一致就說明轉換正確如果不正確,你來找我

    ?

    ?

    總結

    以上是生活随笔為你收集整理的栈应用:中缀表达式转后缀表达式的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。