棧的規(guī)則
先進(jìn)后出。如:依次入棧順序?yàn)椋篈,B,C,D;怎出棧順序?yàn)椋篋,C,B,A .
二叉樹(shù)和表達(dá)式
- 表達(dá)式的二叉樹(shù)展示方式
例如:(a+b×(c-d))-e/f,我們平時(shí)數(shù)學(xué)中表達(dá)式,其實(shí)就是所謂的中綴表達(dá)式表達(dá)式用樹(shù)形來(lái)表示,如圖所示。運(yùn)算符在樹(shù)中放在非終端結(jié)點(diǎn)的位置上,操作數(shù)放在葉子結(jié)點(diǎn)處。
當(dāng)我們對(duì)此二叉樹(shù)進(jìn)行先序、中序和后序遍歷后,便可得到表達(dá)式的前綴、中綴和后綴書(shū)寫(xiě)形式:
前綴:
-+a*b-cd/ef
中綴:
a+b*c-d-e/f
后綴:
abcd-*+ef/-
一般的解法,可以考慮將中綴表達(dá)式轉(zhuǎn)換成二叉樹(shù),在求值。
前、中、后綴表達(dá)式
舉例:
(3 + 4) × 5 - 6
就是中綴表達(dá)式
- × + 3 4 5 6
前綴表達(dá)式
3 4 + 5 × 6 -
后綴表達(dá)式中綴表達(dá)式(中綴記法)
直接按照數(shù)學(xué)邏輯求值就行了。個(gè)人感覺(jué)中綴表達(dá)式最容器轉(zhuǎn)換成二叉樹(shù)了,因?yàn)闃?shù)的特點(diǎn)是:根節(jié)點(diǎn)為運(yùn)算操作符,而非根葉子節(jié)點(diǎn)為操作數(shù),根據(jù)這個(gè)規(guī)則和表達(dá)式的優(yōu)先規(guī)則切分成根、左右子樹(shù)就可以了。-
前綴表達(dá)式(前綴記法、波蘭式)
特點(diǎn):前綴表達(dá)式的運(yùn)算符位于操作數(shù)之前。前綴表達(dá)式的計(jì)算機(jī)求值:
從右至左(其實(shí)很簡(jiǎn)單記住掃描方向,就是從第一個(gè)操作數(shù)所在的那一端開(kāi)始掃描)掃描表達(dá)式,遇到數(shù)字時(shí),將數(shù)字壓入堆棧,遇到運(yùn)算符時(shí),彈出棧頂?shù)膬蓚€(gè)數(shù),用運(yùn)算符對(duì)它們做相應(yīng)的計(jì)算(棧頂元素 op 次頂元素),并將結(jié)果入棧;重復(fù)上述過(guò)程直到表達(dá)式最左端,最后運(yùn)算得出的值即為表達(dá)式的結(jié)果。
例如前綴表達(dá)式“- × + 3 4 5 6”:
(1) 從右至左掃描,將6、5、4、3壓入堆棧;
(2) 遇到+運(yùn)算符,因此彈出3和4(3為棧頂元素,4為次頂元素,注意與后綴表達(dá)式做比較),計(jì)算出3+4的值,得7,再將7入棧;
(3) 接下來(lái)是×運(yùn)算符,因此彈出7和5,計(jì)算出7×5=35,將35入棧;
(4) 最后是-運(yùn)算符,計(jì)算出35-6的值,即29,由此得出最終結(jié)果使用棧,將中綴表達(dá)式轉(zhuǎn)換為前綴表達(dá)式
遵循以下步驟:
(1) 初始化兩個(gè)棧:運(yùn)算符棧S1和儲(chǔ)存中間結(jié)果的棧S2;
(2) 從右至左(和計(jì)算求值時(shí)的掃描方向是一致的)掃描中綴表達(dá)式;
(3) 遇到操作數(shù)時(shí),將其壓入S2;
(4) 遇到運(yùn)算符時(shí),比較其與S1棧頂運(yùn)算符的優(yōu)先級(jí):
(4-1) 如果S1為空,或棧頂運(yùn)算符為右括號(hào)“)”,則直接將此運(yùn)算符入棧;
(4-2) 否則,若優(yōu)先級(jí)比棧頂運(yùn)算符的較高或相等,也將運(yùn)算符壓入S1;(意思是棧頂?shù)倪\(yùn)算符優(yōu)先級(jí)時(shí)刻至少要高于前面入棧的)
(4-3) 否則,將S1棧頂?shù)倪\(yùn)算符彈出并壓入到S2中,再次轉(zhuǎn)到(4-1)與S1中新的棧頂運(yùn)算符相比較;
(5) 遇到括號(hào)時(shí):
(5-1) 如果是右括號(hào)“)”,則直接壓入S1;
(5-2) 如果是左括號(hào)“(”,則依次彈出S1棧頂?shù)倪\(yùn)算符,并壓入S2,直到遇到右括號(hào)為止,此時(shí)將這一對(duì)括號(hào)丟棄;
(6) 重復(fù)步驟(2)至(5),直到表達(dá)式的最左邊;
(7) 將S1中剩余的運(yùn)算符依次彈出并壓入S2;
(8) 依次彈出S2中的元素并輸出,結(jié)果即為中綴表達(dá)式對(duì)應(yīng)的前綴表達(dá)式。
下面舉例演示一下,省的畫(huà)圖了,就借用一下網(wǎng)上現(xiàn)成的吧,謝謝這位大神。
例如,將中綴表達(dá)1+((2+3)×4)-5
轉(zhuǎn)換為前綴表達(dá)式的過(guò)程如下(最后S2出棧,結(jié)果為- + 1 × + 2 3 4 5
):
-
后綴表達(dá)式(后綴記法、逆波蘭式)
特點(diǎn):后綴表達(dá)式與前綴表達(dá)式類(lèi)似,只是運(yùn)算符位于操作數(shù)之后。后綴表達(dá)式的計(jì)算機(jī)求值
與前綴表達(dá)式求值方式差不多,只是掃描方向相反,從左到右開(kāi)始掃描。將中綴表達(dá)式轉(zhuǎn)換為后綴表達(dá)式
與轉(zhuǎn)換為前綴表達(dá)式相似,遵循以下步驟:
(1) 初始化兩個(gè)棧:運(yùn)算符棧S1和儲(chǔ)存中間結(jié)果的棧S2;
(2) 從左至右(再提一次,此時(shí)操作數(shù)在左邊)掃描中綴表達(dá)式;
(3) 遇到操作數(shù)時(shí),將其壓入S2;
(4) 遇到運(yùn)算符時(shí),比較其與S1棧頂運(yùn)算符的優(yōu)先級(jí):
(4-1) 如果S1為空,或棧頂運(yùn)算符為左括號(hào)“(”,則直接將此運(yùn)算符入棧;
(4-2) 否則,若優(yōu)先級(jí)比棧頂運(yùn)算符的高,也將運(yùn)算符壓入S1(注意轉(zhuǎn)換為前綴表達(dá)式時(shí)是優(yōu)先級(jí)較高或相同,而這里則不包括相同的情況);
(4-3) 否則,將S1棧頂?shù)倪\(yùn)算符彈出并壓入到S2中,再次轉(zhuǎn)到(4-1)與S1中新的棧頂運(yùn)算符相比較;
(5) 遇到括號(hào)時(shí):
(5-1) 如果是左括號(hào)“(”,則直接壓入S1;
(5-2) 如果是右括號(hào)“)”,則依次彈出S1棧頂?shù)倪\(yùn)算符,并壓入S2,直到遇到左括號(hào)為止,此時(shí)將這一對(duì)括號(hào)丟棄;
(6) 重復(fù)步驟(2)至(5),直到表達(dá)式的最右邊;
(7) 將S1中剩余的運(yùn)算符依次彈出并壓入S2;
(8) 依次彈出S2中的元素并輸出,結(jié)果的逆序即為中綴表達(dá)式對(duì)應(yīng)的后綴表達(dá)式(轉(zhuǎn)換為前綴表達(dá)式時(shí)不用逆序)。
例如,將中綴表達(dá)1+((2+3)×4)-5
轉(zhuǎn)換為后綴表達(dá)式的過(guò)程如下(結(jié)果為1 2 3 + 4 × + 5 -
(注意S2出棧后需要逆序輸出)。):
根據(jù)表達(dá)式反推二叉樹(shù)
-
中綴表達(dá)式求二叉樹(shù):
其實(shí)記住運(yùn)算符為根節(jié)點(diǎn),然后把操作數(shù)作為左右葉子節(jié)點(diǎn),根據(jù)二叉樹(shù)的中序遍歷,構(gòu)建一棵子樹(shù),不斷自下而上,就能復(fù)原了。舉例(3 + 4) × 5 - 6
(畫(huà)了個(gè)丑圖):中綴表達(dá)式轉(zhuǎn)二叉樹(shù) -
后綴表達(dá)式求二叉樹(shù):
思路是一樣的,拿兩個(gè)操作數(shù)和一個(gè)運(yùn)算符,不斷自底向上組建二叉樹(shù)。舉例:3 4 + 5 × 6 -
后綴表達(dá)式。(寫(xiě)字太丑了,我自己都看不下去了。。。。。)
后綴表達(dá)式求二叉樹(shù) 前綴表達(dá)式轉(zhuǎn)二叉樹(shù)
抱歉,我想不出來(lái)。。。。
兩個(gè)棧共用存儲(chǔ)空間
棧滿(mǎn)條件:棧1向上增長(zhǎng),棧2向下增長(zhǎng),顯然當(dāng)top[1]和top[2]相鄰時(shí),棧滿(mǎn)。
棧和堆
棧區(qū)(stack)— 由編譯器自動(dòng)分配釋放 ,存放為運(yùn)行函數(shù)而分配的局部變量、函數(shù)參數(shù)、返回?cái)?shù)據(jù)、返回地址等。
堆區(qū)(heap) — 一般由程序員分配釋放, new, malloc之類(lèi)的,若程序員不釋放,程序結(jié)束時(shí)可能由OS回收 。