在通常的表達式中,二元運算符總是置於與之相關的兩個運算對象之間,所以,這種表示法也稱為中綴表示。每一運算符都置於其運算對象之後,稱為後綴表達式,後綴表達式又叫做逆波蘭表達式。它的優勢在於只用兩種簡單操作,入棧和出棧就可以搞定任何普通表達式的運算。其運算方式如下:如果當前字符為變量或者為數字,則壓棧,如果是運算符,則將棧頂兩個元素彈出作相應運算,結果再入棧,最後當表達式掃描完後,棧裡的就是結果。
將一個普通的中序表達式轉換為逆波蘭表達式的一般算法是:
(1)首先構造一個運算符棧,此運算符在棧內遵循越往棧頂優先級越高的原則。
(2)讀入一個用中綴表示的簡單算術表達式,為方便起見,設該簡單算術表達式的右端多加上了優先級最低的特殊符號“#”。
(3)從左至右掃描該算術表達式,從第一個字符開始判斷,如果該字符是數字,則分析到該數字串的結束並將該數字串直接輸出。
(4)如果不是數字,該字符則是運算符,此時需比較優先關系。做法如下:將該字符與運算符棧頂的運算符的優先關系相比較。如果,該字符優先關系高於此運算符棧頂的運算符,則將該運算符入棧。倘若不是的話,則將棧頂的運算符從棧中彈出,直到棧頂運算符的優先級低於當前運算符,將該字符入棧。
(5)重復上述操作(3)-(4)直至掃描完整個簡單算術表達式,確定所有字符都得到正確處理,我們便可以將中綴式表示的簡單算術表達式轉化為逆波蘭表示的簡單算術表達式。
程序化算法流程:
1、建立運算符棧stackOperator用於運算符的存儲,壓入'\0'。
2、預處理表達式,正、負號前加0(如果一個加號(減號)出現在最前面或左括號後面,則該加號(減號)為正負號) 。
3、順序掃描表達式,如果當前字符是數字(優先級為0的符號),則直接輸出該數字;如果當前字符為運算符或括號(優先級不為0的符號),則判斷第4點 。
4、若當前運算符為'(',直接入棧;
若為')',出棧並順序輸出運算符直到遇到第一個'(',遇到的第一個'('出棧但不輸出;
若為四則運算符,比較棧頂元素與當前元素的優先級: 如果棧頂元素運算符優先級 >= 當前元素的優先級,出棧並順序輸出運算符直到 棧頂元素優先級 < 當前元素優先級,然後當前元素入棧;如果棧頂元素 < 當前元素,直接入棧。
5、重復第3點直到表達式掃描完畢。
6、順序出棧並輸出運算符直到棧頂元素為'\0'。
本文主要包括RpnExpression基類、MathExpression以及IntersectionUnionExpresion。
MathExpression主要用於計算簡單數學運算(+、-、*和/)。
IntersectionUnionExpresion主要用於計算交並集運算(|、&)。
懶得用UML來畫圖,直接用VS2012生成的類圖,如下所示:
RpnExpression為逆波蘭表達式的抽象類,提供基礎的方法和結構。
RpnExpression相關代碼如下:
RpnExpression具體代碼主要包括以下方法:
public abstract int GetOperationLevel(string operationChar); //獲取操作級別
protected virtual string AdapteAndReplace(string expression) //轉換和替換原有字符串
public string ToExpression(string expression) //將中綴表達式轉換為逆波蘭表達式
public abstract bool IsValid(string[] splitArray); //檢測相關標識字符
public abstract object ComplieExpression(string expression, params object[] args); //編譯表達式
MathExpression為解析數學逆波蘭表達式的類,能夠執行相應的數字運算。
MathExpression相關代碼如下:
MathExpression界面操作結果如下:
IntersectionUnionExpresion為解析交並集逆波蘭表達式的具體類,能夠執行相應的交並運算。
IntersectionUnionExpresion相關代碼如下:
IntersectionUnionExpresion界面操作結果如下:
針對於二元運算符操作,完全可以使用逆波蘭表達式算法進行相應操作,而且,操作起來比較方便簡單。以上只是2個簡單的應用,也是去年的時候寫的,今天整理了下,希望對各位有所幫助。
參考文獻:http://baike.baidu.com/view/552648.htm
逆波蘭表達式VS2012代碼下載地址:RpnExpressionSolution.rar