用棧實現中綴表達式向后綴表達式的轉換


寫在前面:

只涉及到+、-、*、/、(、)這六種符號(如果有乘方什么的話不要怕麻煩加幾個等級就好啦(~ ̄▽ ̄)~)


想法是這樣的:

  • 將+、-、*、/四個基本運算符號分成兩個等級,+、-級別低,*、/等級較高;而括號單獨處理。
  • 將輸入的字符串從左到右遍歷。
  • 若當前字符是操作數則直接打印;
  • 若當前字符是操作符,先判斷棧是否為空,若是,則直接將此操作符壓入棧,若不是,則查看當前棧頂元素,若棧頂元素:
  1. 是左括號;(經好心人指正,這里有錯誤,若棧頂元素是左括號是不應該打印並且彈出的,只有棧頂元素是低級操作符時才會打印彈出!)
  2. 比此操作符級別高;
  3. 與此操作符級別相同;

   則打印並彈出棧頂元素並繼續進行上述判斷,若棧頂元素不符合上述三項所述(也就是說級別更低時),則直接將操作符壓入棧;(在這種情況下,記住最后這個操作符一定會被壓入棧內的)

  • 若當前字符是左括號則直接壓入棧;
  • 若當前字符是右括號則打印並彈出棧中第一個左括號前的所有操作符,並且將左括號彈出;(這里可以看到:遍歷到右括號后就會彈出對應的左括號及這一對括號中間的所有操作符,也就代表着這一級的結束;而且右括號永遠不入棧);
  • 字符串遍歷結束后,若棧不為空,則彈出棧中所有元素直至棧為空。(注意:最后棧里面應該只有操作符,不可能有括號存在,否則一定有錯誤!)
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 typedef struct Node
  5 {
  6     char ele;
  7     struct Node * next;
  8 }Node;
  9 
 10 typedef Node * Stack;
 11 
 12 Stack MakeStack(void)//新建棧並返回棧頂
 13 {
 14     Stack S = (Node *)malloc(sizeof(Node));
 15     S->next = NULL;
 16     return S;
 17 }
 18 
 19 void MakeNUll(Stack S)//置空棧
 20 {
 21     S->next = NULL;
 22 }
 23 
 24 void Pop(Stack S)//將棧頂彈出
 25 {
 26     Stack temp = S->next;
 27     S->next = temp->next;
 28 }
 29 
 30 void Push(Stack S, char c)//將新節點壓入棧
 31 {
 32     Stack temp = (Node *)malloc(sizeof(Node));
 33     temp->ele = c;
 34     temp->next = S->next;
 35     S->next = temp;
 36 }
 37 
 38 Stack FindHead(Stack S)//返回棧頂
 39 {
 40     Stack temp = S->next;
 41     return temp;
 42 }
 43 
 44 void PrintHead(Stack S)//打印棧頂元素
 45 {
 46     Stack temp = S->next;
 47     printf("%c", temp->ele);
 48 }
 49 
 50 int main(void)
 51 {
 52     Stack S = MakeStack();
 53     int i = 0;
 54     char str[200];
 55     printf("Type something.\n");
 56     gets(str);
 57 
 58     while(str[i] != '\0')
 59     {
 60         if(str[i] == '+' || str[i] == '-')//如果str[i]是加號或減號,則先彈出棧頂直到棧已空或棧頂元素為左括號,再將str[i]壓入棧
 61         {
 62             if(FindHead(S) == NULL)//若棧已空時,棧頂指針為空,找不到其元素,故須單獨討論
 63             {
 64                 Push(S, str[i]);
 65             }
 66             else
 67             {
 68                 while(FindHead(S)->ele == '+' || FindHead(S)->ele == '-' || FindHead(S)->ele == '*' || FindHead(S)->ele == '/')
 69                 {
 70                     PrintHead(S);
 71                     Pop(S);
 72                 }
 73                 Push(S, str[i]);
 74             }
 75         }
 76 
 77         else if(str[i] == '*' || str[i] == '/')//如果str[i]是乘號或除號,則只有棧頂也是乘除號時才需要彈出
 78         {
 79             if(FindHead(S) == NULL)
 80             {
 81                 Push(S, str[i]);
 82             }
 83             else
 84             {
 85                 while(FindHead(S)->ele == '*' || FindHead(S)->ele == '/')
 86                 {
 87                     PrintHead(S);
 88                     Pop(S);
 89                 }
 90                 Push(S, str[i]);
 91             }
 92         }
 93 
 94         else if(str[i] == '(')//如果str[i]是左括號則直接壓入棧
 95         {
 96             Push(S, str[i]);
 97         }
 98 
 99         else if(str[i] == ')')//如果str[i]是右括號,則打印並彈出棧中第一個左括號前的所有操作符,最后將此左括號直接彈出
100         {
101             while(FindHead(S)->ele != '(')
102             {
103                 PrintHead(S);
104                 Pop(S);
105             }
106             Pop(S);
107         }
108 
109         else//如果str[i]不是操作符則直接打印
110         {
111             printf("%c", str[i]);
112         }
113 
114         i++;
115     }
116 
117     while(FindHead(S) != NULL)//遍歷后如果棧不為空,則彈出所有操作符
118     {
119         PrintHead(S);
120         Pop(S);
121     }
122 
123     return 0;
124 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM