一、棧
1.1 棧的定義
- 棧(Stack):只允許在一端進行插入或刪除操作的線性表。首先棧是一種線性表,但是限定這種線性表只能在某一端進行插入和刪除操作。
- 棧頂(Top):線性表允許進行插入和刪除的那一端。
- 棧底(Bottom):固定的,不允許進行插入和刪除的另一端。
- 空棧:不含任何元素的空表。
1.2 棧的基本操作
- InitStack(&S):初始化一個空棧 S。
- StackEmpty(S):判斷一個棧是否為空,若棧 S 為空返回 true,否則返回 false。
- Push(&S,x):進棧,若棧 S 未滿,將 x 加入使之成為新棧頂。
- Pop(&S,&x):出棧,若棧 S 非空,彈出棧頂元素,并用 x 返回。
- GetTop(S,&x):讀棧頂元素,若棧頂元素為空,用 x 返回棧頂元素。
- ClearStack(&S):銷毀棧,并釋放棧 S 占用的存儲空間。
1.3 棧的順序存儲結構
- 順序棧的實現:棧的順序存儲稱為順序棧,是利用一組地址連續的存儲單元存放自棧底到棧頂的數據元素,同時附設一個指針(Top)指示當前棧頂的位置。
- 順序棧的基本運算:初始化、判棧空、進棧、出棧、讀棧頂元素。
- 共享棧:利用棧底位置相對不變的特性,可以讓兩個順序棧共享一個一維數據空間,將兩個棧的棧底分別設置在共享空間的兩端,兩個棧頂向共享空間的中間延申。
1.4 棧的鏈式存儲結構
- 采用鏈式存儲的棧成為鏈棧,鏈棧的優點是便于多個棧共享存儲空間和提高其效率,且不存在棧滿上溢的情況。
- 通常采用單鏈表實現,并規定所有操作都是在單鏈表的表頭進行。
- 采用鏈式存儲,便于結點的插入與刪除。
二、隊列
2.1 隊列的定義
- 隊列簡稱隊,是一種操作受限的線性表,只允許在表的一端進行插入,而在表的另一端進行刪除。向隊列中插入元素稱為入隊或進隊;刪除元素稱為出隊或離隊。
- 操作特性為先進先出,又被稱為先進先出的線性表。
- 隊頭(Front):允許刪除的一端,又稱為隊首。
- 隊尾(Rear):允許插入的一端。
- 空隊列:不含任何元素的空表。
2.2 隊列的順序存儲結構
- 隊列的順序存儲:隊列的順序實現是指分配一塊連續的存儲單元存放隊列中的元素,并附設兩個指針 front 和 rear 分別指示隊頭元素和隊尾元素的位置。
- 初始條件(對空條件):Q.front == Q.rear == 0;
- 進隊操作:隊不滿時,先送值到隊尾元素,再送隊尾指針加 1。
- 出隊操作:隊不空時,先取隊頭元素值,再將隊頭指針加 1。
- 隊空條件為:Q.rear == MaxSize ;
2.3 循環隊列
- 把存儲隊列元素的表從邏輯上看成一個環,當隊首指針 Q.front = MaxSize-1后,再前進一個位置就自動到 0,可利用除法取余(%)來實現。
- 初始時:Q.front = Q.rear = 0;
- 隊首指針進 1:Q.front = (Q.front+1)%MaxSize;
- 隊尾指針進 1:Q.rear = (Q.rear+1)%MaxSize;
- 隊列長度:(Q.rear+MaxSize-Q.front)%MaxSize;
- 出隊入隊時:指針都按順時針方向進 1;
- 犧牲一個單元來區分隊空和隊滿,入隊少用一個隊列單元,即隊頭指針在隊尾指針的下一個位置作為隊滿的標志。
- 隊滿條件為:(Q.rear+1)%MaxSize==Q.front。
- 隊空條件為:Q.front == Q.rear。
- 隊中元素的個數:(Q.rear-Q.front+MaxSize)%MaxSize
- 類型中增設表示元素個數的數據成員
- 隊空:Q.size = 0;
- 隊滿:Q.size = MaxSize;
- 上述兩種情況均有Q.front = Q.rear
- 類型中增設 tag 數據成員,以區分是隊空還是隊滿。
- tag 等于零的情況下,若因刪除導致Q.front == Q.rear 則為隊空;
- tag 等于 1 的情況下,若因插入導致Q.front == Q.rear 則為隊滿;
- 循環隊列的操作:初始化,判隊空,入隊,出隊
2.4 隊列的鏈式存儲結構
- 隊列的鏈式表示稱為鏈隊列,是一個同時帶有隊頭指針和隊尾指針的單鏈表。
- 頭指針指向頭節點,尾指針指向尾結點,即鏈表的最后一個結點。
- 當 Q.front == NULL,且 Q.rear == NULL 時,鏈表隊列為空。
- 出隊時,首先判斷隊是否為空,若不空,則取出隊頭元素,將其從鏈表中摘除,并讓 Q.front 指向下一個結點(若該節點為最后一個節點,則置 Q.front 和 Q.rear 都為NULL)。
- 入隊時,建立一個新節點,將新節點插入到鏈表的尾部,并改讓 Q.rear 指向這個新插入的結點(若原隊列為空隊,則令 Q.front 也指向該節點。
- 用單鏈表表示的鏈式隊列特別適合于數據元素變動比較大的情形,而且不存在隊列滿且產生溢出的問題。
- 假如程序中要使用多個隊列,于多個棧的情況一樣,最好使用鏈式隊列,這樣就不會出現存儲分配不合理和溢出的問題。
- 鏈式隊列的基本操作:初始化,判隊空,入隊,出隊
2.5 雙端隊列
- 雙端隊列是指允許兩端都可以進行入隊和出隊操作大的隊列,其元素的邏輯結構仍是線性,將隊列的兩端分別稱為前端和后端,兩邊都可以入隊和出隊。
- 在雙端隊列進隊時:前端進的元素排列在隊列中后端進的元素后面,后端進的元素排列在隊列中前端元素進的元素的后面。
- 在雙端隊列出隊時:無論前端還是后端出隊,先出的元素排在后出的元素前面。
- 輸出受限的雙端隊列:允許在一端進行插入和刪除,但在另一端只允許插入的雙端隊列稱為輸出受限的雙端隊列。
- 輸入受限的雙端隊列:允許在一端進行插入和刪除,但在另一端只允許刪除的雙端隊列稱為輸入受限的雙端隊列。而如果限定雙端隊列從某個端點插入的元素只能從該端點刪除,則該雙端隊列就蛻變為兩個棧底相鄰接的棧了。
三、棧和隊列的應用
- 棧在括號匹配中的應用
- 棧在表達式求值中的應用
- 棧在遞歸中的應用
- 隊列在層次遍歷中的應用
- 隊列在計算機系統中的應用
四、特殊矩陣的壓縮存儲
- 矩陣在計算機圖形學、工程計算中占有舉足輕重的地位,在數據結構中考慮的是如何用最小的內存空間來存儲同樣的一組數據。
4.1 數組
- 數組和線性表的關系:數組是線性表的推廣。一維數組可以看作是一個線性表,二維數組可以看作元素是線性表的線性表,以此類推。
- 數組一旦被定義,它的維數和維界就不再改變,因此,除了結構的初始化和銷毀之外,數組就只會有存取元素和修改元素的操作。
4.2 數組的存儲結構
- 一個數組的所有元素在內存中占用一端連續的存儲空間。
- 對于多維數組,有兩種映射方法 :按行優先和按列優先。
- 按行優先:先行后列,先存儲行號較小的元素,行號相等先存儲列號較小的元素。
- 按列優先:先列后行。
4.3 矩陣的壓縮存儲
- 壓縮存儲:指為多個值相同的元素只分配一個存儲空間,對零元素不分配存儲空間,其目的是為了節省存儲空間。
- 特殊存儲:指具有許多相同矩陣元素或零元素,并且這些相同矩陣元素或零元素的分布有一定規律性的矩陣。常見的特殊矩陣有對稱矩陣、上(下)三角矩陣、對角矩陣等。
- 特殊矩陣的壓縮存儲方法:找出特殊矩陣中值相同的矩陣元素的分布規律,把那些呈現規律性分布的值相同的多個矩陣元素壓縮存儲到一個存儲空間中。
4.4 稀疏矩陣
- 矩陣元素個數 s 相對于矩陣中非零元素個數 t 來說非常多,即 s >> t 為的矩陣稱為稀疏矩陣。
- 將非零元素及其相應的行和列構成一個三元組(行標,列標,值),然后按照某種規律存儲這些三元組。
- 稀疏矩陣壓縮存儲后便失去了隨機存取的特性。