資料結構-樹與二元樹
考研相關文章參考資料為 wjungle 大神提供的筆記
樹 (Tree)
- 由
>0 個節點 (Node)所構成 - 森林 (Forest): 由
>=0 個樹所構成 (可以為空)
表示方式
-
Link list
- Node: | Data | child 1 | child 2 | … | child k
- 假設 degree 為 ,並且有 個節點,會浪費 條 Link (Nil links)
-
轉為二元樹表示
-
Child-sibling方法- Node: | Data | child | sibling |
- child: 指向
leftmost-child - sibling: 指向
次右兄弟
-
括號法
- 以
父(子1,子2,...子n)表示父點與子點之間的關係,並且可以巢狀方式表示
- 以
二元樹 (BT)
可以為空,若不為空則滿足:- 有
root及左右子樹 - 左右子樹也是二元樹
- 有
- 與樹比較:
| 樹 | 二元樹 |
|---|---|
| 不能為空 | 可以為空 |
| 子樹之間無次序/方向之分 | 子樹有左右之分 |
基本定理
- 二元樹第 level 的最多 Node 數為
高度為 的二元樹,最多 Node 數為- 若二元樹有 個 Node,則其最小高度為
- 給予一個非空的二元樹,若
leaf有 個,Degree-2的 Node 數有 個,則
分類
skewed BT(斜曲)- left-skewed BT: 每個 Node 都只有左節點
- right-skewed BT: 每個 Node 都只有右節點
Full BT(完滿)- 高度為 的
Full BT擁有最多的 Node 數 ()
- 高度為 的
Complete BT(完整)- 高度為 的
Complete BT的 Node 數 - Node 編號順序與高度為 的
Full BT之前 個點編號一一對應 (由上而下,由左而右) - 若 Node 數為 ,某 Node 之編號為 ,則:
- 左子點編號為 ,若 則無左子點
- 左子點編號為 ,若 則無左子點
- 父點編號為 ,若 則無父點
- 高度為 的
Strict BT(嚴格)- 每個非 leaf 節點必有兩個子點 ()
表示方式
-
Array
- 若樹高度為 ,準備一個 ,將 Node 資料存入
Full BT對應的編號 - 若為
Complete/Full BT有 個節點,只需要 - 優點:
- 易於存取左右節點及父點
- 對於
Complete/Full BT可以充分利用空間
- 缺點:
- 不易插入/刪除 Node (可能需要改變高度)
- 對於
skewed BT極為浪費空間 (浪費 格)
- 若樹高度為 ,準備一個 ,將 Node 資料存入
-
Link list
- Node: | Lchild | Data | Rchild |
- 優點:
- 易於插入/刪除 Node
- 對於
skewed BT相較 Array 省空間
- 缺點:
- 不易存取父節點
- 浪費約 50% 的 Link ( 個 Node 會有 條 Nil link)
追蹤 (Traversal)
拜訪
BT中每個 Nodes 各一次
- 前序 (
Preorder): DLR - 中序 (
Inorder): LDR - 後序 (
Postorder): LRD level-order(依照level由上而下,由左而右)
決定二元樹
中序 + 前序/後序/level-order: 可決定唯一的BT前序/後序/level-order 三選二: 無法決定唯一的BT- ex: 給定 前序ABC + 後序CBA,能夠決定出四顆不同的
BT
- ex: 給定 前序ABC + 後序CBA,能夠決定出四顆不同的
- 如果是
Complete BT,前序/中序/後序 可決定唯一的BT
產生 BT 個數
個 Nodes 可以形成的
BT個數
- (卡塔蘭數)
- 遞迴定義:
- 假設左子樹有 個節點: ()
- 右子樹會有 個節點:
二元搜尋樹 (BST)
- 是一個二元樹,若不為空則滿足:
- 左子樹所有 Nodes 之值小於 Root
- 右子樹所有 Nodes 之值大於 Root
- 左右子樹也是
BST
- 對
BST進行中序遍歷,可以得到由小到大的排序 - 插入&建立: 受到順序的影響
- 刪除:
- 如果是葉節點: 直接刪除
- 如果是
Degree-1的節點: 將該節點的父點指向該點子節點 - 如果是
Degree-2的節點: 以該節點的左子樹最大值/右子樹最小值替代該節點,並且對要替代的節點進行處理
- 比較次數:
- 成功: 內部節點的
level - 失敗: 外部節點的
level - 1 - 平均比較次數 ( 個節點):
skewed BT:Full BT:
- 成功: 內部節點的
堆積 (Heap)
- 是一個
Complete BT,並且滿足:- 所有
父點都 >= (<=) 子點之值 - Root 具有最大 (小) 值
- 所有
- 適合使用
array保存 (Complete BT) - 插入:
- 將插入的節點放置於最後一個節點的後面
- 往上不斷
挑戰父節點並交換位置,直到無父點或是挑戰失敗
- 刪除
Max (Min):- 移走根結點,並且用最後一個節點取代
- 將取代的節點
由上而下不斷調整,直到滿足Heap為止
- 建立:
- Top-down ():
- 依序進行插入操作
- Bottom-up ():
- 將所有節點以
Complete BT 表示 - 從
最後一個父點開始倒推,依序調整每顆子樹成為Heap,直到調整到 Root 為止
- 將所有節點以
- Top-down ():
Tree/Forest 轉為 BT
Tree
Leftmost-Child-Next-Right-Sibling
- 正向 (
Tree->BT):- 建立 Sibling 之間的 Links
- 刪除父節點與子節點之間的連結,只
保留 Leftmost-Child 的 Link - 順時針旋轉 45 度 (Leftmost-Child -> 左子點,Next-Right-Sibling -> 右子點)
- 反向 (
BT->Tree):- 逆時針旋轉 45 度 (
右子點拉上成為父點的 Next-Right-Sibling) - 補足父子節點之間的 Links
- 刪除 Sibling 間的 Links
- 逆時針旋轉 45 度 (
Forest
- 正向 (
Forest->BT)- 將 Forest 中的每棵樹都化為
BT - 將
每個 BT 的 roots 視為 Sibling建立 Links - 將串接的 roots 順時針旋轉 45 度
- 將 Forest 中的每棵樹都化為
- 反向 (
BT->Forest)- 將 root 之右子點拉上成為 root 的 Sibling
- 刪除 roots 之間的 Sibling Links 得到多顆
BT - 每個
BT再化為 Tree
Disjoint Sets
- 由一組
互斥之集合組成 - 每個 set 利用樹的結構表示 (從 set 中選一點作為 root,其餘為它的子點)
- Link list
- Array: 紀錄每個點的 Parent (root 的 Parent 為 0/-1)
Union & Find
Union(i, j): 聯集 所在的集合與 所在的結合任意的 Union:- 取 的集合的 root 為 new root,另一個 set 為它的子樹
- 可能產生一個高度為 樹,使得 Find 需要 的時間
Union-by-Height (Weight):- 取
樹高較高 (節點較多)者作為 new root,另一個 set 為它的子樹 - 如果樹高 (節點) 相同則作任意的 Union
- 如果是高度相同的 set 作 Union,樹的高度會增加 1,否則高度不變 (與樹高較高者相同)
- 產生的樹最高為 ,Find 最多需要 的時間
- 取
Find(x): 找出 所在的集合,傳回 root (or root->data)Simple-Find:- 沿著 的 Parent link 往上尋找,直到找到 root 並傳回
- 需要 的時間 (h 為樹高)
Find-with-Path-Compression- 尋找 root 時,將 Parent link 上面的所有 Nodes 的
Parent 改為 root - 平均成本為 ,約為 (趨近 )
- 尋找 root 時,將 Parent link 上面的所有 Nodes 的
引線二元樹 (Thread BT)
為了充分利用 link list 中的 條 nil links
- 將 nil links 作為
Thread pointer,指向其他 Nodes- x->lchild 作為左引線,指向
中序順序中的前一個 Node - x->rchild 作為右引線,指向中序順序中的後一個 Node
- x->lchild 作為左引線,指向
- Structure
- Node: | Left Thread | Lchild | Data | Rchild | Right Thread |
- Left Thread:
- True: Lchild 是左引線
- False: Lchild 是左子點
- Right Thread:
- True: Rchild 是右引線
- False: Rchild 是右子點
- 增加一個
Head node (串列首)- 不存 Data
Rchild 指向自己(Right Thread = False)- 空樹:
Lchild 指向自己(Left Thread = True) - 非空樹:
Lchild 指向 root(Left Thread = False)
Insuc(x): 找出 的中序後繼者- 若 x->Right Thread == True,則
x->Rchild即是 - 若 x->Right Thread == False
- 沿著 的右子點之左子點往左下尋找,直到該 Node 之 Left Thread==True (
右子樹的最左子點)
- 沿著 的右子點之左子點往左下尋找,直到該 Node 之 Left Thread==True (
- 若 x->Right Thread == True,則





