定義
- 中綴表達式:平常我們手動輸入的表達式、計算式,都是中綴表達式,按照我們理解的運算優先順序進行計算。按照人的思維方式進行表達式的輸入,最終輸出預期結果。比如 1 + (2 + 3) × 4 - 5
- 后綴表達式、前綴表達式:雖然中綴表達式是按照我們肉眼的運算符優先級寫出的,但是最終實現這個運算的,比如計算器是沒有這么智能的,計算器只會按照輸入的運算符一個一個的進行計算。這時候就用到了后綴、前綴表達式。比如:后綴表達式針對於上面的就是 1 2 3 + 4 × + 5 -
手動實現
-
那么我們怎么實現中綴轉換為后綴呢?
手動實現:把所有運算按照優先級加上括號,然后把運算符號移動到括號前面,然后去除括號。
比如:1 + (2 + 3) × 4 - 5
加括號:
1 +( (2 + 3) × 4 ) - 5
(1 +( (2 + 3) × 4 )) - 5
((1 +( (2 + 3) × 4 )) - 5)
運算符號后移,並去除括號:
1 2 3 + 4 × + 5 -
前綴表達式,就是符號前移,一樣的
2.計算機怎么去識別后綴呢
使用大名鼎鼎的棧就很方便的實現了
棧的特點是先進后出,后進先出
針對於后綴表達式
1. 遇到數字入棧
2. 遇到運算符,彈出棧的兩個數字,然后和運算符進行運算
3. 重復過程
4. 因為后綴表達式,其實已經是把運算符優先級順序換一種表示形式,展現出來了而已
程序實現
說了一大推,我們首先來看一下程序上的實現一個對中綴表達式進行輸入,然后進行轉換,並進行結果的輸出
步驟
1. 中綴表達式轉化為后綴表達式
2. 進行后綴表達式的計算
第一步
程序思路:
-
定義棧S1,存儲運算符。定義棧S2,存儲數字和運算符,存儲最終的后綴表達式
-
對於新字符進行判斷只要新字符不等於‘\0’,一直進行下面的循環:
-
如果S1的大小為空, 字符入S1
-
如果是( 入棧
-
如果是),將S1知道(之前的運算符出棧,添加到S2中
-
如果S1的大小不為空,並且S1棧頂的運算符優先級大於當前的新字符或者兩個字符是相等的
那么當前的S1棧頂就可以出棧,添加到S2中
新字符入棧S1
-
如果新字符的范圍是‘0’ - ’9‘之間,那么新字符添加進S2中
-
否則,添加到S1中
-
-
跳出循環后,如果S1的size不為空,把S1的運算符一一彈出,添加到S2中,最終S2就是排列好的后綴表達式
-
然后就可以進行運算
代碼,使用c++
int weight(const char code) { if((code == '+') || (code == '-')) { return 1; } else if((code == '*') || (code == '/')) { return 2; } } bool priority(const char left, const char right) { if(left == '(') { return false; } else if(weight(left) < weight(right)) { return false; } else { return true; } } bool caculation(const char* input, LinkStack<char>& S2) { if(input == NULL) { return false; } bool ret = true; LinkStack<char> S1; int i = 0; int out_index = 0; while(ret && (input[i] != '\0')) { if(input[i] == '(') { S1.push(input[i]); } else if((S1.size() > 0) && (input[i] == ')')) { char code = S1.get(); while(code != '(') { S2.push(code); S1.pop(); code = S1.get(); } if(code == '(') { S1.pop(); } } else if((S1.size() > 0) && priority(S1.get(), input[i])) { std::cout << "13" << std::endl; char code = S1.get(); S2.push(code); S1.pop(); S1.push(input[i]); } else if( (input[i] >= '0') && (input[i] <= '9')) { S2.push(input[i]); } else { S1.push(input[i]); } i++; } while(S1.size() > 0) { char code = S1.get(); S2.push(code); S1.pop(); } return ret; }
- 核心函數就是上面的兩個,輸入參數1是中綴表達式,輸入參數2是棧,最終棧中存儲排序好的后綴表達式
- 拿一個例子來演示一下:
6.
說明
后綴表達式,這種方式后計算優點也很大,直接從上到下,數字就入棧,符號就把當前棧中的連續兩個彈出,然后和當前符號進行運算,然后再入數字棧。