棧和逆波蘭表示式

2021-09-25 03:18:01 字數 4317 閱讀 3898

1+2,1+3*2,1+(3*2*(1+3)),這些就是中綴表示式,就是我們 平時經常見到的形式,先算加減再算乘除,有括號的先算括號裡面的,沒有括號按照優先順序順序進行計算。但是,計算機處理中綴表示式卻並不方便,因為沒有一種簡單的資料結構可以方便從乙個表示式中間抽出,一部分算完結果,再放進去,然後繼續後面的計算(鍊錶也許可以,但是,代價也是不菲)。

若用鍊錶進行計算,不斷地更新值,更新節點,時間複雜度很高,**量也不低.

以a+b*(c-d)-e*f為例:

叫做中綴表示式原因就是它是由相應的語法樹的中序遍歷的結果得到的。

比如上圖二叉樹遍歷結果

前序遍歷:abcdefghk(根節點排在最先,然後同級先左後右)

中序遍歷:bdcaehgkf(左節點排在最先,然後根節點,最後右)

後序遍歷:dcbhkgfea(左節點排在最先,然後右節點,最後根節點)

中序遍歷如下圖,中序比較重要

字首表示式就是波蘭式,有相應的語法樹前序遍歷得到,

上圖的字首表示式為- + a * b -c d * e f

兩種思路算出結果:

1.第一步是從左至右掃瞄表示式,如果乙個操作符後面有兩個運算元時,則先計算,用計算後的值替換(這個操作符和兩個數)。重複此步驟,直至全部處理完,如- + a * b -c d * e f,先計算c-d,用計算後的值c'代替,- + a * bc' * e f。用b'代替b*c',-+ab'*ef,用a'代替a+b',-a'*ef,用e』代替e*f,然後為-a'e',最終的結果為a'-e'。

2,由以上分析思索如何去實現過程,首先我們可以逆序,採用棧的思想,多遍掃瞄表示式,需要將3個字元替換為1個字元,我們每次掃瞄到運算元時,則入棧,掃瞄到操作符,則彈出來兩個數進行計算,計算後的值則壓進棧中,按照順序和思路則為出2入1,那麼掃瞄結束後棧頂就是表示式結果。

3,那麼我們需要幾個棧呢?兩個乙個用來儲存數字逆序,另乙個用來儲存操作符,因為操作符預設是從左到右的,所以就需要乙個棧,字首表示式往往需要用兩個棧來計算,其中乙個棧用來預處理:將字串倒序壓進棧中。

啊,我忘了儲存,電腦睡眠,但是回來系統自己更新了,寫了一上午的部落格都沒有儲存,心痛,重來重來。

字尾表示式就是逆波蘭式,它是由相應的語法樹後序遍歷得到結果例如上面舉的例子它的字尾表示式為 a b c d - * + e f * -

字尾表示式和字首表示式看起來就像一對逆過程,實際上並不是這樣子,還是有一定區別的。

如果熟練的話,可以根據給出的中綴表示式中序遍歷畫出相應的二叉樹,然後後序遍歷則為相應的字尾表示式。

例如:12 * (3 + 4) - 6 + 8 / 2 

依次獲取: 

12 ,是數字,直接輸出

字尾表示式:12 

符號棧:

』 * 』 ,是運算子,入棧

字尾表示式:12 

符號棧:*

』 ( 『,左括號,直接入棧

字尾表示式:12 

符號棧: * (

3 , 數字 ,輸出

字尾表示式:12 3 

符號棧: * (

『 + 』,運算子 ,入棧

字尾表示式:12 3 

符號棧: * ( +

4 ,數字,輸出

字尾表示式:12 3 4 

符號棧: * ( +

『 )』,右括號,棧中元素依次出棧並輸出知道遇到左括號,並且左括號也要出棧且不輸出

字尾表示式:12 3 4 + 

符號棧: *

『 - 』,操作符,減號的優先順序低於乘號所以乘號出棧並輸出,此時站內沒有符號,減號入棧

字尾表示式:12 3 4 + * 

符號棧: -

6 ,數字,輸出

字尾表示式:12 3 4 + * 6 

符號棧: -

』 + 『,操作符 ,優先順序與減號相同(也就是說沒有減號的優先順序高)所以減號出棧輸出,加號入棧

字尾表示式:12 3 4 + * 6 - 

符號棧: +

8 ,數字 ,輸出

字尾表示式:12 3 4 + * 6 - 8 

符號棧: +

『 / 』,操作符,比減號的優先順序高直接入棧

字尾表示式:12 3 4 + * 6 - 8 

符號棧: + /

2 ,數字,輸出

字尾表示式:12 3 4 + * 6 - 8 2 

符號棧: + / 

中綴表示式獲取完後,將棧中剩餘元素依次出棧輸出 

字尾表示式:12 3 4 + * 6 - 8 2 / + 

符號棧:

以上就是中綴表示式轉字尾表示式。這是一位大佬的部落格的分析過程,我覺得很棒,以後再繼續理解。

這位大佬更厲害,我覺得分析很到位

個人認為中綴轉字尾的主要難點在於運算子的處理以及括號的處理,這是特別容易出錯的地方,這一塊出錯了,結果就很容易出錯。

若遇到的是運算子:a、如果該運算子的優先順序大於棧頂運算子的優先順序時,將其壓棧

b、如果該運算子的優先順序低於棧頂元素,將棧頂元素輸出,接著和新的棧頂運算 符比較,若大於,則將其壓棧,若小於,繼續將棧頂運算子彈出並輸出......(一直遞迴下去,直至運算子大於棧頂雲算符為止)。

#include#include#include#include#include#include#includeusing namespace std;

//中綴表示式轉字尾表示式

//遇到運算元時新增到字尾表示式將其直接輸出

//遇到操作符的話,如果棧空將其直接入棧

//遇到左括號直接入棧

//遇到右括號,執行出棧操作,輸出到字尾表示式,直到彈出的是左括號

//左括號不輸出到字尾表示式

//遇到其他運算子:彈出所有優先順序大於或等於該優先順序的棧頂元素

//然後將運算子入棧

//將棧中剩餘內容依次彈出字尾表示式

mapp;

struct point

;typedef struct point node;

stacks;//操作符棧

queueq;//字尾表示式佇列

void change(string str)

q.push(temp);//運算元入字尾表示式

}else

temp.op=str[i];

s.push(temp);

i++;

}} //將棧中剩餘內容依次彈出字尾表示式

while(!s.empty()) }

int main()

;typedef struct point node;

stacks;//操作符棧

stacks1;//運算元棧

queueq;//字尾表示式佇列

mapp;//設定優先順序,預設運算元的優先順序最高,即其不需要進棧

void change(string str)

q.push(temp);//運算元進入字尾表示式

}else//遇到其他運算子

temp.op=str[i];

s.push(temp);

i++;

}} while(!s.empty())//將棧中剩餘內容依次彈出字尾表示式 }

//字尾表示式的計算

//從左到右掃瞄字尾表示式,若是運算元就壓棧

//若是操作符就連續彈出兩個運算元

//棧頂的值就為計算的結果

//先彈出的是第一運算元,其次彈出的是第二運算元

double calcuate()

else

else if(cur.op=='-')

else if(cur.op=='*')

else

s1.push(next);//計算後的結果再次壓棧

}} return s1.top().num;//棧頂的值就為計算的結果

}int main()

double answer=calcuate();

cout一定要弄清楚思路和處理方法,可以自己參照思路寫出**,逆波蘭主要就是棧的應和處理問題的思路,大同小異。

注:要輸入合法的表示式,不然會出錯。**中沒有寫當輸入非法表示式時的處理情況。

波蘭表示式和逆波蘭表示式(棧)

中綴表示式如1 2 2 1 其運算子一般出現在運算元之間,因此稱為中綴表示式,也就是大家程式設計中寫的表達 式。編譯系統不考慮表示式的優先級別,只是對表示式從左到右進行掃瞄,當遇到運算子時,就把其前面的兩 個運算元取出,進行操作。為達到上述目的,就要將中綴表示式進行改寫,變為字尾表示式 如上面的表示...

波蘭表示式和逆波蘭表示式

題目 根據逆波蘭表示法,求表示式的值。有效的運算子包括 每個運算物件可以是整數,也可以是另乙個逆波蘭表示式。說明 示例 1 輸入 2 1 3 輸出 9 解釋 該算式轉化為常見的中綴算術表示式為 2 1 3 9 示例 2 輸入 4 13 5 輸出 6 解釋 該算式轉化為常見的中綴算術表示式為 4 13...

波蘭表示式 逆波蘭表示式

中綴表示式是最常見的運算表示式,如 3 5 2 6 1 波蘭表示式又稱為字首表示式,它是由中綴表示式經過一定的方式轉換來的 比如中綴表示式為 3 5x 2 6 1 對應的字首表示式為 3 x 5 2 6 1 對於中綴表示式從右向左遍歷轉換為字首表示式,中途要是用棧進行儲存 轉換規則如下 波蘭表示式 ...