1、簡介
在數據結構中,有一種數據結構叫做:Stack,LIFO(Last In First Out),在這個結構中,有個後綴表達式計算,運用該數據結構進行計算。
棧是一種只允許一端操作的線性數據結構,具有LIFO(last in first out)的特點,具有廣泛的應用,如我在遊戲編程模式--命令模式(2)中使用棧的結構來實驗撤銷、重做功能。現在打算用棧結構來實現後綴表達式的計算。
後綴表達式也叫逆波蘭表達式,其求值過程可以用到棧來輔助存儲。
2、後綴表達式
後綴表達式,指的是不包含括號,運算符放在兩個運算對象的後面,所有的計算按運算符出現的順序,嚴格從左向右進行(不再考慮運算符的優先規則)。
例如 5+(2+3)*4 轉換爲後綴表達式爲 523+4*+
3、後綴表達式的計算
規則:從左向右掃描,遇到數字壓棧,遇到操作符,彈出棧頂的兩個元素,先彈出的元素在右邊,後彈出來的在左邊,進行計算後,將結果壓棧,再往後掃描,直到掃描結束,輸出棧頂元素,即爲最終結果。
以 523+4*+爲例
5壓棧 2壓棧 3壓棧 遇到+號,彈出3 2,計算2+3,將5壓棧,此時棧爲5 5,將4壓棧,遇到*號,彈出4 5,計算5*4,將20壓棧 此時棧爲5 20 ,遇到+號,計算5+20,將25壓棧,掃描結束,輸出25。
以上就是計算過程。下面用C++編寫代碼,爲了方便標記算式的結束,在末尾我們加上#,用來標識算式結束,這裏我們只進行四則運算
#include <iostream>
#include <stack>
#include "string"
using namespace std;
int main()
{
stack<int> a;
string temp;
cin >> temp;
int i = 0;
while (true)
{
if (temp[i]=='#') cout << a.top(); break;
if (temp[i]<='9'&&temp[i]>='0') a.push(temp[i]-48);
else
{
int x, y;
y = a.top(); a.pop();
x = a.top(); a.pop();
switch (temp[i])
{
case '+':a.push(x + y); break;
case '-':a.push(x - y); break;
case '*':a.push(x * y); break;
case '/':a.push(x / y); break;
default:break;
}
}
++i;
}
cin >> temp;
return 0;
}
4、中綴表達式轉後綴表達式
4.1、規則
中綴表達式a + b*c + (d * e + f) * g,其轉換成後綴表達式則爲a b c * + d e * f + g * +。
轉換過程需要用到棧,具體過程如下:
1)如果遇到操作數,我們就直接將其輸出。
2)如果遇到操作符,則我們將其放入到棧中,遇到左括號時我們也將其放入棧中。
3)如果遇到一個右括號,則將棧元素彈出,將彈出的操作符輸出直到遇到左括號爲止。注意,左括號只彈出並不輸出。
4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,從棧中彈出元素直到遇到發現更低優先級的元素(或者棧爲空)爲止。彈出完這些元素後,纔將遇到的操作符壓入到棧中。有一點需要注意,只有在遇到" ) "的情況下我們才彈出" ( ",其他情況我們都不會彈出" ( "。
5)如果我們讀到了輸入的末尾,則將棧中所有元素依次彈出。
4.2、實例
規則很多,還是用實例比較容易說清楚整個過程。以上面的轉換爲例,輸入爲a + b * c + (d * e + f)*g,處理過程如下:
1)首先讀到a,直接輸出。
2)讀到“+”,將其放入到棧中。
3)讀到b,直接輸出。
4)讀到“*”,因爲棧頂元素"+"優先級比" * " 低,所以將" * "直接壓入棧中。
5)讀到c,直接輸出
6)讀到" + ",因爲棧頂元素" * "的優先級比它高,所以彈出" * "並輸出, 同理,棧中下一個元素" + "優先級與讀到的操作符" + "一樣,所以也要彈出並輸出。然後再將讀到的" + "壓入棧中。
7)下一個讀到的爲"(",它優先級最高,所以直接放入到棧中。
8)讀到d,將其直接輸出。
9)讀到" * ",由於只有遇到" ) "的時候左括號"("纔會彈出,所以" * "直接壓入棧中。
10)讀到e,直接輸出。
11)讀到" + ",彈出" * "並輸出,然後將"+"壓入棧中。
12)讀到f,直接輸出。
13)接下來讀到“)”,則直接將棧中元素彈出並輸出直到遇到"("爲止。這裏右括號前只有一個操作符"+"被彈出並輸出。
14)讀到" * ",壓入棧中。讀到g,直接輸出。
15)此時輸入數據已經讀到末尾,棧中還有兩個操作符“*”和" + ",直接彈出並輸出。至此整個轉換過程完成。程序實現代碼後續再補充了。
4.3、轉換的另一種方法
1)先按照運算符的優先級對中綴表達式加括號,變成( ( a+(b*c) ) + ( ((d*e)+f) *g ) )
2)將運算符移到括號的後面,變成((a(bc)*)+(((de)*f)+g)*)+
3)去掉括號,得到abc*+de*f+g*+
具體細節關注微信公衆號 【阿龍學堂】