寫在前面:
只涉及到+、-、*、/、(、)這六種符號(如果有乘方什么的話不要怕麻煩加幾個等級就好啦(~ ̄▽ ̄)~)
想法是這樣的:
- 將+、-、*、/四個基本運算符號分成兩個等級,+、-級別低,*、/等級較高;而括號單獨處理。
- 將輸入的字符串從左到右遍歷。
- 若當前字符是操作數則直接打印;
- 若當前字符是操作符,先判斷棧是否為空,若是,則直接將此操作符壓入棧,若不是,則查看當前棧頂元素,若棧頂元素:
- 是左括號;(經好心人指正,這里有錯誤,若棧頂元素是左括號是不應該打印並且彈出的,只有棧頂元素是低級操作符時才會打印彈出!)
- 比此操作符級別高;
- 與此操作符級別相同;
則打印並彈出棧頂元素並繼續進行上述判斷,若棧頂元素不符合上述三項所述(也就是說級別更低時),則直接將操作符壓入棧;(在這種情況下,記住最后這個操作符一定會被壓入棧內的)
- 若當前字符是左括號則直接壓入棧;
- 若當前字符是右括號則打印並彈出棧中第一個左括號前的所有操作符,並且將左括號彈出;(這里可以看到:遍歷到右括號后就會彈出對應的左括號及這一對括號中間的所有操作符,也就代表着這一級的結束;而且右括號永遠不入棧);
- 字符串遍歷結束后,若棧不為空,則彈出棧中所有元素直至棧為空。(注意:最后棧里面應該只有操作符,不可能有括號存在,否則一定有錯誤!)
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 }