平衡二叉樹的定義 (AVL—— 發明者爲Adel'son-Vel'skii 和 Landis)
平衡二叉查找樹,又稱 AVL樹。 它除了具備二叉查找樹的基本特徵之外,還具有一個非常重要的特點:它 的左子樹和右子樹都是平衡二叉樹,且左子樹和右子樹的深度之差的絕對值(平衡因子 ) 不超過1。 也就是說AVL樹每個節點的平衡因子只可能是-1、0和1(左子樹高度減去右子樹高度)。
那麼如何是二叉查找樹在添加數據的同時保持平衡呢?基本思想就是:當在二叉排序樹中插入一個節點時,首先檢查是否因插入而破壞了平衡,若 破壞,則找出其中的最小不平衡二叉樹,在保持二叉排序樹特性的情況下,調整最小不平衡子樹中節點之間的關係,以達 到新的平衡。所謂最小不平衡子樹 指離插入節點最近且以平衡因子的絕對值大於1的節點作爲根的子樹。
平衡二叉樹的操作
1. 查找操作
平衡二叉樹的查找基本與二叉查找樹相同。
2. 插入操作
在平衡二叉樹中插入結點與二叉查找樹最大的不同在於要隨時保證插入後整棵二叉樹是平衡的。那麼調整不平衡樹的基本方法就是: 旋轉 。 下面我們歸納一下平衡旋轉的4中情況
1) 繞某元素左旋轉
80 90
/ \ 左旋 / \
60 90 ---- -> 80 120
/ \ / \ /
85 120 60 85 100
/
100
a) BST樹 b ) AVL樹
分析一下:在插入數據100之前,a圖的B ST樹只有80節點的平衡因子是-1(左高-右高),但整棵樹還是平衡的。加入100之後,80節點的平衡因子就成爲了-2,此時平衡被破壞。需要左旋轉成b 圖。
當樹中節點X的右孩子的右孩子上插入新元素,且平衡因子從-1變成-2後,就需要繞節點X進行左旋轉。
2) 繞某元素右旋轉
100 85
/ \ 右旋 / \
85 120 ------ -> 60 100
/ \ \ / \
60 90 80 90 120
\
80
a) B ST樹 b) AVL樹
當樹中節點X的左孩子的左孩子上插入新元素,且平衡因子從1變成2後,就需要繞節點X進行右旋轉。
3) 繞某元素的左子節點左旋轉,接着再繞該元素自己右旋轉。 此情況下就是左旋與右旋 的結合,具體操作時可以分解成這兩種操作,只是圍繞點不一樣而已。
100 100 90
/ \ 左旋 / \ 右旋 / \
80 120 ------> 90 120 ------> 80 100
/ \ / / \ \
60 90 80 60 85 120
/ / \
85 60 85
當樹中節點X的左孩子的右孩子上插入新元素,且 平衡因子從1變成2後,就需要 先繞X的左子節點Y左旋轉,接着再繞X右旋轉
4) 繞某元素的右子節點右旋轉,接着再繞該元素自己左旋轉。 此情況下就是 右旋與左旋 的結合,具體操作時可以分解 成這兩種操作,只是圍繞點不一樣而已 。
80 80 85
/ \ 右 旋 / \ 左 旋 / \
60 100 ------> 60 85 -------> 80 100
/ \ \ / / \
85 120 100 60 90 120
\ / \
90 90 120
當樹中節點X的右孩子的左孩子上插入新元素,且 平衡因子從-1變成-2後,就需要 先繞X的右子節點Y右旋轉,接着再繞X左旋轉
平衡二叉樹性能分析
平衡二叉樹的性能優勢:
很顯然,平衡二叉樹的優勢在於不會出現普通二叉查找樹的最差情況。其查找的時間複雜度爲O(logN)。
平衡二叉樹的缺陷:
(1) 很遺憾的是,爲了保證高度平衡,動態插入和刪除的代價也隨之增加。
(2) 所有二叉查找樹結構的查找代價都與樹高是緊密相關的,能否通過減少樹高來進一步降低查找代價呢。我們可以通過多路查找樹的結構來做到這一點。
(3) 在大數據量查找環境下(比如說系統磁盤裏的文件目錄,數據庫中的記錄查詢 等),所有的二叉查找樹結構(BST、AVL、RBT)都不合適。如此大規模的數據量(幾G數據),全部組織成平衡二叉樹放在內存中是不可能做到的。那麼把這棵樹放在磁盤中吧。問題就來了:假如構造的平衡二叉樹深度有1W層。那麼從根節點出發到葉子節點很可能就需要1W次的硬盤IO讀寫。大家都知道,硬盤的機械部件讀寫數據的速度遠遠趕不上純電子媒體的內存。 查找效率在IO讀寫過程中將會付出巨大的代價。在大規模數據查詢這樣一個實際應用背景下,平衡二叉樹的效率就很成問題了。