1. 程式人生 > >編譯原理中的逆波蘭表示式(資料流圖中運算變數的流程)

編譯原理中的逆波蘭表示式(資料流圖中運算變數的流程)

表示式一般由運算元(Operand)、運算子(Operator)組成,例如算術表示式中,通常把運算子放在兩個運算元的中間, 這稱為中綴表示式(Infix Expression),如A+B。 波蘭數學家Jan Lukasiewicz提出了另一種數學表示法,它有兩種表示形式: 把運算子寫在運算元之前,稱為波蘭表示式(Polish Expression)或字首表示式(Prefix Expression),如+AB; 把運算子寫在運算元之後,稱為逆波蘭表示式(Reverse Polish Expression)或字尾表示式(Suffix Expression),如AB+;

其中,逆波蘭表示式在編譯技術中有著普遍的應用。

演算法: 一、 將中綴表示式轉換成字尾表示式演算法: 1、從左至右掃描一中綴表示式。 2、若讀取的是運算元,則判斷該運算元的型別,並將該運算元存入運算元堆疊 3、若讀取的是運算子   (1) 該運算子為左括號"(",則直接存入運算子堆疊。   (2) 該運算子為右括號")",則輸出運算子堆疊中的運算子到運算元堆疊,直到遇到左括號為止。   (3) 該運算子為非括號運算子:       (a) 若運算子堆疊棧頂的運算子為括號,則直接存入運算子堆疊。       (b) 若比運算子堆疊棧頂的運算子優先順序高或相等,則直接存入運算子堆疊。       (c) 若比運算子堆疊棧頂的運算子優先順序低,則輸出棧頂運算子到運算元堆疊,並將當前運算子壓入運算子堆疊。 4、當表示式讀取完成後運算子堆疊中尚有運算子時,則依序取出運算子到運算元堆疊,直到運算子堆疊為空。

所謂的標準的表示式如"A+B",它在數學上學名叫中綴表示式(Infix Notation),原因是:

運算子號在兩個運算物件的中間

      其優勢: 在於只:用兩種簡單操作,入棧和出棧就可以搞定任何普通表示式(僅包含:+-*/和()的表示式)的運算。

      其基本運算方式 :如果當前字元為變數或者為數字,則壓棧,如果是運算子,則將棧頂兩個元素彈出作相應運算,結果再入棧,最後當表示式掃描完後,棧裡的就是結果。

      為什麼說逆波蘭式產生機器碼的效率高因為逆波蘭式非常易於計算機的處理。原因是這樣的。舉例:

     3   32   + 5 3   *   -
  12 34 2   -   *   8 /
  乍一看上面兩個式子很奇怪,是嗎?它們就是一種表示式的記法——逆波蘭表示式。
  現在,準備一個很窄的圓筒,筒是有底的(其實是堆疊)。再做幾個圓紙片,在紙片上依次寫上“3”“32”“+”“5”“3”“*”“-”,記住,每個紙片上要麼只寫一個數,要麼只寫一個運算子號,把它們按上面的順序排好。好,現在仔細聽我說,按順序一個接一個地拿起小圓紙片,反覆執行以下幾個規則:
  1. 如果你拿著的是一個數,不多說,直接把它放進圓筒;
  2. 如果你拿著的是一個運算子號,不要把它放進去。先從圓筒裡取出兩個數(當然是先取最上而的啦,筒很細的),然後處這兩個數作運算子號指定的運算,並把結果寫在一張新的紙片上,然後放進筒裡。比如你拿著的是“+”,你要依次取出“32”和“3”,讓它們相加,得“35”,把“35”寫在一張新紙片上(現在“34”和“12”可以扔掉了),並把這張新紙片放進圓筒。
  當圓筒裡只有一個數時,你就可以停下來了,我猜這個數是20,沒錯,這就是這個表示式的值!
  我們剛才操作的,其實就是一個“棧”,棧是一種資料結構,具有一個性質——後進先出(LIFO——Last Input First Output),你已經深有體會了,就像一摞盤子,你只能從最上面的開始取,放的時候也只能放在最上面。放進去的動作叫做“入棧”,取出來叫做“彈出”。以後你就可以把棧想像成一摞盤子,或是上面說的小圓筒和小紙片,棧就是這麼簡單!
  逆波蘭表示式雖然看起來比較繁瑣,其實在計算機中很有用。計算機可不知道先乘除後加減,先括號內後括號外

,它要把你輸入的式子變成逆波蘭表示式,它就可以不斷地執行上面兩個固定的規則,直至把結果算出來告訴你。,編譯器在處理時候按照從左至右的順序讀取逆波蘭表示式,遇到運算物件直接壓入堆疊,遇到運算子就從堆疊提取後進的兩個物件進行計算,這個過程正好符合了計算機計算的原理。所以,逆波蘭式非常適宜計算機的處理。

      將一箇中綴表示式 轉換成 逆波蘭式的演算法 結合一個具體例子分析如下:

a)給出一箇中綴表示式1*(2+3)

b)系統先定義兩個先進後出的堆疊:運算子號棧(簡稱入棧in),字尾表示式輸出符號棧(簡稱出棧out)

c)系統按從左至右的順序讀取中綴表示式

d)讀入數字直接壓入出棧(out)

e)讀入第一個運算子直接壓入入棧(in)

f)讀入"("直接壓入入棧(in)。 按上述規則讀取若干次後,若,此時兩棧的資料為: in 【*,( 】 ; out 【1,2】,開始讀取的第二個的運算子"+",並將之與入棧(in)中的棧頂運算子"("進行比較,

g)高於棧頂運算子級別的算符直接進棧,低於或等於棧頂級別的要將入棧(in)解棧(即出棧),按次壓入出棧(out)中

f)最後讀取")"時要找到入棧in中最近的"(",將其前面所有符號全部按後進先出的順序壓入出棧,並解壓,"("與")"抵消。此時兩棧的資料為:in 1,2,3,+ ; out *

g)系統讀取中綴表示式結束後將入棧in中的所有符號按後進先出的順序全部解壓,並依次壓入出棧out中,最後出棧的結果就應該為1,2,3,+,*

h)按先進先出的順序將出棧out解壓得到字尾標準表示式1,2,3,+,*

兩個堆疊先後資料情況:

In

out

1

*

1

*,(

1

*,(

1,2

*,(,+

1,2

*,(,+

1,2,3

*

1,2,3,+

1,2,3,+,*

將中綴表示式轉換成逆波蘭表示式過程中,特別要注意對於中綴標到式中括號的處理

1、要注意的,如果算符是"(",無論入棧中棧頂級別(只看棧頂)為何直接入棧,所以,“(”的等級

    只用於對其後入棧的算符進行優先順序比較,在“(”入棧時是無視優先順序的。(博主強烈提醒!!!!!!!!!!!!!!!!!!!)

2、在遇到")"時候找到最後進入的"(",並把"("前面所有的符號都壓入出棧。不能僅憑運算子的級別來判斷。

將一個 逆波蘭式 倒轉回 中綴表示式 的演算法:

   這個就相當簡單了,就是一個機械的入堆疊出堆疊的操作,

1)設定一個堆疊,將逆波蘭式從左到右開始進行出入堆疊操作,還以上例為例:1,2,3,+,*

2)遇到數字直接壓棧;例如,上例逆波蘭先進行三次入棧操作,堆疊的格局是: 1,2,3(棧頂);

3)遇到算符,將堆疊中的兩個數字出棧。 如,讀到+號後,2,3出棧,進行運算。注意,出棧時先出棧的元素是右運算元,後出棧的是左運算元,上例是2+3,不是3+2;

4)將運算的結果作為新的運算元,壓入堆疊中。如運算結果(2+3)入棧,堆疊格局:1,(2+3);

5)反覆1-4的操作,得到的中序表示式就是: 1*(2+3);

   中序表式生成的逆波蘭式唯一嗎?:

是唯一的,和固定形式的中序表示式一一對應,但,請注意這個概念,

例如: a+(b-c)*d 和 (b-c)*d+a 和 a+d*(b-c) 的是完全一樣的。但是,他們的中序形式不同,

產生的逆波蘭式必然是不同的。

      a+(b-c)*d : abc-d*+

      (b-c)*d+a :   bc-d*a+

      a+d*(b-c) : adbc-*+




相關推薦

編譯原理波蘭表示式資料運算變數流程

表示式一般由運算元(Operand)、運算子(Operator)組成,例如算術表示式中,通常把運算子放在兩個運算元的中間, 這稱為中綴表示式(Infix Expression),如A+B。 波蘭數學家Jan Lukasiewicz提出了另一種數學表示法,它有兩種表示形

C#資料結構與算法系列波蘭計算器——波蘭表示式字尾表示式

1.介紹 字尾表示式又稱逆波蘭表示式,與字首表示式相似,只是運算子位於運算元之後 2.舉例說明 (3+4)*5-6對應的字尾表示式就是3 4 +5 * 6 - 3.示例 輸入一個逆波蘭表示式(字尾表示式),使用棧(Stack),計算其結果 思路分析: 從左至右掃描表示式,遇到數字時,將數字壓入堆疊,遇到運算

Python 藉助波蘭表示式字尾表示式實現簡單計算器

Python 藉助逆波蘭表示式(字尾表示式)實現簡單計算器 文章目錄 Python 藉助逆波蘭表示式(字尾表示式)實現簡單計算器 0. 參考資料 1. 中綴表示式轉字尾表示式 2. 字尾表示式的求值 3. Python

Java實現波蘭表示式Evaluate Reverse Polish Notation

逆波蘭表示式 定義:傳統的四則運算被稱作是中綴表示式,即運算子實在兩個運算物件之間的。逆波蘭表示式被稱作是字尾表示式,表示式實在運算物件的後面。 逆波蘭表示式: a+b ---> a,b,+

波蘭表示式字尾表示式的計算

  已知12*(3+4)- 6+8/2的字尾表示式為:12 3 4 + * 6 - 8 2 / +    字尾表示式計算時,所有運算按照運算子出現的順序,嚴格從左到右,每個操作符取前兩個運算元進行運算,運算後的結果仍然作為下次的運算元。 那如果已知字尾表

編譯原理:將a+d*(b-c) 寫成波蘭表示式

逆波蘭表示式示例 1. a+b 改為 ab+ 2. (a+b)*(c+d) 改為 ab+cd+* 3. a+d*(b-c) 改為 adbc-*+ 逆波蘭表示式又叫做字尾表示式,顧

資料結構--中綴表示式轉為字尾表示式波蘭表示式

中綴表示式是一個通用的算術或邏輯公式表示方法。操作符是以中綴形式處於運算元中間。例如:3*4+3-1; 字尾表示式不包含括號,運算子放在兩個運算物件的後面,所有的計算按運算子出現的順序,嚴格從左向右(不再考慮運算子的優先規則)例如:(2+1)*3,即2 1 + 3 * (以

LeetCode150.波蘭表示式求解Evaluate Reverse Polish Notation

題目描述 根據逆波蘭表示法,求表示式的值。 有效的運算子包括 +, -, *, / 。每個運算物件可以是整數,也可以是另一個逆波蘭表示式。 說明: 整數除法只保留整數部分。 給定逆波蘭表示式總是有效的。換句話說,表示式總會得出有效數值且不存在除數為 0 的情況。

中綴表示式轉化為字尾表示式波蘭表示式

1.將中綴表示式轉化為字尾表示式 字尾表示式也叫作逆波蘭表示式,主要是運用棧的後進先出思想,下面就講講我自己的思考, 假設中綴表示式為:2*(2+1)-6(4-2)#,則字尾表示式為:2 2 1 + * 6 4 2 - / -; 首先依次遍歷中綴表示式,遇到運算元字元則直接輸出(數字字元

波蘭字尾表示式的表達求值

逆波蘭表示式求值 [編輯]虛擬碼 while有輸入符號 讀入下一個符號IF是一個運算元 入棧ELSE IF是一個操作符 有一個先驗的表格給出該操作符需要n個引數IF堆疊中少於n個運算元 (錯誤) 使用者沒有輸入足夠的運算元Else,n個操作數出棧計算操作符。將計算所得的

LeetCode: Evaluate Reverse Polish Notation計算波蘭表示式兩種方法

題目描述Evaluate the value of an arithmetic expression in Reverse Polish Notation.Valid operators are +, -, *, /. Each operand may be an integ

波蘭表示式原理實現

解析原理如下: (1) 該運算子為左括號"(",則直接存入運算子堆疊。      (2) 該運算子為右括號")",則輸出運算子堆疊中的運算子到運算元堆疊,直到遇到左括號為止,此時拋棄該左括號。      (3) 該運算子為非括號運算子:      (a) 若運算子堆疊棧頂的

基於波蘭表示式的公式解析器-演算法和思路

背景:        最近專案需要自己完成Excel的公式解析和求值,在Java中可以使用POI解析Excel公式然後求值。但是專案需要JS端和Java後端均需要支援公式解析,所以就需要自己寫一套了。

將中綴表示式轉化為波蘭c++實現

<pre name="code" class="cpp">/************************************************************************* > File Name: ReversePol

字尾表示式波蘭表示式

逆波蘭表示式又叫做字尾表示式。在通常的表示式中,二元運算子總是置於與之相關的兩個運算物件之間,這種表示法也稱為中綴表示。波蘭邏輯學J.Lukasiewicz於1929年提出了另一種表示表示式的方法,按此方法,每一運算子都置於其運算物件之後,故稱為字尾表示。 表

JavaScript中綴表達式轉為波蘭四則運算

。。 刪除 並且 asc 情況 暫存 運算符 pan true 實現過程: 1.首先創建兩個空數組,result用來存放結果,temp用來存放符號;再創建一個符號集ops存放+-*/符號 2.轉表達式字符為數組,開始遍歷數組 3.如果遇到運算符,直接推入結果數組 4.遇到括

C語言_解決括號匹配問題和波蘭表示式求值為題

##1、括號匹配問題: 解決思路: void MatchBrackets (const char* str) { char* per = NULL; int i = 0; Stack s; assert (str != NULL); InitStack (&s);

leet150. 波蘭表示式求值

題目: 求在 逆波蘭表示法 中算術表示式的值。 有效的運算子號包括 +, -, *, / 。每個運算物件可以是整數,也可以是另一個逆波蘭計數表達。 例如: ["2", "1", "+", "3", "*

LeetCode:波蘭表示式求值【150】

LeetCode:逆波蘭表示式求值【150】 題目描述 根據逆波蘭表示法,求表示式的值。 有效的運算子包括 +, -, *, / 。每個運算物件可以是整數,也可以是另一個逆波蘭表示式。 說明: 整數除法只保留整數部分。 給定逆波蘭表示式總是

佇列&棧//波蘭表示式求值

根據逆波蘭表示法,求表示式的值。 有效的運算子包括 +, -, *, / 。每個運算物件可以是整數,也可以是另一個逆波蘭表示式。 說明: 整數除法只保留整數部分。 給定逆波蘭表示式總是有效的。換句話說,表示式總會得出有效數值且