中綴表達式的值 ( 棧的運用 )

參考1:https://www.cnblogs.com/hantalk/p/8734511.html

參考2:https://blog.csdn.net/Coder_Dacyuan/article/details/79941743

題目描述
    模擬計算機處理算術表達式過程。從鍵盤上輸入算術表達式串(只含+、-、×、÷運算符,允許含括號),輸出算術表達式的值。設輸入的表達式串是合法的,且只包含整數。

輸入
    一行,中綴表達式,長度不超過255,以“@”結束。

輸出
    中綴表達式的值。

樣例輸入
4+5-9+10*2@

樣例輸出
20

 

分析
表達式
中綴表達式(常用表達式)、前綴表達式(波蘭式)、後綴表達式(逆波蘭式)
中綴表達式:操作符是以中綴形式處於操作數的中間,中綴表達式是人們常用的算術表示方法。
前綴表達式:也叫波蘭式,不包含括號,運算符放在兩個運算對象的前面。
後綴表達式:也叫逆波蘭式,不包含括號,運算符放在兩個運算對象的後面,所有的計算按運算符出現的順序,嚴格從左向右進行。
比如:a+b
中綴:a+b      前綴:+ab     後綴:ab+
再比如:(a+b)*(c-d)
中綴:(a+b)*(c-b)     前綴:*+ab-cd     後綴:ab+cb-*

中綴轉前綴/後綴  手工算法
1、給每個表達式加上括號
2、將移動每個二元運算符,將其放在與其相應括號的左/右括號處 
3、刪除所有括號
如: 中綴表達式爲:a/b-c+d*e-a*c
執行第一步:((((a/b)-c)+(d*e))-(a*c))
執行第二步:
        前綴:(-(+(-(/ab)c)(*de))(*ac))        //左括號處
        後綴:((((ab/)c-)(de*)+)(ac*)-)        //右括號處
執行第三步:
        前綴:-+-/abc*de*ac
        後綴:ab/c-de*+ac*

中綴轉前綴 計算機算法
1、初始化兩個棧:運算符棧s1,儲存中間結果的棧s2
2、從右至左掃描中綴表達式
3、遇到操作數時,將其壓入s2
4、遇到運算符時,比較其與s1棧頂運算符的優先級
        1若優先級比棧頂運算符的較高或相等,或s1爲空,或棧頂運算符爲右括號“)”,則直接將此運算符入棧
        2否則,將s1棧頂的運算符彈出並壓入到s2中,再次轉到(4-1)與s1中新的棧頂運算符相比較
5遇到括號時
        如果是右括號“)”,則直接壓入s1
        如果是左括號“(”,則依次彈出S1棧頂的運算符,並壓入S2,直到遇到右括號爲止,此時將這一對括號丟棄
6、重複步驟2至5,直到表達式的最左邊
7、 將s1中剩餘的運算符依次彈出並壓入s2
8、依次彈出s2中的元素並輸出,結果即爲中綴表達式對應的前綴表達式

中綴轉後綴 計算機算法
1、初始化一個棧:運算符棧s;
2、從左至右掃描中綴表達式;
3、遇到操作數時,輸出;
4、遇到運算符時,比較其與s棧頂運算符的優先級:
        1若優先級比s棧頂運算符的高,或者s爲空,或者左括號“(”,則直接將此運算符入棧;
        2否則,將s棧頂的運算符輸出,再次轉到(4-1)與s中新的棧頂運算符相比較;
5、遇到括號時:
        如果是左括號“(”,則直接壓入s;
        如果是右括號“)”,則依次彈出s棧頂的運算符,輸出,直到遇到左括號爲止,此時將這一對括號丟棄;
6、重複步驟2至5,直到表達式的最右邊;
7、將s中剩餘的運算符依次彈出並輸出;
以上輸出即爲後綴表達式。

前綴表達式求值
從右至左掃描表達式,遇到數字時,將數字壓入堆棧,遇到運算符時,彈出棧頂的兩個數,用運算符對它們做相應的計算(棧頂元素 運算符 次頂元素),並將結果入棧;重複上述過程直到表達式最左端,最後運算得出的值即爲表達式的結果

後綴表達式求值
從左至右掃描表達式,遇到數字時,將數字壓入堆棧,遇到運算符時,彈出棧頂的兩個數,用運算符對它們做相應的計算(次頂元素 運算符 棧頂元素),並將結果入棧;重複上述過程直到表達式最右端,最後運算得出的值即爲表達式的結果。

#include<iostream>
#include<string>
#include<stack>
using namespace std;
string s;
stack<int> num;
stack<char> sym;
char lev[128];
 
void calculate(){	//計算
	int x=num.top(); num.pop();
	int y=num.top(); num.pop();
	switch (sym.top()){
		case '+': y+=x; break;
		case '-': y-=x; break;
		case '*': y*=x; break;
		case '/': y/=x; break;
	}
	num.push(y);	//運算後值入數字棧
	sym.pop();		//運算符棧出棧
}
 
int main(){
	cin>>s;
	lev['+']=lev['-']=1; lev['*']=lev['/']=2;	//運算符優先級
	for (int i=0,len=s.size()-1; i<len; ){
		if (s[i]=='(') sym.push(s[i]),i++;	//左括號直接入棧
		else if (s[i]==')'){	//右括號
			while (sym.top()!='(') calculate();	//運算符出棧 到 最近一次左括號
			sym.pop();	//最近一次左括號出棧
			i++;	//跳過當前右括號
		}
		else if (isdigit(s[i])){	//數字,計算值
			int x=0;
			while (isdigit(s[i])) x=10*x+s[i++]-'0';
			num.push(x);	//數字入數字棧
		}
		else {	//運算符
			while (!sym.empty() && lev[s[i]]<=lev[sym.top()]) calculate();
			//當前運算符s[i]  <=  運算符棧頂運算符  運算符出棧
			sym.push(s[i]);	//當前運算符入棧
			i++;	//跳過當前運算符
		}
	}
	while (!sym.empty()) calculate();	//清空運算符棧
	cout<<num.top()<<endl;
	return 0;
}

 

發佈了31 篇原創文章 · 獲贊 4 · 訪問量 5296
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章