中綴表達式轉換為后綴表達式
首先何為中綴表達式。中綴表達式就是我們最為常見的算術表達式形式,即操作符在操作數中間。比如 3 + 4。
后綴表達式是將操作符置於操作數后面,即如下形式:3 4 +。
給定一個中綴表達式,我們如何將其轉換為后綴表達式?
我們這里涉及的操作符只局限於加、減、乘、除四種運算,即四則運算,外加括號功能。
比如給定一個中綴表達式:
1 + 3 * 5 – ( 7 / 9 )
其后綴表達式應為:
1 3 5 * + 7 9 / -
中綴表達式:
( 1 + 3 ) * ( 5 – 7 ) / 9
其后綴表達式為:
1 3 + 5 7 - * 9 /
我們先給出其程序實現如下:
// 中綴表達式轉換為后綴表達式 #include <iostream> #include <sstream> #include <vector> #include <string> #include <stack> #include <map> using namespace std; void get_infix(vector<string>& inf) { inf.clear(); string line; getline(cin, line); istringstream sin(line); string tmp; while (sin >> tmp) { inf.push_back(tmp); } } void show(const vector<string>& hs) { for (vector<string>::size_type i = 0; i != hs.size(); ++i) { cout << hs[i] << ' '; } cout << endl; } void init_op(map<string, int>& ops) { ops.clear(); ops["+"] = 100; ops["-"] = 100; ops["*"] = 200; ops["/"] = 200; ops["("] = 1000; ops[")"] = 0; } bool is_operator(const string& hs, const map<string, int>& ops) { map<string, int>::const_iterator cit = ops.find(hs);\ if (cit != ops.end()) { return true; } else { return false; } } void in2post(const vector<string>& inf, vector<string>& postf, map<string, int>& ops) { postf.clear(); stack<string> op_st; for (vector<string>::size_type i = 0; i != inf.size(); ++i) { if (!is_operator(inf[i], ops)) { postf.push_back(inf[i]); } else { if (inf[i] == "(") { op_st.push(inf[i]); } else if (inf[i] == ")") { while (!op_st.empty()) { if (op_st.top() == "(") { op_st.pop(); } else { postf.push_back(op_st.top()); op_st.pop(); } } } else // 若為其他運算符 { if (op_st.empty()) // 若為空棧,則直接入棧 { op_st.push(inf[i]); } else { if (ops[inf[i]] > ops[op_st.top()]) { // 如果當前操作符優先級高於站定操作符優先級 // 則直接入棧 op_st.push(inf[i]); } else { // 否則彈出棧中優先級大於等於當前操作符優先級 // 的操作符,並最后將當前操作符壓棧 while (!op_st.empty() && ops[op_st.top()] >= ops[inf[i]] && op_st.top() != "(") { /* 等價於 && op_st.top != "(" if (op_st.top() == "(") { // 如果當前棧頂操作符為 "(" // 則終止操作,繼續保留 "(" 的棧頂位置 break; } */ postf.push_back(op_st.top()); op_st.pop(); } op_st.push(inf[i]); } } } } } while (!op_st.empty()) { postf.push_back(op_st.top()); op_st.pop(); } } int main() { map<string, int> ops; init_op(ops); vector<string> inf, postf; while (1) { get_infix(inf); // show(inf); in2post(inf, postf, ops); show(postf); } system("PAUSE"); return 0; }
下面我們主要講解一下中綴表達式轉換為后綴表達式的數據結構與算法邏輯。
首先我們在進行后綴表達式轉換為后綴表達式的過程中,利用了一種常見的數據結構:棧。我們利用棧先進后出的特性進行轉換操作。該棧用於存儲表達式中的操作符:
+、-、*、/、(、)
所以,我們將該棧稱作為操作符棧。
借助於棧這種數據結構,我們的算法邏輯為:
1.順序掃描整個中綴表達式;
2.中綴表達式的元素類型分為兩類:操作數和操作符,如果當前元素為操作數,則將該
元素直接存入到后綴表達式中;
3.如果當前元素為操作符,分為以下幾種情況進行討論:
3.1 如果為“(”,則將其直接入棧;
3.2 如果為“)”,則將棧中的操作符彈棧,並將彈棧的操作符存入到后綴表達式中,
直至遇到“(”,將“(”從棧中彈出,並不將其存入到后綴表達式中(后綴表
達式是不需要“(”和“)”的);
3.3 如果是其他操作符(+、-、*、/),如果其優先級高於棧頂操作符的優先級,則
將其入棧,如果是小於或低於站定操作符優先級,則依次彈出棧頂操作符並存
入后綴表達式中,直至遇到一個站定優先級小於當前元素優先級時或者棧頂元
素為“(”為止,保持當前棧頂元素不變,並將當前元素入棧;
4.掃描完畢整個中綴表達式后,檢測操作符棧,依次彈出其元素,並將其元素順序存入
到后綴表達式中。
相關討論
在進行中綴表達式轉換為后綴表達式過程中,除了中綴表達式、后綴表達式外,還涉及了中間結果即:操作符棧。利用操作符棧存儲在轉換過程中涉及優先級先后順序的操作符。操作符的優先級是根據 +、- 小於 *、/,運算順序是先左后右,括號操作最優先的規則進行的。
中綴表達式轉換為后綴表達式關鍵點主要有以下幾點:
1.使用操作符棧
2.對於操作數直接進入后綴表達式
3.對於“(”,入棧
4.對於“)”,彈棧,直至“(”
5.對於其他操作符,彈棧並進入后綴表達式,直至小於當前操作符優先級或者“(”
6.掃描中綴表達式后,彈出棧中所有操作符並進入后綴表達式。