在計算機科學中,AVL樹是最先發明的自平衡二叉查找樹。AVL樹得名於它的發明者 G.M. Adelson-Velsky 和 E.M. Landis,他們在 1962 年的論文 "An algorithm for the organization of information" 中發表了它。
二叉樹的常見問題及其解決程序 http://www.linuxidc.com/Linux/2013-04/83661.htm
【遞歸】二叉樹的先序建立及遍歷 http://www.linuxidc.com/Linux/2012-12/75608.htm
在JAVA中實現的二叉樹結構 http://www.linuxidc.com/Linux/2008-12/17690.htm
【非遞歸】二叉樹的建立及遍歷 http://www.linuxidc.com/Linux/2012-12/75607.htm
二叉樹遞歸實現與二重指針 http://www.linuxidc.com/Linux/2013-07/87373.htm
AVL樹的基本操作一般涉及運做同在不平衡的二叉查找樹所運做的同樣的算法。但是要進行預先或隨後做一次或多次所謂的"AVL旋轉"。
假設由於在二叉排序樹上插入結點而失去平衡的最小子樹根結點的指針為a(即a是離插入點最近,且平衡因子絕對值超過1的祖先結點),則失去平衡後進行進行的規律可歸納為下列四種情況:
平衡二叉樹某一節點的左孩子的左子樹上插入一個新的節點,使得該節點不再平衡。這時只需要把樹向右旋轉一次即可,如圖所示,原A的左孩子B變為父結點,A變為其右孩子,而原B的右子樹變為A的左子樹,注意旋轉之後Brh是A的左子樹(圖上忘在A於Brh之間標實線)
平衡二叉樹某一節點的右孩子的右子樹上插入一個新的節點,使得該節點不再平衡。這時只需要把樹向左旋轉一次即可,如圖所示,原A右孩子B變為父結點,A變為其左孩子,而原B的左子樹Blh將變為A的右子樹。
平衡二叉樹某一節點的左孩子的右子樹上插入一個新的節點,使得該節點不再平衡。這時需要旋轉兩次,僅一次的旋轉是不能夠使二叉樹再次平衡。如圖所示,在B節點按照RR型向左旋轉一次之後,二叉樹在A節點仍然不能保持平衡,這時還需要再向右旋轉一次。
平衡二叉樹某一節點的右孩子的左子樹上插入一個新的節點,使得該節點不再平衡。同樣,這時需要旋轉兩次,旋轉方向剛好同LR型相反。
向AVL樹插入可以通過如同它是未平衡的二叉查找樹一樣把給定的值插入樹中,接著自底向上向根節點折回,於在插入期間成為不平衡的所有節點上進行旋轉來完成。因為折回到根節點的路途上最多有 1.5 乘 log n 個節點,而每次AVL 旋轉都耗費恆定的時間,插入處理在整體上耗費 O(log n) 時間。
在平衡的的二叉排序樹Balanced BST上插入一個新的數據元素e的遞歸算法可描述如下:
若BBST為空樹,則插入一個數據元素為e的新結點作為BBST的根結點,樹的深度增1;
若e的關鍵字和BBST的根結點的關鍵字相等,則不進行;
若e的關鍵字小於BBST的根結點的關鍵字,而且在BBST的左子樹中不存在和e有相同關鍵字的結點,則將e插入在BBST的左子樹上,並且當插入之後的左子樹深度增加(+1)時,分別就下列不同情況處理之:BBST的根結點的平衡因子為-1(右子樹的深度大於左子樹的深度,則將根結點的平衡因子更改為 0,BBST的深度不變; BBST的根結點的平衡因子為0(左、右子樹的深度相等):則將根結點的平衡因子更改為1,BBST的深度增1;BBST的根結點的平衡因子為1(左子樹的深度大於右子樹的深度):則若BBST的左子樹根結點的平衡因子為1:則需進行單向右旋平衡處理,並且在右旋處理之後,將根結點和其右子樹根結點的平衡因子更改為0,樹的深度不變;若e的關鍵字大於BBST的根結點的關鍵字,而且在BBST的右子樹中不存在和e有相同關鍵字的結點,則將e插入在BBST的右子樹上,並且當插入之後的 右子樹深度增加(+1)時,分別就不同情況處理之。
從AVL樹中刪除可以通過把要刪除的節點向下旋轉成一個葉子節點,接著直接剪除這個葉子節點來完成。因為在旋轉成葉子節點期間最多有 log n個節點被旋轉,而每次 AVL 旋轉耗費恆定的時間,刪除處理在整體上耗費 O(log n) 時間。
刪除操作需要考慮的情況較多,具體見代碼實現吧。
在AVL樹中查找同在一般BST完全一樣的進行,所以耗費 O(log n) 時間,因為AVL樹總是保持平衡的。不需要特殊的准備,樹的結構不會由於查詢而改變。(這是與伸展樹查找相對立的,它會因為查找而變更樹結構。)
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-06/102863p2.htm