BST的性質有可能致使全部的數據都插在了同一個鏈路上,致使沒有一個節點有左子樹,都是右子樹,像是一個鏈表,失去了它的lgn的性質node
AVL是做者的名字縮寫git
每一個左子樹的高度與右子樹的高度差值不大於1github
若是是AVL+BST須要只須要在BST的基礎上加上AVL的性質,AVL自己須要去維護高度算法
另爲在一個高度爲h的AVL中節點的最少的數量,有bash
一個AVL樹,除去根節點這層,至少包含的左右兩部分爲:一邊是高度爲h-1,另外一邊是高度爲h-2spa
從上式可得:,即h<2lgn,於是獲得AVL的高度確定是lgn.net
插入過程當中,一旦出現層級超過1的狀況,須要進行旋轉,而對應出現2層的高度差異,只會出現以下4種code
1
\
2
\
3
須要進行一次左旋
2
/ \
1 3
複製代碼
1
\
3
/
2
先右旋
1
\
2
\
3
再左旋
2
/ \
1 3
複製代碼
3
/
2
/
1
右旋
2
/ \
1 3
複製代碼
3
/
1
\
2
對1進行左旋
3
/
2
/
1
再右旋
2
/ \
1 3
複製代碼
保持平衡的算法爲get
def _reblance(self,node):
while node is not None:
self._update_height(node)
if self._height(node.left) - self._height(node.right) >=2:
//左子樹要高
nodeL = node.left
if self._height(nodeL.left) < self._height(nodeL.right):
//狀況4
self._left_roate(nodeL)
//狀況3+狀況4
self._right_roate(node)
elif self._height(node.right) - self._height(node.left) >=2:
//右子樹要高
nodeR = node.right
if self._height(nodeR.left) > self._height(nodeR.right):
//狀況2
self._right_roate(nodeR)
//狀況1+狀況2
self._left_roate(node)
node = node.parent
複製代碼
左旋string
def _left_roate(self,node):
'''當前節點的右節點高度-左節點高度>=2 從上到下,按照父子一對一對處理 '''
pivot = node.right
pivot.parent = node.parent
if node == self.root:
self.root = pivot
else:
if node.parent.left is node:
pivot.parent.left = pivot
else:
pivot.parent.right = pivot
tempNode = pivot.left
pivot.left = node
node.parent = pivot
node.right = tempNode
if tempNode is not None:
tempNode.parent = node
self._update_height(pivot)
self._update_height(node)
複製代碼
右旋
def _right_roate(self,node):
'''當前節點的左節點高度-右節點高度>=2 右旋表示左邊節點高 '''
pivot=node.left
pivot.parent = node.parent
if node == self.root:
self.root=pivot
else:
if node.parent.left is node:
pivot.parent.left = pivot
else:
pivot.parent.right = pivot
node.parent = pivot
tempNode = pivot.right
pivot.right = node
node.left = tempNode
if tempNode is not None:
tempNode.parent = node
self._update_height(pivot)
self._update_height(node)
複製代碼