字首表示式、中綴表示式、字尾表示式的定義及實現
阿新 • • 發佈:2020-08-09
定義
- 中綴表示式:平常我們手動輸入的表示式、計算式,都是中綴表示式,按照我們理解的運算優先順序進行計算。按照人的思維方式進行表示式的輸入,最終輸出預期結果。比如 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.
說明
字尾表示式,這種方式後計算優點也很大,直接從上到下,數字就入棧,符號就把當前棧中的連續兩個彈出,然後和當前符號進行運算,然後再入數字棧。