王道408数据结构——第三章 栈和队列
一、棧
棧(Stack)是只允許在一端進行插入或刪除操作的線性表。
棧頂:線性表允許插入刪除的那一端
棧底:固定的、不允許進行插入刪除的另一端
棧的操作特性可以概括為后進先出(LIFO)
n個不同的元素進棧,出棧元素不同的排列個數為C2nnn+1=1n!(2n)!n!1n+1=(2n)!n!(n+1)!\frac{C^n_{2n}}{n+1}=\frac{1}{n!}\frac{(2n)!}{n!}\frac{1}{n+1}=\frac{(2n)!}{n!(n+1)!}n+1C2nn??=n!1?n!(2n)!?n+11?=n!(n+1)!(2n)!?(卡特蘭數)
順序棧
采用順序存儲的棧稱為順序棧,利用一組地址連續的存儲單元存放自棧底到棧頂的數據元素,同時附設一個指針(top)指示當前棧頂元素的位置。
共享棧
利用棧底位置相對不變的特性,可以讓兩個順序棧共享一個一維數組空間,將兩個棧的棧底分別設置在共享空間的兩端,兩個棧頂向共享空間的中間延伸。
共享棧是為了更有效地利用存儲空間,兩個棧的空間相互調節,只有在整個存儲空間被占滿時才發生上溢。
鏈棧
采用鏈式存儲的棧稱為鏈棧,優點是便于多個棧共享存儲空間和提升效率,不存在棧滿上溢的情況。通常采用單鏈表實現,規定所有操作在表頭進行。
二、隊列
隊列(Queue)只允許在表的一段進行插入,而在表的另一端進行刪除。
隊頭(Front):允許刪除的一端。
隊尾(Rear):允許插入的一端。
其特性概括為先進先出(FIFO)
隊列的順序儲存
分配一塊連續的存儲單元存放隊列中的元素,并設隊頭指針front(指向隊頭元素)和隊尾指針rear(指向隊尾元素下一個位置)
循環隊列
將順序隊列臆造為一個環狀的空間,即把存儲隊列元素的表從邏輯上視為一個環,稱為循環隊列,當隊首指針Q.front = MAXSIZE - 1后,再前進一個位置就自動到0,可以利用取余運算。
隊頭指針front指向隊頭元素,隊尾指針rear指向隊尾元素的下一個指針。
初始時:Q.front = Q.rear = 0
隊首指針進一(出隊):Q.front = (Q.front + 1) % MAXSIZE
隊尾指針進一(入隊):Q.rear = (Q.rear + 1) % MAXSIZE
隊列長度:(Q.rear + MAXSIZE - Q.front) % MAXSIZE
隊空:Q.front == Q.fear
隊滿:(Q.rear + 1) % MAXSIZE == Q.front
隊列的鏈式存儲
隊列的鏈式表示稱為鏈隊列,實際上是一個同時帶有隊頭指針和隊尾指針的單鏈表。
用單鏈表表示的鏈式隊列特別適合于數據元素變動較大的情形,而且不存在隊列滿產生溢出的問題。
雙端隊列
指允許兩端都進行入隊出隊操作的隊列,其元素的邏輯結構仍是線性結構。
- 輸出受限的雙端隊列:允許在一端進行插入和刪除,但在另一端只允許插入的雙端隊列。
- 輸入受限的雙端隊列:允許在一端進行插入和刪除,但在另一端只允許刪除的雙端隊列
三、隊列和棧的應用
括號匹配
算法如下
初始設置一個空棧,順序讀入括號:
- 若是左括號,將其壓入棧中;
- 若是右括號,則將其與棧頂的括號進行匹配:
- 若棧頂是類型相同的左括號,使其出棧
- 若棧頂括號類型不匹配,則匹配不成功,退出程序
當括號序列讀取完畢時,若???#xff0c;則匹配成功,否則匹配不成功。
表達式求值
后綴表達式(逆波蘭表達式)
后綴表達式的運算符在操作數的后面,在后綴表達式中已考慮了算符的優先級。后綴表達式只有操作數和算符,無需括號。
后綴表達式與表達式樹的后序遍歷序列相同。
算法如下
初始設置一個空棧,順序讀入后綴表達式的每一項,根據其類型決定操作:
- 若為操作數:將其壓入棧中
- 若為運算符<op>:連續從棧中彈出兩個操作數Y、X,進行X<op>Y運算,并將結果壓入棧中
當表達式的所有項都處理完后,棧頂存放的就是最后的計算結果。
棧在遞歸中的應用
將遞歸算法轉換為非遞歸算法,需要借助棧實現。
但對于單項遞歸和尾遞歸,可以用迭代的方式消除遞歸。
尾遞歸:程序中只有一句遞歸語句,且在末尾。
單向遞歸:指程序中的遞歸語句,在本程序操作執行前,都已經完成,如斐波那契數列。
這樣一來,它們共同的特點是在化非遞歸時都沒有非要保存的分支路線
隊列在層次遍歷中的應用
使用隊列保存下一步的處理順序。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的王道408数据结构——第三章 栈和队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 王道408数据结构——第二章 线性表
- 下一篇: 王道408数据结构——第四章 串(KMP