中綴運算子方法的名稱

2021-09-26 13:00:09 字數 3936 閱讀 8670

「計算中綴表示式」可以稱得上是乙個特別經典的關於棧的演算法題,幾乎在所有資料結構教材中都會涉及,而且很多公司面試或者筆試的時候都會把這道題作為乙個考察點。可以說,這是一道必須要掌握的演算法題。中綴表示式、字尾表示式等概念在這裡就不贅述了,讓我們直奔主題。

題目:輸入乙個中綴表示式,計算其結果。

輸入的前提假設:

(1)只考慮+、-、*、/這四種運算子,中綴表示式中只有一種括號:();

(2)輸入的中綴表示式中只有整數,沒有小數;

(3)假定輸入是合法的。

很多文章或課本喜歡一步到位,直接討論如何從中綴表示式計算結果。但對於初學者來說,跨度未免大了點。這裡循序漸進,從易到難,先討論如何將中綴表示式轉化為字尾表示式,再討論如何計算字尾表示式。最後在前面兩步的基礎上,討論如何一步到位,直接計算中綴表示式的結果:

在日常應用中,算術表示式中運算子總是出現在兩個運算元之間,例如5*(7-2*3)+8/2,這種形式稱為中綴表示式。計算乙個中綴表示式需要知道運算子的優先順序和結合性。乘除是高優先順序,加減是低優先順序,優先順序相同時他們都是左結合的,也就是從左計算到右。有括號就要計算括號內的表示式。

中綴表示式利於人的理解,但不便於計算機的處理。因此需要將中綴表示式轉換成字尾表示式,以方便計算機處理。所謂字尾表示式就是將運算子放在運算數之後。字尾表示式也稱為逆波蘭表示式。

比如:中綴表示式為:1+(2-3)*4+4/2

對應字尾表示式為:1 2 3 - 4* + 4 2 / +

如何將乙個中綴表示式轉化為字尾表示式?我們需要借助棧的力量,用它來存放運算子。演算法流程如下:

首先將各種運算子(包括括號)的優先順序排列如下(數字越大,優先順序越高):

1:(2:+ -

3:* /

4:)對輸入的中綴表示式從左到右遍歷:

1)如果遇到數字,直接新增到字尾表示式末尾;

2)如果遇到運算子+、-、*、/:

先判斷棧是否為空。若是,則直接將此運算子壓入棧。若不是,則檢視當前棧頂元素。若棧頂元素優先順序大於或等於此操作符級別,則彈出棧頂元素,將棧頂元素新增到字尾表示式中,並繼續進行上述判斷。如果不滿足上述判斷或者棧為空,將這個運算子入棧。要注意的是,經過上述步驟,這個運算子最終一定會入棧。

3)如果遇到括號:

如果是左括號,直接入棧。如果是右括號,彈出棧中第乙個左括號前所有的操作符,並將左括號彈出。(右括號別入棧)。

4)字串遍歷結束後,如果棧不為空,則彈出棧中所有元素,將它們新增到字尾表示式的末尾,直到棧為空。

字尾表示式的計算就相當簡單了。準備乙個數字棧。從左到右掃瞄字尾表示式,如果是數字,放入數字棧。如果是符號,從數字棧中彈出兩個數字,第乙個取出的數字為右運算數,第二個為左運算數,進行運算。然後將結果放進數字棧中。如此反覆,直到讀完整個表示式後,留在數字棧中的那個數字就是最終結果。

c++**如下,要注意,下面的**預設中綴表示式中所有數字都是整數,並且都在0到9之間。而且計算結果都是整數(比如5/2=2)。

[cpp] view plain

copy

#include

#include

#include

using namespace std;  

int getpriority(char ch)  

string getpostfixexpression(string str)  

elseif (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/')   

else   

else break;  

}  mystack.push(str[i]);  

}  }  

else   

mystack.pop();  

}  }  

i++;  

}  //遍歷完後,若棧非空,彈出所有元素  

while (!mystack.empty())   

return res;  

}  int calculator(string str)  

else   

else if (str[i] == '-')   

else if (str[i] == '*')   

else if (str[i] == '/')   

mystack.push(num3);  

}  }  

return mystack.top();  

}  int main()  

其實將前面的兩步結合起來,就可以得到直接計算的方法。準備乙個數字棧和乙個符號棧。

從左到右遍歷中綴表示式。如果遇到數字,入數字棧。

如果遇到符號(四個運算子以及括號),跟前面的「中綴表示式轉字尾表示式」過程一樣,對符號棧進行處理。處理過程中,對每乙個出棧的運算子:+ - * /,根據「計算字尾表示式」的方法,計算結果(跟數字棧配合)。

如果遍歷完中綴表示式後符號棧還非空,就繼續出符號棧的運算子,計算,直到符號棧為空。最後數字棧剩下的數字就是結果。

下面給出用c++實現「計算中綴表示式」的**,裡面考慮了「數字不止1位」,並且用浮點型來表示最終運算結果。要求中綴表示式中只能包含整數和運算子(不能包含小數),並且是合法的。

[cpp] view plain

copy

#include

#include

#include

using namespace std;  

int getpriority(char ch)  

void calculate(stack&mystack, char operation)  

else if (operation == '-')   

else if (operation == '*')   

else if (operation == '/')   

mystack.push(num3);  

}  double calculator(string str)  

tmp_num = str.substr(i, j - i);  

mystack_number.push(atoi(tmp_num.c_str()));  

i = j;  

}  else if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/')   

else   

else break;  

}  mystack_operation.push(str[i]);  

}  i++;  

}  else   

mystack_operation.pop();  

}  i++;  

}  }  

//遍歷完後,若棧非空,彈出所有元素  

給出一道思考題:如果加入乘方'^',應該如何處理?要注意,乘方運算是右結合的。

其實很簡單。只有兩處修改:

1)將乘方新增到優先順序中:

1:(2:+ -

3:* /

4:^5:)

2)在讀中綴表示式的時候,如果讀到乘方^,就將它放進符號棧中。因為乘方的優先順序是最高的,而且是右結合的,所以無論它前面出現的是什麼運算,這些運算都不能執行。而且它本身能否執行也是不知道的,因此只能進棧。

大家自己試試吧~要記住,學習程式設計,動手去寫**永遠是第一位的。

【參考資料】

[1][2]翁惠玉, 俞勇. 資料結構:思想與實現[m]. 高等教育出版社, 2009.

(運算子) 運算子

運算子既可作為一元運算子也可作為二元運算子。備註 unsafe context data guid 00bf87717d88a9fac1afadb796c675da 一元 運算子返回運算元的位址 要求 unsafe 上下文 bool data guid 9efd189df2cfb88799dca08...

JS運算子 算術運算子 比較運算子 賦值運算子

兩邊的變數都是number型別 則是單純的加法運算 當字串出現時 結果是字串型別 字串之後的內容 不論什麼型別 都會被作為字串進行拼接 例子 var num1 10 var num2 20 num num1 num2 var result num1 num2 num1 false console.l...

NOT運算子與 運算子

6.4.2 not運算子與 運算子 對於簡單的條件查詢,not運算子與 運算子的功能幾乎沒有什麼區別,那麼not運算子的優勢體現在 呢?答案是它可以與其他運算子組合使用,這一點是 運算子所不能實現的。在6.4.1節已經介紹了not運算子與in運算子組合使用的例子,下面給出乙個not運算子與betwe...