from https://www.cnblogs.com/zhujunxxxxx/p/3348798.htmlhtml
AVL樹是根據它的發明者G.M. Adelson-Velsky和E.M. Landis命名的。它是最早發明的自平衡二叉查找樹,也被稱爲高度平衡樹。相比於"二叉查找樹",它的特色是:AVL樹中任何節點的兩個子樹的高度最大差異爲1。它是一種高度平衡的二叉排序樹。高度平衡?意思是說,要麼它是一棵空樹,要麼它的左子樹和右子樹都是平衡二叉樹,且左子樹和右子樹的深度之差的絕對值不超過1。linux
將二叉樹上結點的左子樹深度減去右子樹深度的值稱爲平衡因子BF,那麼平衡二叉樹上的全部結點的平衡因子只多是-一、0和1。只要二叉樹上有一個結點的平衡因子的絕對值大於1,則該二叉樹就是不平衡的。 數組
平衡二叉樹的前提是它是一棵二叉排序樹。 post
距離插入結點最近的,且平衡因子的絕對值大於1的結點爲根的子樹,稱爲最小不平衡子樹。以下圖所示,當插入結點37時,距離它最近的平衡因子的絕對值超過1的結點是58。學習
一、平衡二叉樹實現原理 spa
平衡二叉樹構建的基本思想就是在構建二叉排序樹的過程當中,每當插入一個結點時,先檢查是否因插入而破壞了樹的平衡性,如果,則找出最小不平衡子樹。在保持二叉排序樹特性的前提下,調整最小不平衡子樹中各結點之間的連接關係,進行相應的旋轉,使之成爲新的平衡子樹。 下面講解一個平衡二叉樹構建過程的例子。如今又a[10] = {3, 2, 1, 4, 5, 6, 7, 10, 9, 8}須要構建二叉排序樹。在沒有學習平衡二叉樹以前,根據二叉排序樹的特性,一般會將它構建成以下左圖。雖然徹底符合二叉排序樹的定義,可是對這樣高度達到8的二叉樹來講,查找是很是不利的。所以,更加指望構建出以下右圖的樣子,高度爲4的二叉排序樹,這樣才能夠提供高效的查找效率。3d
如今來看看如何將一個數組構成出如上右圖的樹結構。 對於數組a的前兩位3和2,很正常地構建,到了第個數「1」時,發現此時根結點「3」的平衡因子變成了2,此時整棵樹都成了最小不平衡子樹,須要進行調整,以下圖圖1(結點左上角數字爲平衡因子BF值)。由於BF爲正,所以將整個樹進行右旋(順時針),此時結點2成了根結點,3成了2的右孩子,這樣三個結點的BF值均爲0,很是的平衡,以下圖圖2所示。htm
而後再增長結點4,平衡因子沒有改變,如上圖圖3。增長結點5時,結點3的BF值爲-2,說明要旋轉了。因爲BF是負值,對這棵最小平衡子樹進行左旋(逆時針旋轉),以下圖圖4,此時整個樹又達到了平衡。blog
繼續增長結點6時,發現根結點2的BF值變成了-2,以下圖圖6所示。因此對根結點進行了左旋,注意此時原本結點3是結點3的左孩子,因爲旋轉後須要知足二叉排序樹特性,所以它成告終點2的右孩子,如圖7所示。排序
增長結點7,一樣的左旋轉,使得整棵樹達到平衡,以下圖8和9所示。
當增長結點10時,結構無變化,如圖10所示。再增長結點9,此時結點7的BF變成了-2,理論上只須要旋轉最小不平衡樹七、九、10便可,可是,若是左旋轉後,結點9變成了10的右孩子,這是不符合二叉排序樹的特性的,此時不能簡單的左旋。如圖11所示。
仔細觀察圖11,發現根本緣由在於結點7的BF是-2,而結點10的BF是1,也就是說,它們兩個一正一負,符號並不統一,而前面的幾回旋轉,不管左仍是右旋,最小不平衡子樹的根結點與它的子結點符號都是相同的。這就是不能直接旋轉的關鍵。 不統一,不統一就把它們先轉到符號統一再說,因而先對結點9和結點10進行右旋,使得結點10成了9的右子樹,結點9的BF爲-1,此時就與結點7的BF值符號統一了,如圖12所示。
這樣再以結點7爲最小不平衡子樹進行左旋,獲得以下圖13。接着,插入8,狀況與剛纔相似,結點6的BF是-2,而它的右孩子9的BF是1,如圖14,所以首先以9爲根結點,進行右旋,獲得圖15,此時結點6和結點7的符號都是負,再以6爲根結點左旋,最終獲得最後的平衡二叉樹,如圖16所示。
經過這個例子,能夠發現,當最小不平衡樹根結點的平衡因子BF是大於1時,就右旋,小於-1時就左旋,如上例中的結點一、五、六、7的插入等。插入結點後,最小不平衡子樹的BF與它的子樹的BF符號相反時,就須要對結點先進行一次旋轉以使得符號相同後,再反向旋轉一次纔可以完成平衡操做,如上例中結點九、8的插入時。
目前linux kernel裏已再也不使用平衡二叉樹,代之以紅黑樹rbtree。