資料結構 棧和佇列
文章目錄
- 1 棧
- 2 棧的應用舉例
- 3 棧與遞迴的實現
- 4 佇列
- 5 離散事件模擬
1 棧
1.1 抽象資料型別棧的定義
棧(stack)是限定僅在表尾進行插入或刪除操作的線性表。
1.1.1 棧頂和棧尾
因此,對棧來說,表尾端有其特殊含義,稱為棧頂(top),表頭端稱為棧底(bottom)。
1.1.2 空棧
不含元素的空表稱為空棧
1.1.3 特點
棧的修改是按照後進先出的原則進行的
因此,棧又被稱為後進先出(last in first out)的線性表(簡稱(LIFO)結構)
1.1.4 上溢和下溢
上溢——當堆疊已滿時做插入操作。(top=M–1)
下溢——當堆疊為空時做刪除操作。(top=–1)
1.2 棧的表示和實現
1.2.1 順序棧
棧的順序儲存結構是利用一組地址連續的儲存單元依次存放自棧底到棧頂的資料元素,同時附設指標top指示棧頂元素在順序棧中的位置
typedef struct{
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
其中,stacksize指示棧的當前可使用的最大容量
1.2.2 鏈棧
連結堆疊就是用一個線性連結串列來實現一個堆疊結構
同時設定一個指標變數( 這裡不妨仍用top表示)指出當前棧頂元素所在鏈結點的位置
棧為空時,有top=NULL。
1.3 各種棧的判滿與判空條件
2 棧的應用舉例
棧的引入簡化了程式設計的問題,劃分了不同的關注層次,使思考範圍縮小了
2.1 數值轉換
2.2 括號匹配的檢驗
2.3 行編輯程式
2.4 迷宮求解(深度優先搜尋)
2.5 表示式求值(逆波蘭表示式)
計算機可以通過棧來計算字尾表示式的值,從而計算表示式的值。
3 棧與遞迴的實現
3.1 遞迴
如果在一個函式、過程或資料結構的定義中有應用了它自身,那麼這個函式、過程或資料結構稱為是遞迴定義的,簡稱遞迴。
遞迴最重要的是遞迴式和遞迴邊界
3.1 用分治法求解遞迴問題
3.1.1 分治法
對於一個較為複雜的問題,能夠分解成幾個相對簡單的且解法相同或類似的子問題來求解
3.1.2 必備條件
-
能將一個問題轉變成一個新問題,而新問題與原問題的解法相同或類同,不同的僅是處理的物件,且這些處理物件是變化有規律的
-
可以通過上述轉化而使問題簡化
-
必須有一個明確的遞迴出口,或稱遞迴的邊界
3.2 函式呼叫過程
3.2.1 呼叫前
3.2.1.1 將實參,返回地址等傳遞給被呼叫函式
3.2.1.2 為被呼叫函式的區域性變數分配儲存區
3.2.1.3 將控制轉移到被呼叫函式的入口
3.2.2 呼叫後
3.2.2.1 儲存被呼叫函式的計算結果
3.2.2.2 釋放被呼叫函式的資料區
3.2.2.3 依照被呼叫函式儲存的返回地址將控制轉移到呼叫函式
3.3 遞迴演算法的效率分析
空間效率 與遞迴數的深度成正比
時間效率 與遞迴樹的結點數成正比
3.4 藉助棧改寫遞迴
(1)設定一個工作棧存放遞迴工作記錄(包括實參、返回地址及區域性變數等)。
(2)進入非遞迴呼叫入口(即被呼叫程式開始處)將呼叫程式傳來的實在引數和返回地址入棧(遞迴程式不可以作為主程式,因而可認為初始是被某個呼叫程式呼叫)。
(3)進入遞迴呼叫入口:當不滿足遞迴結束條件時,逐層遞迴,將實參、返回地址及區域性變數入棧,這一過程可用迴圈語句來實現—模擬遞迴分解的過程。
(4)遞迴結束條件滿足,將到達遞迴出口的給定常數作為當前的函式值。
(5)返回處理:在棧不空的情況下,反覆退出棧頂記錄,根據記錄中的返回地址進行題意規定的操作,即逐層計算當前函式值,直至棧空為止—模擬遞迴求值過程。
4 佇列
4.1 抽象資料型別佇列的定義
佇列(queue)是一種先進先出(first in first out,縮寫為 FIFO)的線性表。
它只允許在表的一端進行插入,而在另一端刪除元素。
4.1.1 隊尾和隊頭
在佇列中,允許插入的一端叫做隊尾(rear),允許刪除的一端叫做隊頭(front)。
4.1.2 雙端佇列
雙端佇列是限定插入和刪除造作在表的兩段進行的線性表。
4.2 鏈佇列——佇列的鏈式表示和實現
用連結串列表示的佇列簡稱為鏈佇列
佇列的鏈式儲存結構是用一個線性連結串列表示一個佇列
指標front與rear分別指向實際隊頭元素與實際隊尾元素所在的鏈結點。
4.3 迴圈佇列
把佇列(陣列)設想成頭尾相連的迴圈表,使得陣列前部由於刪除操作而導致的無用空間儘可能得到重複利用,這樣的佇列稱為迴圈佇列。