前綴表達式的計算
前面我們曾對《后綴表達式的計算》做過討論。后綴表達式的計算過程是首先設定一個操作數棧,順序掃描整個后綴表達式,如果遇到操作數,則將操作數壓棧;如果遇到操作符,則從操作數棧中彈出相應的操作數進行運算,並將運算結果進行壓棧。當將整個后綴表達式掃描完畢時,操作數棧中應該只有一個元素,該元素的值即為后綴表達式的計算結果。
對於一個后綴表達式:
1 2 3 + -
其對應的前綴表達式為:
-1 + 2 3
前綴表達式的計算方法與后綴表達式的計算方法類似。對前綴表達式從后向前掃描,設定一個操作數棧,如果是操作數,則將其直接入棧,如果是操作符,則從棧中彈出操作符對應的操作數進行運算,並將計算結果壓棧。直至從右到左掃描完畢整個前綴表達式,這時操作數棧中應該只有一個元素,該元素的值則為前綴表達式的計算結果。
具體前綴表達式的計算程序如下:
// 計算前綴表達式 #include <iostream> #include <sstream> #include <vector> #include <stack> #include <string> using namespace std; void GetPrefix(vector<string>& prefix) { prefix.clear(); string line, tmp; getline(cin, line); istringstream sin(line); while (sin >> tmp) { prefix.push_back(tmp); } } bool IsOperator(const string& op) { return op == "+" || op == "-" || op == "*" || op == "/"; } double CalPrefix(const vector<string>& prefix) { double ret = 0.0; stack<double> opeStk; for (int i = prefix.size() - 1; i >= 0; --i) { if (!IsOperator(prefix[i])) { opeStk.push((double)atof(prefix[i].c_str())); } else { double a = opeStk.top(); opeStk.pop(); double b = opeStk.top(); opeStk.pop(); double c = 0.0; switch (prefix[i][0]) { case '+': c = a + b; opeStk.push(c); break; case '-': c = a - b; opeStk.push(c); break; case '*': c = a * b; opeStk.push(c); break; case '/': c = a / b; opeStk.push(c); break; default: break; } } } if (opeStk.size() == 1) { return opeStk.top(); } else { return -1000000000.0; } } int main() { vector<string> prefix; while (true) { GetPrefix(prefix); cout << CalPrefix(prefix) << endl << endl; } return 0; }
下面我們比較一下前綴表達式的計算與后綴表達式計算的聯系和區別:
|
前綴表達式計算 |
后綴表達式計算 |
掃描順序 |
從右到左 |
從左到右 |
棧 |
操作數棧 |
操作數棧 |
遇到操作數時 |
壓棧 |
壓棧 |
遇到操作符時 |
出棧 |
出棧 |
出棧的順序 |
先彈出操作數a,后彈出b |
先彈出操作數b,后彈出a |
結果 |
操作數棧中唯一元素的值 |
操作數棧中唯一元素的值 |
以上是討論了前綴表達式的計算,並與后綴表達式的計算進行了比較。后續我們將進一步討論中綴表達式如何轉換為前綴表達式,並且結合之前的中綴表達式轉換為后綴表達式的算法,比較兩者之間的關系和區別,從而對中綴、前綴、后綴這三種表達式的計算以及相互之間的轉換有更深的理解。
另外,我們之前討論過關於四則四則運算表達式的語法分析,通過語法分析我們可以得到四則運算表達式對應的遞歸二叉樹,進而可以根據該二叉樹得到任意的前綴、中綴、后綴表達式,其實質即使二叉樹的前序、中序、后序遍歷。針對前綴、中綴、后綴三種表達式,我們可以通過對其進行語法分析,得到對應的遞歸二叉樹,進而對二叉樹進行前序、中序、后序遍歷,得到每種表達式對應的其他兩種形式的表達式。這種通過遞歸下降語法分析而實現的四則運算表達式在前綴、中綴、后綴三種形式之間的轉換很好的解決了表達式在三種形式間的轉換問題。