- 中綴表達式指的是"1+2-3*4/5"這種其實就是我們通常見到的書寫算式順序,要計算中綴表達式則首先要將字符串轉換成后綴表達式並存儲在一個隊列當中,即1 2 3 4 5 / * - +(空格只是為了隔開方便理解),可以看到數字都集中在了前面,算術符號則集中在后面。然后計算后綴表達式的方式便是從開頭遍歷,遇到數字則入棧,遇到符號便pop()兩個數字出來進行運算,然后再入棧,最后只剩一個數據在棧頂即最終結果。
- 要注意的細節是,讀取的數字可能不只一位,可能為負數,可能為小數,按題目具體情況分析
- 一開始讀取的字符串當中可能有多余的空格,但題目可能不會提醒,遍歷的時候要順便進行特判
- 運算符號之間的優先等級通過map建立映射關系:$(*==/) > (+==-)$ 當前符號優先級高於棧頂操作符則入棧,如果低於或等於則將不停出棧直至棧空了或者符合當前符號優先級高於棧頂的符號優先級。(因為越早進入隊列的符號意味着越早進行運算,所以優先級高的自然早過優先級低的,相同優先級的時候影響的是結合律:$(a*b/c) != (a*(b/c))$) 因此也相同的時候也要出棧。
- 遍歷一遍過后,如果棧中還剩符號,則依次全部出棧並push進隊列中形成后綴表達式。
- 如果題目出現括號的話,那么遍歷的時候就加入一個判斷,如果是左括號'(',就像其他符號一樣入棧,但是遇到右括號')'的時候就不入棧,然后直接就符號不停地出棧,直到遇到左括號就停止出棧。注意括號是不會出現在后綴表達式中的,影響的只是計算的順序。
- 在計算的過程中可能會出現非法運算,注意進行特判
1 #include <iostream> 2 #include <string> 3 #include <map> 4 #include <stack> 5 #include <queue> 6 7 8 9 10 11 using namespace std; 12 13 struct node 14 { 15 double num; // 也可以改成 int 具體情況具體分析 16 char op; // 存儲符號 17 bool flag; // true代表數字 false代表符號 18 }; 19 20 string str; 21 stack s; 22 queue q; 23 map<char,int> m; 24 25 void Change() // 中綴表達式轉換為后綴表達式 26 { 27 double num; 28 node temp; 29 for(int i=0;i<str.length();) { if(str[i]>='0' && str[i]<='9') 30 { 31 temp.flag = 1; 32 temp.num = str[i++] - '0'; 33 while(i<str.length() && str[i]>='0' && str[i]<='9') 34 { 35 temp.num = temp.num*10 + (str[i]-'0'); 36 ++i; 37 } 38 q.push(temp); 39 } 40 else if(str[i]==' ') 41 { 42 ++i; 43 } 44 else 45 { 46 temp.flag = 0; 47 while(!s.empty() && m[str[i]]<=m[s.top().op]) 48 { 49 q.push(s.top()); 50 s.pop(); 51 } 52 temp.op = str[i]; 53 s.push(temp); 54 ++i; 55 } 56 } 57 while(!s.empty()) //轉換結束后棧為空,隊列保存的是一個完整的后綴表達式 58 { 59 q.push(s.top()); 60 s.pop(); 61 } 62 } 63 64 double cal() 65 { 66 double temp1,temp2; 67 while(!q.empty()) //將隊列遍歷,最終結果保存在棧里 68 { 69 node head = q.front(); 70 q.pop(); 71 if(head.flag == 1) 72 { 73 s.push(head); 74 } 75 else if(head.flag == 0) 76 { 77 node b = s.top(); //第一次彈出的是第二操作數 78 s.pop(); 79 node a = s.top(); //第二次彈出的是第一操作數 80 s.pop(); 81 node c; 82 c.flag = 1; 83 if(head.op == '+') 84 { 85 c.num = a.num + b.num; 86 } 87 else if(head.op == '-') 88 { 89 c.num = a.num - b.num; 90 } 91 else if(head.op == '*') 92 { 93 c.num = a.num * b.num; 94 } 95 else if(head.op == '/') //有可能出現除以零的非法,要特判,不過這里沒寫 96 { 97 c.num = a.num / b.num; 98 } 99 s.push(c); 100 } 101 } 102 return s.top().num; 103 } 104 105 int main() 106 { 107 m['+'] = m['-'] = 0; //設置優先級 108 m['*'] = m['/'] = 1; 109 getline(cin,str); 110 Change(); 111 cout << cal() << endl; 112 return 0; 113 }