從零開始學算法---二叉平衡樹(AVL樹)


先來了解一些基本概念:

1)什么是二叉平衡樹?

之前我們了解過二叉查找樹,我們說通常來講, 對於一棵有n個節點的二叉查找樹,查詢一個節點的時間復雜度為log以2為底的N的對數。  

通常來講是這樣的, 但是。。。有例外

比如,我們向一棵樹中輸入預先排好序的數據, 如1,2,3,4,5,。。。10000, 可以想象到,將形成一棵斜樹那么查找10000就要經過9999次比較才能得到,這顯然不是我們期望看到的

所以,我們希望引入一個約束條件----任何節點的深度不得過深。

這就是二叉平衡樹

二叉平衡樹是二叉查找樹(排序樹)的一種,其每一個節點的左子樹和右子樹的高度差最多為1

 

 如上圖, 左邊兩棵樹並不是二叉平衡樹, 因為節點58的左子樹和右子樹高度差>1。 (分別為2和3)

2)平衡因子?

二叉樹上節點的左子樹高度 減去 右子樹高度, 得到的結果稱為該節點的平衡因子

3)最小不平衡樹?

當我們給一個二叉平衡樹增加新的節點時,會產生最小不平衡樹

以   距離插入節點最近的,平衡因子大於1的節點   為根的樹, 我們稱為最小不平衡樹

 

 

 了解了基本概念之后,我們來看看如何構建一棵二叉平衡樹

來看一個例子,我們從初始的空AVL樹開始插入3,2,1, 當插入1時, AVL的性質在根(3)處被破壞,此時,我們需要在根與其左兒子間實施單旋轉以解決這個問題

 

 我們繼續插入節點4, 這沒什么問題, 但當我們插入節點5時, AVL的性質在節點3處被破壞, 因此, 我們需要在節點3與其右兒子之間實施一次左旋來解決這個問題

 

 現在我們再插入節點6,此時AVL的性質在根節點(2)處被破壞, 因此我們在根節點和其右節點4之間實施一次左旋

 

 左旋的結果是 4成為根節點,2成為4的左兒子, 4 原本的左兒子3成為2的右兒子

現在再插入節點7, 此時AVL的性質在節點5處被破壞, 因此我們在5節點和其右節點6之間實施一次左旋

 

 根據上面的操作,我們現總結處兩條規律:(太繞口,不用記,看圖能理解就可以)

假設當我們插入新節點時,導致了原AVL樹在節點 p 處不平衡,那么

1)如果添加的新節點是p的左兒子的左兒子, 則在p和其左兒子之間實施一次右旋轉, p變成其左兒子的右兒子(如果其左兒子原本已經有右兒子, 則原本的右兒子成為p的左兒子)

2)如果新加的節點是p的右兒子的右兒子, 則在p和其右兒子之間實施一次左旋轉,p變成其右兒子的左兒子(如果其右兒子原本已經有左兒子, 則原本的左兒子成為p的右兒子)

感覺頭都轉暈了😄

but...真正復雜的還在后面。。。。。。。。

現在我們給上面的二叉樹插入節點16,這沒什么問題, 再插入15, 此時二叉樹在節點7處不再平衡,這時我們發現單旋轉已經不能解決問題了, 如果只是在7和16之間左旋的話,15將成為16的右節點,這顯然不符合二叉排序樹的性質。

因此這里我們需要兩次旋轉,先在15和16之間進行一次右旋,右旋之后就滿足了上文規律2)的條件,此時再進行一次左旋

 

 現在我們再插入14, 跟上面情況類似,插入之后需要執行先右旋再左旋的操作

 

 現在讓我們再做個小結,

當我們插入新節點時,導致了原AVL樹在節點 p 處不平衡,那么

3)如果添加的新節點是p的右兒子的左兒子, 則先在其右兒子和右兒子的左兒子之間實施一次右旋轉, 再在p和其右兒子之間實施一次左旋轉

3)如果添加的新節點是p的左兒子的右兒子, 則先在其左兒子和左兒子的右兒子之間實施一次左旋轉, 再在p和其左兒子之間實施一次右旋轉

 

再高度總結下: 同向時單旋轉,異向時雙旋轉

 原理就到這里了, 代碼實現比較復雜,這里就不再寫了,個人覺得沒有必要,因為AVL樹是最古老的平衡樹, 我們了解其原理是為了下一步----更好的理解紅黑樹。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM