1.07k likes | 1.85k Views
資料結構 第五章:樹( Tree ). 鄧姚文 ywdeng@mail.knu.edu.tw http://w3.im.knu.edu.tw/~joseph/. 樹的概念. 具有層次關係 家族族譜 組織架構 生物演化樹 檔案系統 運算樹. A. B. C. D. E. F. G. H. I. K. L. M. N. J. 樹狀結構. 高度(或深度)等於 4 的樹. 定義. 樹( Tree )為節點( Node )組成的有限集合,其中 存在一特殊節點 R 稱為樹根( Root )
E N D
資料結構第五章:樹(Tree) 鄧姚文 ywdeng@mail.knu.edu.tw http://w3.im.knu.edu.tw/~joseph/
樹的概念 • 具有層次關係 • 家族族譜 • 組織架構 • 生物演化樹 • 檔案系統 • 運算樹
A B C D E F G H I K L M N J 樹狀結構 高度(或深度)等於 4 的樹
定義 • 樹(Tree)為節點(Node)組成的有限集合,其中 • 存在一特殊節點R稱為樹根(Root) • 其他節點可分割成n個無交集的集合T1,T2,…,Tn,n0,而T1,T2,…,Tn本身皆為樹,稱為R的子樹(Subtree)。 • 樹林(Forest)是由 n (n0)個互斥樹(Disjoint Tree)所組成的 • 一樹移去樹根節點後即形成樹林
專有名詞 • 節點(Node):代表資料 • 邊(Edge):代表連結(Link),單向 • 祖先(Ancestor)節點 VS 子孫(Descendant)節點 • 根節點(Root Node):為所有節點的祖先 • 父節點:Father Node或Parent Node,指子樹的上層節點 • 子節點:Child Node指一節點之子樹的根 • 兄弟節點(Sibling Node)同父節點的子節點
專有名詞(續) • 非終點節點(Non-Terminal Node)有子節點者 • 終點節點(Terminal Node):又稱為樹葉節點(Leaf Node),沒有子節點者 • 分支度(Degree):一節點的子樹數目 • 分支度=0者稱為樹葉(Leaf Node)或終端節點(Terminal Node) • 分支度>0者稱為Non-terminal Node或Internal Node • 定義:一棵樹的分支度等於其所有節點分支度的最大值
專有名詞(續) • 階層(Level)又稱為階度定義樹根的Level=1,階層 L 的節點其子節點的階層為 L+1 • 高度(Height)或深度(Depth): • 節點的高度:此節點至樹根節點的最長路徑(Path)長度 • 樹的高度,定義為該樹節點中所擁有的最大階度
R T1 T2 Tm … 基本性質 • 若一樹 T 的總節點數(Node)為 V,總邊(Edge)數為 E,則V=E+1 • 以數學歸納法證明Apply Induction on V 除了 Root 之外,每一個 Node 上方都有一個 Edge
V=E+1 歸納法證明 • Induction Base 基底 • 當 V=1 時,E=0,V=E+1 成立 • Induction Hypothesis 假設 • 當 1≦V≦K 時,V=E+1 • Induction Steps 推論 • 當 V=K+1 時,令樹根為 R,R 有 m 個子樹 T1、T2、…、Tm,分別有V1、V2、…、Vm個節點,其中V1+V2+..+Vm=K • 若E1、E2、…、Em分別為這 m 個子樹的邊數,則 E=E1+E2+…+Em+m --------------------------式<1>
V=E+1 歸納法證明(續) • 由假設得知 • V1=E1+1、V2=E2+1、…、Vm=Em+1 • 所以 • V1+V2+…+Vm=E1+E2+Em+m ------------------式<2> • 然而 • V=V1+V2+…+Vm+1 -----------------------------式<3> • 將式<2>代入式<3>,得到 • V=E1+E2+Em+m+1 • 引用式<1>,可得 • V=E+1
Data Subtree 1 Subtree 2 …. Subtree k k 個指標 樹的表示法 k = Degree of the tree
樹的表示法一般化串列(Generalized List) • 串列(List):有限且有順序的元素集合 • 一般化串列(Generalized List):串列中的元素資料型態不必相同 • T=(R,T1,T2,…,Tn) • 例: • (A,(B,(E,K),(F,L,M),G),(C,H),(D,(I,N),(J,O,P))) • T=(A,T1,T2,T3) • T1=(B,(E,K),(F,L,M),G) • T2=(C,H) • T3=(D,(I,N),(J,O,P)) • 此法又稱為『巢狀括弧法』
(A,(B,(E,K),(F,L,M),G),(C,H),(D,(I,N),(J,O,P))) A B C D E F G I J H K L M N O P
最左邊的兒子 最右邊的兄弟 Left-Most-Child Data Right-Most-Sibling 樹的表示法左子右兄弟表示法 Left Child, Right Sibling Representation 優點:不管樹的 Degree 是多少,只需要 2 個指標
左兒子 右兒子 Left Child Data Right Child 二元樹(Binary Tree) • 分支度為2的樹:二元樹(Binary Tree) • 左子右兄弟樹是二元樹
二元樹(Binary Tree) • 定義:二元樹是一個由節點組成的有限集合,可以是空集合,或是包含了: • 一個樹根節點 • 其他節點分割成兩個沒有交集的二元樹,其一為左子樹(Left Subtree),另一為右子樹(Right Subtree) • 一般樹與二元樹的差異: • 二元樹的節點數可以為零,一般樹至少由一個節點組成 • 一般樹的子樹沒有順序,而二元樹的子樹有左右之分 • 二元樹的分支度至多為 2,一般樹則無此限制 • 任何樹皆可轉換成二元樹
A A B B 分辨二元樹 • 二元樹的子樹有左右之分 不同的兩棵二元樹
最小的樹 最小的二元樹 分辨『樹』與『二元樹』
A B C D E 歪斜樹(Skew Tree) 左歪斜樹
基本性質 • 一棵二元樹在第 i 階度(Level)上最多有2i-1 個節點,i1 • 一棵深度為 k 的二元樹,最多有 2k-1 個節點,k1 • 一棵二元樹,若 n0為樹葉節點的數量,n2為分支度為 2 的節點數量,則n0 = n2 + 1
基本性質完滿二元樹(Full Binary Tree) • 定義:完滿二元樹(Full Binary Tree)又稱為滿枝二元樹一個高度為 k 的二元樹,且其節點數為 2k-1,k0
基本性質完整二元樹(Complete Binary Tree) • 定義:深度為 k,節點數為 n的二元樹稱為完整二元樹(或譯為完備二元樹),若且為若當 1i<k時,階層 i 有 2i-1 個節點,且第 k 層的節點皆由第 k-1 層的分支由左向右逐一連接而成
基本性質 • n 個節點的 Complete Binary Tree 或 Full Binary Tree 其深度為 log2(n+1) • 也可以寫成 log2n+1
基本性質正規二元樹(Formal Binary Tree) • 若二元樹的所有內部節點恰有2個子節點,則稱之為正規二元樹 • 又稱為嚴格二元樹(strictly binary tree)
二元樹表示法 • 以陣列表示 • 適合 Full Binary Tree • 不適合 Skew Tree(歪斜樹) • 容易 Traversal • 以鍵結串列(Linked List)表示 • 動態配置
Complete Binary Tree 基本性質 • 若一個具有 n 個節點的 Complete Binary Tree 以循序的方式編號,並依序存放在陣列A中,即第 i 個節點存放在 A[i] 中,1in,則 • 根節點位於 A[1] • 節點 i 的父節點位在 A[i/2],i1 • 若 2in,則節點 i 的左兒子位在 A[2i],若 2i>n,則節點 i 沒有左兒子 • 若 2i+1n,則節點 i 的右兒子位在 A[2i+1],若2i+1>n,則節點 i 沒有右兒子 • 以歸納法證明
0 以陣列表示 Binary Tree A[i] 的兒子在 A[2i]、A[2i+1] A 1 2 B C 3 4 D 5 E F 6 G 7 8 9 10 H 11 I 12 13 14 以一維陣列儲存 Binary Tree 適合 Full Binary Tree 不適合 Skew Tree
以鍵結串列(Linked List)表示樹 • 以鍵結串列(Linked List)表示 • 動態配置 typedef struct _tree_node_ { int data; /* 資料區 */ struct _tree_node_ * llink; /* 指向 Left Subtree */ struct _tree_node_ * rlink; /* 指向 Right Subtree */ } Node_type;
二元樹走訪(Traversal) • Depth-First Traversal 深先走訪 • 中序 In-order(左、中、右) • 前序 Pre-order(中、左、右) • 後序 Post-order(左、右、中) • Breadth-First Traversal 廣先走訪 • 階層走訪 Level-order Traversal • Depth-First Traversal 使用堆疊,Breadth-First Traversal 使用佇列
中序走訪(In-order Traversal) void inorder(Node_type *node) { if(node != NULL) { inorder(node->llink); printf("%d\n", node->data); inorder(node->rlink); } }
前序走訪(Preorder Traversal) void preorder(Node_type *node) { if(node != NULL) { printf("%d\n", node->data); preorder(node->llink); preorder(node->rlink); } }
後序走訪(Postorder Traversal) void postorder(Node_type *node) { if(node != NULL) { postorder(node->llink); postorder(node->rlink); printf("%d\n", node->data); } }
廣先走訪(Breadth First Traversal) void bft(Node_type *root) { Node_type *node; if (NULL == root) return; init_queue(); enqueue(root); while (!queue_empty()) { node = dequeue(); printf("%d\t", node->data); if (node->llink != NULL) { enqueue(node->llink); } if (node->rlink != NULL) { enqueue(node->rlink); } } }
+ * E / D A % C B Traversal Example Depth First: 中序:A/B%C*D+E 前序:+*/A%BCDE 後序:ABC%/D*E+ Breadth First: +*E/DA%BC
二元搜尋樹(Binary Search Tree) • 定義: • 二元搜尋樹是一個二元樹,可能是空二元樹,若不為空二元樹則滿足: • 每一節點均含有一鍵值(Key),每個鍵值都不一樣 • 左子樹的所有鍵值均小於樹根的鍵值 • 右子樹的所有鍵值均大於樹根的鍵值 • 左子樹和右子樹亦是二元搜尋樹
二元搜尋樹(Binary Search Tree) • 搜尋:類似 Binary Search • 插入:依照 key 的大小,尋找適當的插入點 • 刪除:找到該節點之後刪除 • Terminal Node:直接刪除 • Non-Terminal Node:找一個節點來補位 • 左子樹最大 key 的節點 • 右子樹最小 key 的節點 • 詳見程式範例
二元搜尋樹(Binary Search Tree)的特性 • 二元搜尋樹若長成 Complete Binary Tree 的形狀,則搜尋時間為 O(log N),相當於 Binary Search • 二元搜尋樹若長成 Skew Tree 的形狀,則搜尋時間為 O(N),退化成 Sequential Search • 資料插入的順序影響二元搜尋樹的長相 • 二元搜尋樹的中序走訪產生從小到大的資料排序結果
引線二元樹(Threaded Binary Tree) • V=E+1 • 共有 2V 個指標,其中2V–E = 2V-(V-1) = V+1個指標是浪費掉的 • Threaded Binary Tree • 將原本浪費掉的指標廢物利用,讓 In-Order Traversal 更迅速 • Left-Child -> In-Order Predecessor • Right-Child -> In-Order Successor • 用一個額外的 Bit 判斷指標內容是 Link 還是 Thread
引線二元樹表示法 Lbit=1, Llink 正常指標 Lbit=0, Llink 引線 Rbit=1, Rlink 正常指標 Rbit=0, Rlink 引線
將二元樹轉換為引線二元樹的步驟 • 先將二元樹經由中序走訪方式依序排出,並將所有空鏈結改成引線。 • 如果引線鏈結是指向該節點的左鏈結,則將該引線指到中序走訪順序下的前一個節點。 • 如果引線鏈結是指向該節點的右鏈結,則將該引線指到中序走訪順序下的後一個節點。 • 最左邊樹葉節點的左鏈結和最右邊樹葉節點的右鏈結指向一個空節點,並將此空節點的右鏈結指向自己,而空節點的左子樹是此引線二元樹。
面對現實,引線二元樹真的好嗎? • 在現實的系統環境中,引線二元樹的 RBIT 和 LBIT 都不以 bit 實作,而是以 Integer 實作 • 引線二元樹為了善用 V+1 個指標,又增加了 2V 的空間實作引線。 • 優點:引線二元樹做中序走訪不需要堆疊 • 缺點:加入節點、刪除節點的程序變得更複雜了
如何將一般樹化為二元樹 • 一般樹轉為二元樹 • 左子右兄弟法 • 順時針旋轉45度 • 樹林轉為二元樹 • 每一棵樹各自做左子右兄弟法 • 把所有樹的樹根節點連結 • 旋轉45度
決定唯一的二元樹 • 每一棵二元樹皆有唯一的一對 • 中序+前序 • 中序+後序 • 前序+後序無法決定二元樹
TEST • 一二元搜尋樹(Binary Search Tree)的Traversal結果如下,請畫出此二元搜尋樹: • 中序:20,40,43,45,50,60,70,80 • 後序:20,43,45,40,60,80,70,50 • 在此二元搜尋樹中加入一節點key=65後,請畫出此二元搜尋樹。 • 在此二元搜尋樹中刪除根節點(root),經重整後此二元搜尋樹變成如何? • 將此二元搜尋樹轉換成引線二元樹(Threaded Binary Tree) • 在此引線二元樹中,在節點key=70的左方插入一節點key=68,經重整後此引線二元樹變成如何?
什麼樣的二元搜尋樹比較好? • 什麼樣的二元搜尋樹比較好? • 優:Complete Binary Tree • 劣:Skew Tree • 如果有冷門資料與熱門資料之分? • 熱門資料應該放靠近樹根
延伸二元搜尋樹Extended Binary Search Tree • 一棵 N 個節點的二元樹有 N+1 個空白的鍵結(Link) • 延伸二元搜尋樹(Extended Binary Search Tree) • 將這 N+1 個空白鍵結以外部節點(External Node)標示(方形節點) • 外徑長(External Path Length)E • 所有外部節點到樹根距離的總和 • 內徑長(Internal Path Length)I • 所有內部節點到樹根距離總和 • E=I+2N
延伸二元搜尋樹Extended Binary Search Tree 內部節點 Internal Node 外部節點 External Node
加權外徑長Weighted External Path Length • 節點數 n(外部節點數 n+1) • qi:外部節點加權值(Weight) • ki:樹根至外部節點 i 的外徑長 • 如何達成最小的加權外徑長(Minimal Weighted External Path Length)? • Huffman Tree
Huffman Tree • 作法: • 以所有的外部節點形成一個串列 • 挑出兩個最小加權的子樹 x, y,結合成一個新子樹 z,新子樹的加權 z=x+y,將新子樹放回串列。 • 重複直到串列中只剩一棵樹 • 特性:擁有最小的加權外徑長 • 用途: • 可以編出長度最短的碼(Huffman Code) • 資料壓縮、秘密通訊