數據結構與算法-二叉查找樹平衡(AVL)

上節討論的DSW算法能夠從全局從新平衡樹:每一個節點均可能參與樹的從新平衡,或者從節點中移除數據,或者從新設置指針的值。可是,當插入或刪除元素時,將隻影響樹的一部分,此時樹的從新平衡能夠只在局部進行。局部平衡二叉查找樹有一個鼎鼎大名的算法,叫作AVL算法,由AVL算法構建出來的二叉樹稱之爲AVL樹。
AVL樹首先是一顆二叉查找樹,其次,AVL樹要求每一個節點左右子樹的高度差最大爲1。例如,圖1-1中的全部樹都是AVL樹。節點中的數字表示平衡因子,即左右子樹的高度差。平衡因子等於右子樹的高度減去左子樹的高度。對於AVL樹,全部的平衡因子都應是+一、0或-1。平衡AVL樹的技術不保證獲得的樹是徹底平衡的,但倒是高度平衡的。有關平衡的概念能夠參考數據結構與算法-二叉查找樹平衡(DSW)。
假設咱們已經有了一顆AVL樹,那麼如何保證在插入或者刪除元素時繼續保持AVL樹的特性呢?
  • 插入
前人對於AVL樹的插入操做進行總結,發現一共有4種狀況須要討論。其中,在左子樹中插入有兩種狀況,在右子樹中插入也有兩種狀況。而且它們是對稱的,所以,咱們以右子樹爲例,只須要討論兩種狀況便可。
假設咱們在AVL樹中插入一個新的節點p,那麼p的父節點以及祖父節點的平衡因子都有可能改變,咱們從下到上更新節點的平衡因子,若是發現某個節點的平衡因子成爲+2或者-2,那麼就以該節點爲根截取這段子樹。若是根節點平衡因子成爲了+2,表明節點插入到了右子樹中,若是根節點平衡因子成爲了-2,表明節點插入到了左子樹。咱們這裏只討論+2,即節點插入到右子樹上的兩種狀況。
若是節點平衡因子變成了+2,那麼,咱們能夠將這顆子樹抽象出來,它必然是下面這種樣子:
也就是說,若是插入新節點使P節點的平衡因子成了+2,那麼以P爲根的子樹,必然是上面的樣子。插入的新節點要麼放在Q的左子樹上,要麼放在Q的右子樹上,這就是咱們要討論的兩種狀況。
一、RR
第一種狀況有個簡稱,叫作RR,也就是說新節點插入到右子樹的右節點,就像這樣:
怎麼處理呢?P節點的左子樹比右子樹低,還記得左旋的效果嗎?左旋能夠提升左子樹的高度,下降右子樹的高度,用在這裏正合適。將Q節點圍繞P節點進行左旋以後效果以下:
很是完美,左旋在這裏產生了兩個效果。首先,左旋使當前子樹從新保持平衡,其次,左旋沒有改變當前子樹的高度。左旋以前子樹高度爲h + 2,左旋以後依然是h + 2。這就意味着,從Q節點開始往上的節點不須要更新平衡因子了。因此,左旋使得算法變得足夠簡單。
  • RL
顧名思義,RL的意思是將新節點插入到右子樹的左節點上,就像這樣:
怎麼處理呢?首先仍是左旋,可是很快你會發現,左旋確實提升了左子樹高度,可是過高了,又形成了新的不平衡,就像這樣:
究其緣由,是h + 1那顆子樹大大提升了左子樹高度,咱們必須把它放在右子樹上才行,能夠這樣處理。首先,咱們認爲,若是是由於在P樹的右子樹的左節點上插入元素致使P節點不平衡,那麼,在沒有插入新節點以前,P樹確定是下面這種樣子的:
Q的左子樹插入了新的節點,可能插入到R的左子樹或者右子樹,先無論這個,爲了下降Q的左子樹的高度,將R圍繞着Q進行右旋,結果是這樣:
靠譜,R的左子樹高度就是就是m1樹的高度,既多是h - 1,也多是h,可是都比h + 1要小,這時咱們再作一次左旋,結果以下:
完美,R樹最終平衡了,而且R樹的高度依然保持在h + 2,這也意味着沒必要更新R節點之上的祖先節點的平衡因子了。至於P和Q節點的平衡因子,這要看新節點是插入到m1樹仍是m2樹上了,可是不管如何,R樹都已經高度平衡了。
總結一下,對於RL形式的子樹,首先對右子樹的左節點作一次右旋,而後對新的根節點作一次左旋便可。
插入還有LL,LR兩種形式,可是它們分別和RR,RL形式對稱,這裏就很少介紹了。
這裏有個我看到的很是精闢的總結,引用一下:
下面介紹刪除節點以後如何平衡二叉查找樹。
  • 刪除
刪除比插入更加複雜,可是有着插入節點積累的經驗,理解刪除反而更加容易。
刪除節點首先面對的問題是平衡因子從哪一個節點開始變化的?這就要說到二叉查找樹的刪除邏輯了,在數據結構與算法-二叉查找樹中有着詳細的介紹。這裏簡單介紹一下,刪除葉子節點或者度爲1的節點,平衡因子從被刪除節點的父節點開始變化。刪除度爲2的節點須要使用複製刪除的技巧,使用被刪除節點的直接前驅或者直接後繼來替換被刪除節點,而後刪除直接前驅或者直接後繼,那麼,平衡因子就是從直接前驅或者直接後繼的父節點開始變化的。
既然知道了平衡因子開始變化的節點,就能夠從下到上的更新平衡因子的變化。
在探討插入節點引發的二叉樹的變化時,咱們總結出了RR、RL、LL、LR四種狀況,刪除節點會引發怎樣的變化呢?
刪除和插入有兩個不一樣點:
一、刪除不只包含以上四中變化,還多出兩種,固然這兩種也是對稱的
多出來的兩種是當前節點的父節點的平衡因子等於+2或者-2時,當前節點的平衡因子等於0。
插入節點之因此沒有這兩種變化,是由於插入節點使當前節點平衡因子變成0,說明當前節點的高度沒有變化,更加不會引發祖先節點的平衡因子變化了。而刪除節點時,若是當前節點平衡因子變成0,那麼當前節點的高度其實變小了,可能引發祖先節點的平衡因子變化。
怎麼處理這種狀況呢?若是父節點平衡因子等於+2,那就對當前節點進行左旋。若是父節點平衡因子等於-2,那就對當前節點進行右旋便可。
二、從新平衡過程沒有在發現平衡因子爲+2或者-2的第一個節點P後中止,而是追蹤到根節點
在插入節點的從新平衡過程當中,咱們在乎的是第一個平衡因子爲+2或者-2的節點,緣由在於咱們執行左旋或者右旋以後,子樹不只從新平衡而且高度也和沒有插入節點以前保持一致,所以,祖先節點的平衡因子就不會發生變化了。可是刪除節點發生了變化,從新平衡以後子樹的高度變小了。
爲何從新平衡以後,插入節點高度不變而刪除節點高度變小呢?
能夠思考下平衡的過程,假設平衡因子變化爲+2的節點爲P,它的左子樹高度爲h,右子樹高度必然爲h + 1,只有在右子樹插入新的節點,P節點的平衡因子纔會變化爲+2,從新平衡以後該樹的左右子樹高度爲h + 1,所以該樹的高度h + 2沒有變化。可是對於刪除又有不一樣,假設P節點左子樹高度爲h,右子樹高度必然爲h + 1,只有在左子樹刪除節點以後,P節點的平衡因子纔會變化爲2,從新平衡以後該樹的左右子樹的高度爲h,那麼該樹的高度h + 1比原來就減小了1。由於上述緣由,刪除節點以後從新平衡的邏輯不能只執行一次,而是從平衡因子發生變化的節點開始往上一直追蹤到根節點,發現不平衡的節點都要執行平衡邏輯。
到此爲止,AVL樹中添加和刪除節點的邏輯已經探討完畢。固然,這裏純粹是學術上的探討,沒有代碼示例,更加精深的內容須要在實踐中摸索。
知識的積累歷來不是看了一兩篇文章就能夠完成的,畢竟,功夫在詩外。

數據結構與算法-自適應二叉樹
html

相關文章
相關標籤/搜索