理论基础 —— 栈
【概述】
棧(Stack)是一種特殊的線性表,只能在某一端插入和刪除的特殊線性表。它按照后進先出的原則存儲數(shù)據(jù),先進入的數(shù)據(jù)被壓入棧底,最后的數(shù)據(jù)在棧頂。
由于棧滿足先進后出,后進先出的性質,因此也被稱為先進后出表(FILO)或后進先出表(LIFO)
當棧中元素個數(shù)為零時稱為空棧。
【棧的邏輯結構】
棧的棧底固定,棧頂浮動,允許進行插入和刪除操作的一端稱為棧頂(Top),另一端為棧底(Bottom),插入一個元素稱為進棧(Push),刪除一個棧頂元素稱為出棧(Pop)。
無論是順序棧還是鏈棧,其出棧、入棧的時間復雜度均為 O(1)
當棧滿時再插入元素,將發(fā)生上溢,當棧為空時刪除元素,將發(fā)生下溢。
【棧的順序存儲結構】
1.順序棧
棧的順序存儲結構即順序棧,其使用數(shù)組來模擬棧,并設置一個棧頂指針 top,選用 a[0] 作為棧底,a[top] 作為棧頂
其元素個數(shù)存在限制,并且可能造成空間浪費。
2.雙端棧
在一個程序中有時需要同時使用具有相同數(shù)據(jù)類型的兩個棧,當為他們開辟相同的存儲空間后,某一時刻一個棧已經(jīng)滿了,而另一個棧還有很大的空間,這樣會造成存儲空間的浪費,此時可以令兩棧共享空間,即使用雙端棧。
使用一個數(shù)組來存儲兩個棧,讓一個棧的棧底為該數(shù)組的始端(a[0]),另一個棧的棧底為該數(shù)組的末端(a[n-1]),兩個棧從各自的端點向中間延伸(top1++,top2--)。
由于雙端棧的特性,因此其一般是用于具有兩??臻g需求存在相反情況時,即一個棧增長,另一個??s短的情況。
【棧的邏輯存儲結構】
棧的邏輯存儲結構即鏈棧,其將鏈表的頭指針作為棧頂,便于插入、刪除操作。
由于其空間是動態(tài)擴展的,因此一般不存在上溢的問題,只有當內存沒有可用空間時才會出現(xiàn)棧滿,但每個元素都需要一個指針域,從而產生了結構性開銷。
【實現(xiàn)】
【應用】
1.中綴表達式
中綴表達式:運算符在兩個運算對象中間,基本運算符有 +、-、*、/、()、# 等,其中 # 為中綴表達式的界定符
例如:#3*(4+2)/2-5# 就是一個中綴表達式
在進行運算時,要考慮運算符的優(yōu)先級與結合性,常見運算符優(yōu)先級表如下:
中綴表達式的求值過程用到兩個棧:運算對象棧 Opnd、運算符棧 Optr,算法偽代碼如下:
1)若當前字符是操作數(shù):入棧 Opnd
2)若當前字符是運算符
? ①當前運算符優(yōu)先級 > 棧 Optr 的棧頂運算符優(yōu)先級:入棧 Optr,處理下一字符
? ②當前運算符優(yōu)先級 <?棧 Optr 的棧頂運算符優(yōu)先級:棧 Opnd 出棧兩個操作數(shù),棧 Optr 出棧一個運算符,進行運算后將結果入棧 Opnd,處理當前字符
? ③當前運算符優(yōu)先級 = 棧 Optr 的棧頂運算符優(yōu)先級:棧 Optr 棧頂元素出棧,處理下一字符
以下圖為例:
2.中綴表達式轉后綴表達式
后綴表達式:所有的計算按照運算符出現(xiàn)的順序從左向右進行,不用考慮運算符的優(yōu)先級
例如:中綴表達式 3*(4+2)/2-5 對應后綴表達式 3 4 2 + * 2 / 5 -
為了處理方便,常將中綴表達式轉為等價的后綴表達式,在轉換過程中用到一個棧 S,算法偽代碼如下:
1)若當前字符是操作數(shù):輸出該字符,處理下一字符
2)若當前字符是運算符:
? ①當前運算符優(yōu)先級 > 棧?S 棧頂運算符優(yōu)先級:該運算符入棧 S,處理下一字符
? ②當前運算符優(yōu)先級 <?棧?S 棧頂運算符優(yōu)先級:棧 S 棧頂運算符彈出并輸出,處理當前字符
? ③當前運算符優(yōu)先級 =?棧?S 棧頂運算符優(yōu)先級:棧 S 棧頂運算符彈出,處理向下一字符
3.后綴表達式求值
后綴表達式的求值過程中用到一個棧 S,算法偽代碼如下:
1)若當前字符是操作數(shù):入棧 S,處理下一個字符
2)若當前字符是運算符:棧 S 出棧兩個操作數(shù),進行運算并將執(zhí)行結果入棧 S,處理下一個字符
以下圖為例:
?
?
總結
- 上一篇: 信息学奥赛一本通(1055:判断闰年)
- 下一篇: 数列分块入门 3(LibreOj-627