天天看點

AVL樹

本章代碼是上一篇《二叉樹初步總結》的序章,主要記錄AVL樹的學習過程。

概念:AVL樹是一種自平衡樹,添加或移除節點時AVL樹會嘗試保持自平衡,任意一個節點的左子樹和右子樹高度最多相差1,添加或移除節點時,AVL樹會盡可能嘗試轉換為完全樹。

首先,定義一個AVLTree類

該類隻需要結成BinarySearchTree類,再對其中的插入、移除方法進行覆寫即可。

其次,定義一個計算節點高度的方法

 該方法利用了遞歸原理,隻要節點不為空,就一直向下查,每查一次就+1,直到查到最終結果為止。

再定義一個計算平衡因子的方法

  為了避免在代碼中直接處理平衡因子的數值,建立一個用來作為計數器的常量

AVL樹

如圖所示,可以清晰的看出AVL樹與非AVL樹的差別。

旋轉

為了将不平衡的樹進行平衡,就需要通過旋轉的方式來進行操作,旋轉應該如何了解?

右旋轉

AVL樹

  如圖示,這樣一棵樹左右子節點的高度差為1,他是處于平衡狀态的,但是,當我們再插入一個節點5之後

AVL樹

  目前樹的左右子節點高度差達到了2,這個時候平衡性已經被破壞了,就需要進行一些操作去平衡它。

  平衡之後樹為

  

AVL樹

這時候執行的操作就是旋轉,這麼說可能不太明白

AVL樹

看圖示,這個時候就是以節點7為原點,将15節點向右側旋轉,旋轉之後再用7這個節點去替代原來的15節點,即可以生成一個滿足平衡需求的樹。注意,在調整時,找離最新插入的節點最近的不平衡的樹進行調整。

AVL樹

現在看一種複雜一點的情況,是節點15存在右側子節點的時候,這個時候我們需要執行四步操作

将節點15置于節點20所在的位置

将節點15的左側子節點保持不變

将節點20的左側子節點置為節點15的右側子節點

将節點15的右側子節點置為節點20

最終結果是這樣的

AVL樹

整個流程的代碼如下

左旋轉

左旋轉即某個節點的右側子節點導緻不平衡的時候,需要對右側子節點進行左旋轉來保證平衡,整體思路與右轉選一樣,代碼如下

先左旋轉再右旋轉

AVL樹

如圖所示,這種情況是根節點的左側子節點的右側子節點導緻的不平衡,首先,我們對左側子節點進行平衡,我們知道當右側子節點不平衡時使用左轉

AVL樹

對根節點20的左側子節點進行左旋之後的結果如圖所示,這個時候就變成了所有導緻不平衡的情況都是左側子節點導緻的,是以這個時候再對整棵樹進行向右的旋轉

AVL樹

代碼如下:

先右旋轉再左旋轉

先右再左是當右側子節點的左側子節點導緻不平衡時的情況使用的,和先左再右相反,代碼如下:

向AVL樹中插入節點

與普通二叉樹不同的是,每次插入值之後,都需要去判斷一下目前這個節點是否失衡了,如果失衡了需要去進行相應的旋轉平衡節點

  整體思路為,先插入相應節點,然後去判斷這個節點在插入子節點之後是否失衡了,如果是左側子節點失衡再去判斷插入的值是插入了左側子節點還是右側子節點,如果是左側子節點那麼直接右旋,如果是右側子節點就需要先左旋再右旋。當是右側失衡時思路相反。

  移除節點

  移除節點時直接調用之前的移除節點的方法,然後再對樹的平衡進行檢測,再針對左側子節點的左側子節點不平衡、左側子節點的右側子節點不平衡,右側子節點的左側子節點不平衡,右側子節點的右側子節點不平衡這幾種情況進行相應的旋轉處理。