算法導論讀書筆記(10)
棧和隊列
棧和隊列都是動態集合。棧實現了一種 先進先出 的策略。相似地,隊列實現了一種 後進先出 的策略。java
棧
做用於棧上的 INSERT
操做稱爲 壓入 ( PUSH
),而無參的 DELETE
操做常稱爲 彈出 ( POP
)。能夠使用一個數組 S [ 1 .. n ]來實現一個至多有 n 個元素的棧。以下圖所示,數組 S 有個屬性 S.top ,它指向最近插入的元素。算法
STACK-EMPTY(S) 1 if S.top == 0 2 return TRUE 3 else 4 return FALSE
PUSH(S, x) 1 S.top = S.top + 1 2 S[S.top] = x
POP(S) 1 if STACK-EMPTY(S) 2 error "underflow" 3 else 4 S.top = S.top - 1 5 return S[S.top + 1]
隊列
咱們把做用於隊列上的 INSERT
操做稱爲 入隊 ( ENQUEUE
),把做用於隊列上的 DELETE
操做稱爲 出隊 ( DEQUEUE
)。隊列有 頭 和 尾 。當一個元素入隊時,將排在隊尾,而出隊的元素老是隊首元素。下圖說明了用一個數組 Q [ 1 .. n ]來實現一個至多含 n - 1 個元素的隊列的方法。隊列具備屬性 Q.head ,它指向隊列的頭,另外一個屬性爲 Q.tail ,它指向新元素將會被插入的地方。sql
ENQUEUE(Q, x) 1 Q[Q.tail] = x 2 if Q.tail == Q.length 3 Q.tail = 1 4 else 5 Q.tail = Q.tail + 1
DEQUEUE(Q) 1 x = Q[Q.head] 2 if Q.head == Q.length 3 Q.head = 1 4 else 5 Q.head = Q.head + 1 6 return x
鏈表
在 鏈表 中,各對象按線性順序排序。其順序由各對象中的指針決定。本節介紹的是無序的雙鏈表。 雙鏈表 的每個元素都是一個對象,每一個對象包含一個關鍵字域和兩個指針域: next 和 prev 。對鏈表中的某個元素 x , x.next 指向鏈表中 x 的後繼元素,而 x.prev 則指向鏈表中 x 的前驅元素。下面給出的是鏈表的基本操做。數組
LIST-SEARCH(L, k) 1 x = L.head 2 while x != NIL and x.key != k 3 x = x.next 4 return x
LIST-INSERT(L, x) 1 x.next = L.head 2 if L.head != NIL 3 L.head.prev = x 4 L.head = x 5 x.prev = NIL
LIST-DELETE(L, x) 1 if x.prev != NIL 2 x.prev.next = x.next 3 else 4 L.head = x.next 5 if x.next != NIL 6 x.next.prev = x.prev
有根樹的表示
用鏈表表示有根樹bash
二叉樹
以下圖所示,用域 p , left , right 來存放指向二叉樹 T 中的父親,左兒子和右兒子的指針。若是 x.p = NIL
,則 x 爲根。若是結點 x 無左兒子,則 x.left = NIL
,對右兒子也相似。整個樹 T 的根由屬性 T.root 指向。若是 T.root = NIL
,則樹爲空。ide
分支數無限的有根樹
能夠用二叉樹很方便地表示具備任意子女數的樹。該方法的優勢是對任意含 n 個結點的有根樹僅用 O ( n )空間。這種 左孩子 , 右兄弟 的表示以下圖所示。每一個結點都包含一個父親指針 p , T.root 指向樹 T 的根。每一個結點 x 再也不包含指向每一個孩子結點的指針,而僅包含兩個指針:post
- x.left-child 指向結點 x 的最左孩子。
- x.right-sibling 指向結點 x 緊右邊的兄弟。
若是 x 沒有孩子,則 x.left-child = NIL
;若是 x 是其父結點的最右孩子,則 x.right-sibling = NIL
。spa