中綴和字尾算術表示式的分析比較

2021-08-24 21:35:26 字數 4648 閱讀 7216

中綴和字尾算術表示式的分析比較

劉愛貴

(高能物理研究所計算中心 北京 2023年)

摘要: 表示式求值 是程式語言編譯中的乙個最基本問題。與人們習慣的中綴表示的表示式相比,字尾表示式 不存在括號,沒有優先順序的差別,表 達式中各個運算是按照運算子出現的順序進行的。因此非常適合序列工作的計算機處理方式。本文首先對這兩種表示式表示方法進行了分析比較,然後通過具體分析實現這兩種表示式求值的演算法來論證表示式字尾表示優於中綴表示。最後簡要談了一下中綴表示式到字尾表示式的轉換。

表示式求值是程式語言編譯中的乙個最基本問題。 通常書寫的算術表示式是由運算元和運算子以及改變運算次序的圓括號連線而成的式子。運算子包括單目運算子和雙目運算子兩類,單目運算子只要求乙個運算元,並被放在該運算元的前面,雙目運算子要求有兩個運算元,其位置因表示方法不同而有所差異。按照運算子與運算物件的位置關係,算術表示式的表示方法分為字首表示式、中綴表示式和事綴表示式三種,其中後兩者較為常用。 為了簡便起見,在本文的討論中只考慮雙目運算子(僅+、-、*、/  四種)以及括號。

中綴算術表示式最為常用,其 二元運算子置於與之相關的兩個運算物件之間。對中綴表示式的計值,並非按照運算子出現的自然順序來執行其中的各個運算,而是根據算符間的優先關係來確定運算的次序,此外,還需要顧及括號規則。中綴表示式的計算比較複雜,它必須遵守以下三條規則[1]

:(1) 先計算括號內,後計算括號外;

(2) 在無括號或同層括號內,先乘除運算,後加減運算,即乘除運算的優先順序高於加減運算的優先順序;

(3) 同一優先順序運算,從左向右依次進行。

從這三條規則可以看出,在中綴表示式的計算過程中,既要考慮括號的作用,又要考慮運算子的優先順序,還要考慮運算子出現的先後次序。因此,各運算子實際的運算次序往往同它們在表示式中出現的先後次序是不一致的,是不可**的。中綴算術表示式符合人的思維方式,我們 憑直觀判別乙個中綴表示式中運算子運算順序並不困難,但對於計算機處理起來就比較複雜了。由於傳統計算機一維的計算模型,只能乙個字元乙個字元地掃瞄,要想得到哪乙個運算子先算,就必須對整個中綴表示式掃瞄一遍,乙個中綴表示式中有多少個運算子,原則上就得掃瞄多少遍才能計算完畢,這樣演算法的時間複雜性就差了,顯然是不可取的。

波蘭邏輯學家j.lukasiewicz 於1929 年提出了字尾表示式的表示方法。這種方法的算術表示式中的每乙個運算子都置於其運算物件之後,表示式中各個運算是按照運算子出現的順序進行的,故無須使用括號來指示運算順序,因而又稱為無括號式。[2]

如中綴表示式100+(200-50*3)/(13-8) ,其字尾表示式為100 200 50 3 * - 13 8 - / + 。 在字尾表示式中,不存在括號,也不存在優先順序的差別,計算過程完全按照運算子出現的先後次序進行,整個計算過程僅需一遍掃瞄便可完成,顯然比中綴表示式的計算要簡單得多。其實j.lukasiewicz原來提出的是表示式的字首表示方法,即把每一運算子置於運算物件之前[2]

, 前面的表示式用字首表示為+ 100 * 50 3 - / 200 20 。字首表示式的優點與字尾表示式的相同,也不含有括號,表示式中的運算也是按照運算子出現的順序進行的,計值也很容易實現。但由於其表示方法與人們的習慣相差甚遠,因而並不常用。

對於簡單的中綴表示式我們很容易得到其字尾表示式,但對於較為複雜的中綴表示式就很難從直觀上得到其字尾表示式。我們可以用一棵二叉樹來表示算術表示式,內部結點表示運算子,葉結點代表運算物件,如100+(200-50*3)/(13-8) 。這樣按照先序、中序、後序遍歷二叉樹,就可以分別得到字首、中綴和字尾算術表示式。如此可以很方便地實現三種算術表示式的相互轉換。

二叉樹表示的算術表示式100+(200-50*3)/(13-8)

在計算機中進行算術表示式的計算是通過堆疊來實現的。字尾表示式由於其本身所具有的優點,表示式中各個運算是按照運算子出現的順序進行的, 其計算求值比較簡單,掃瞄一遍即可完成。它只需要使用乙個棧,用來儲存字尾表示式中的運算元、計算過程中的中間結果以及最後結果。字尾表示式求值演算法的基本思路是:把包含字尾算術表示式的字串定義為乙個輸入字串,按順序從中讀取字元(空格作為資料之間的分隔符,不會被作為字元讀入)時,若是運算子,則表明它的兩個運算元已在棧中,其中棧頂元素為運算子的後乙個運算元,棧頂元素的下乙個元素為運算子的前乙個運算元,把兩個運算元出棧進行相應運算即可,然後把運算結果再壓入棧中;否則,讀入的字元必為運算元字串中的字元,讀取整個運算元字串,轉換成數後並把它壓入到棧中。依次掃瞄每乙個字元並進行上述處理,直到遇到結束符』

#』 為止,表明字尾表示式計算完畢,最終結果儲存在棧中,並且棧中僅存這乙個值,把它彈出返回即可。字尾表示式求值演算法描述為:

int postexpression(char *exp)

else

} else // 當前字元為運算子,兩個運算元出棧,計算並將結果入棧

ch=*(++exp); // 取下一字元}

result=opnd->pop();

return(result); }

此演算法的執行時間主要花在while 迴圈上,它從頭到尾掃瞄字尾表示式中的每乙個資料(每個運算元或運算子均為乙個資料),若字尾表示式由n 個資料組成,則此演算法的時間複雜度為o(n) 。此演算法在執行時所占用的臨時空間主要取決於運算元棧的大小,顯然,它的最大深度不會超過表示式中運算元的個數,因為運算元的個數與運算子(假定把』

#』 也看作為乙個特殊運算子,即結束運算子)的個數相等,所以此演算法的空間複雜度也同樣為o(n) 。

中綴表示式求值同樣用堆疊來實現,但實現相對字尾表示式較為複雜,它採用一種稱為「算符優先法」的演算法[1]

,它必須嚴格按照前面所述的三條規則來進行計算。為了實現算符優先演算法,要使用兩個工作棧。乙個稱為optr, 用以寄存運算子;另乙個稱為opnd ,用以寄存運算元或運算結果,它的基本思想於字尾表示式計算的不同在於:當讀取到運算子時並不可能作相應運算,必須先比較運算子棧中棧頂元素與當前運算子的優先順序。若為『< 』則運算子入棧;若為『= 』則說明是一對括號,需脫括號;若『> 』則作相應運算並將結果入棧。

中綴表示式求值演算法描述如下:

int middexpression(char *exp)

ch=*++exp; }

else

} }

result=opnd->pop();

return(result); }

分析上面演算法,運算時間主要用在字串掃瞄和算符優先權的比較上。把# 看作運算子,運算元與運算子個數相同,最壞情況下優先順序比較是n/2 次,即運算順序完全是逆序的, 每個字元掃瞄一遍是o(n) 的,所以整個演算法複雜度是o(n2 ) 的。演算法中用到兩個棧,分別為o(n/2) ,其演算法空間複雜度是o(n) 的。

從兩個演算法的分析比較中,我們可以看到優先順序的比較、運算不按順序進行使中綴表達計算的時間複雜性從o(n) 降到了o(n2 ), 花費了大量的執行時間。在pentium ii

266mhz 、128m ram 、win2000 、vc6.0 測試環境下, 對中綴表示式100+(200-(50*(8-45/9))) 、17*9/3+13-11 、100+(200-50*3)/(13-8) 和其字尾表示式表達100 200 50 8 45 9 / - * - + 、17 9 * 3 / 13 + 11 – 和100 200 50 3 * - 13 8 - / + 分別呼叫middexpression() 和postexpression() ,三個表示式運算時間( 秒) 分別為(0.008681,0.003974 )、(0.005812,0.003663 )、(0.008437,0.004524 )。第乙個表示式中綴表示運算是完全逆序的,其運算時間與字尾表示運算時間之比為2.184332 :1 ;第二個表示式中綴表示運算是完全順序的,其運算時間與字尾表示運算時間之比為1.586667 :1 ;第三個表示式中綴表達運算是一般情況,其運算時間與字尾表示運算時間之比為1.865047 :1 。從中我們發現,字尾表示式運算時間比較穩定,而中綴表示式由於運算順序不同執行時間相差較大。可見在時間複雜度和效率方面字尾表示方法要明顯優於中綴表示方法。

經以上的分析比較可以發現,字尾表示式要優於中綴表示式,非常適合用計算機求解。但是比起中綴表示式,形式上沒有中綴表達直觀,後者更適於人類的思維方式。因此利用計算機進行科學計算,在高階語言程式設計中我們用中綴表示式來表示,而在計算機內部是用字尾表示式來進行計算的,因此為了處理方便,編譯程式常把中綴表示式首先轉換為字尾表示式然後再進行運算。中綴表示式-字尾表示式轉換演算法的思想與中綴表示式求值演算法基本相似,這裡就不再贅述。但值得一提的是,轉換的時間複雜度是o (n )的,且只需要乙個o(n/2) 的運算子棧。利用表示式的字尾表示和堆疊技術只需要兩遍掃瞄就可完成中綴算術表示式的計算,時間複雜度仍是o(n) 的,顯然要大大優於直接進行中綴算術表示式計算。

[參考文獻]

[1] 、 嚴蔚敏、吳偉民     資料結構

1997.7 清華大學出版社

[2] 、 蔣立源         編譯原理     1

993.8 西北工業大學出版社

中綴表示式和字尾表示式

一 中綴表示式如何轉成字尾表示式?中綴表示式 符合人類閱讀 字尾表示式 符合計算機運算 1 遍歷中綴表示式中的數字和符號 2 對於數字 直接輸出 3 對於符號 左括號 進棧 運算符號 與棧頂符號進行優先順序比較 若棧頂符號優先順序低 此符號進棧 預設棧頂若是左括號,則左括號優先順序最低 若棧頂符號優...

算術表示式 將中綴表示式轉換為字尾表示式

是什麼?由數字和運算子組成的式子。簡單清楚的描述計算過程和內容。算術表示式分為 字首表示式 中綴表示式 字尾表示式 中綴表示式符合人類的日常思維習慣。採用樹的資料結構,缺點是如果表示式過於複雜,樹的高度會很高,極大的增加了時間複雜度和空間複雜度,但是轉換成線性結構,效率將會提高很多,所以需要將中綴表...

中綴表示式變字尾分析

演算法學習 將中綴變為相應的字尾,需要根據的優先順序來進行棧的變化。具體操作是 我們用乙個棧即可,儲存的是符號棧,數字直接輸出,因為符號輸出順序以及時機需要調整,因此用棧做中轉。在掃瞄符號時,我們稱符號的優先順序是棧外優先順序,這個時候在決定誰可以進棧。等到掃到非數字符號,則可以有機會進棧,每個非數...