--- title: 'AVL Tree' disqus: hackmd --- [TOC] ## AVL Tree * 在 BST 裡最佳時間為 $O(log_2n)$ 最差時間為 $O(n)$ 相距甚遠, 此章所探討正是為了使 $BST$ 能夠穩定的成長方法 使用高度平衡 $(Height\ Balanced)$: 使得最差情況下仍然是 $O(log_2n)$ * $BST\ +\ Heighted\ Balanced\ = AVL\ Tree$ **Def:** 1. 是一顆 $Height\ Balanced\ Binary\ Search\ Tree$ ( 高度平衡二元搜尋樹 ) 2. 任意 $Node$ 之 $Left\ Subtree$ 與 $Right\ Subtree$ 高度差:左子樹高度 $-$ 右子樹高度為 $-1,0,1$,也就是說 $|H_L-H_R|\leq 1$ 3. 因為是 $BST$ 所以記得以 $Root$ 為基準的值,大小會在不同邊 ![](https://i.imgur.com/YNjD8Lv.png) --- ### Unbalanced Condition - 未平衡狀況 * 若出現以下四種情況需要調整,L 及 R 代表 Left、Right Child 1. LL ![](https://i.imgur.com/jGQ1qqb.png =200x) 3. LR ![](https://i.imgur.com/UGeHKLC.png =200x) 5. RL ![](https://i.imgur.com/wDxrpRh.png =200x) 7. RR ![](https://i.imgur.com/gj7y6qG.png =200x) <br><br><br> * 其實這四種情況大致可以分類成兩種 (個人分類),分別是 **LR LL 及 RL RR** <br> * LR 需先 **向左單旋轉 ( Single Right Rotation )** 得 LL ![](https://i.imgur.com/6QqCTxA.png =300x) * RL 需要 **向左單旋轉 ( Single Left Rotation )** 得 RR ![](https://i.imgur.com/QT2OwEh.png =300x) * 而 LL 及 RR 在旋轉一次即可達到我們想要的平衡結果 ![](https://i.imgur.com/Vkk31GC.png =600x) <br><br> * 整個關係就會像這樣 ![](https://i.imgur.com/t2cftjn.png) * 方向下面會開始討論還不用急著弄懂,記得我們的目標就是這個就行了 ```graphviz digraph graphname{ 1[label=""] 2[label=""] 3[label=""] 1->2 1->3 } ``` --- ### Rotation - 旋轉 * Single Rotation 單旋轉:將 LR 及 RL 下半旋轉 ![](https://i.imgur.com/c8jM3Gg.png =400x) * Rotation 旋轉:將 LL 及 RR 整個節點旋轉 ![](https://i.imgur.com/NjiTKVd.png =400x) <br><br><br> #### ==向左單旋轉 Single Left Rotation== * 如下圖所示 ( 數字為 Index,方便理解用 ) * 將 2 替換到 4 * 將 3 替換到 2 這兩個動作一起就會像是一個左旋轉, 而這樣的動作在值域 (值的大小區分) 的判斷也是符合 Binary Tree 的定義 ![](https://i.imgur.com/WwvaGt5.png =400x) <br><br><br> * 我們把 Index 換成 Data 來看 * 40 比 30 大,所以當 40 變成 Parent 的時候 30 自然是他的 Left Child ( 小於30 ) ![](https://i.imgur.com/ILPI5Nl.png) <br><br><br> * 你要考慮的不僅僅如此而已,這兩個 Node 彼此都有可能自帶 Child ![](https://i.imgur.com/ZIsUKOt.png =300x) <br><br><br> * 所幸我們只需要稍微理解一下 C Node 的關係,其餘的都挺直覺的 ![](https://i.imgur.com/6MYyfHq.png =300x) <br><br><br> * **A Node** 的 Left Child 很直覺的跟著下去,並保持在左側 ![](https://i.imgur.com/WeRRtNY.png) <br><br><br> * **B Node** 的 Right Child 很直覺的跟著上去,並保持在右側 ![](https://i.imgur.com/vaYNNm1.png) <br><br><br> * **C Node** 我們代入值進去觀察,看起來可以放在 70 的 Right Child以及 90 的 Left Child 但是謹記著他們的 Parent 80,若放在 90 的 Left Child 代表著 75 > 80 ,所以我們只剩下 70 的 Right Child 可放 ![](https://i.imgur.com/SRoYrOn.png) <br><br><br> * 如圖所示 ![](https://i.imgur.com/FegfaXk.png =500x) <br><br><br> * 回過頭在看一次,所以當 B 有 Left Child 時,單旋轉完後它會變成 A 的 Right Child,Node C 程式部分即為 `A Node->RightChild = C Node`,其他的就照著直覺改動即可 ![](https://i.imgur.com/nkpPsB0.png =500x) --- #### ==向右單旋轉 Single Right Rotation== * 由於是 **向左單旋轉** 的鏡像操作,細節不再贅述 * 如下圖所示 ( 數字為 Index ) * 將 2 替換到 4 * 將 3 替換到 2 這兩個動作一起就會像是一個右旋轉 ![](https://i.imgur.com/Z0u7kZO.png =400x) <br><br><br> * 我們把 Index 換成 Data 來看 ![](https://i.imgur.com/d5AlqHH.png) <br><br><br> * 同樣需理解一下 C Node 的關係 ![](https://i.imgur.com/MWUvBOT.png =300x) <br><br><br> * 如圖所示 ![](https://i.imgur.com/JciT89z.png) <br><br><br> * 回過頭看,程式部分為 `A Node->LeftChild = C Node` ![](https://i.imgur.com/0YF4O5l.png =500x) <br><br><br> --- #### ==向左旋轉 Left Rotation== * 旋轉的想法很簡單,如圖所示 ( 數字為 Index ) ![](https://i.imgur.com/RnelqoD.png =500x) <br><br><br> * 代入值進去探討 ![](https://i.imgur.com/yFgp2OC.png =500x) <br><br><br> * 同樣考慮 Child 的關係 ![](https://i.imgur.com/ET5HU6J.png =300x) <br><br><br> * 代入值進去 ![](https://i.imgur.com/NZH67jk.png) <br><br><br> * 將 Child 放置正確位置,發現需要特別更動的,是原來 600 的 Left Child 550 ![](https://i.imgur.com/glEKwbz.png =530x) <br><br><br> * 回頭來看,關於 C Node 程式部分 `A Node->RightChild = C Node` ![](https://i.imgur.com/u80DErn.png =550x) --- #### ==向右旋轉 Right Rotation== * 同樣為 **向左旋轉** 的鏡像操作,如圖所示 ( 數字為 Index ) ![](https://i.imgur.com/lWeX4uQ.png =500x) <br><br><br> * 代入值進去探討 ![](https://i.imgur.com/08vMdpZ.png =500x) <br><br><br> * 同樣考慮 Child 的關係 ![](https://i.imgur.com/j6Moz0S.png =300x) <br><br><br> * 代入值進去,特別更動的是原來 50 的 Right Child 70 ![](https://i.imgur.com/5DN7WPS.png =550x) <br><br><br> * 回頭來看,關於 C Node 程式部分 `A Node->LeftChild = C Node` ![](https://i.imgur.com/Mk0i8Az.png =550x) :::warning 旋轉的部分請熟悉,之後 Red-Black Tree 的 **Node調整** 就是倚靠旋轉而來 ::: --- ### 形成高為 n 的 AVL Tree 所需最少 Nodes * 使用費式數列,其值恰為 $F_{n+2}-1$ ![](https://i.imgur.com/EAJSegm.png) * 例:高度為 5 之 AVL Tree = $F_{5+2}-1=13-1=12$ :::success 證明:數學歸納法 ::: ###### tags: `Data Structure`