AVL樹是帶有平衡條件的二叉查找樹,一般要求每個節點的左子樹和右子樹的高度最多差1(空樹的高度定義為-1)。
在高度為h的AVL樹中,最少的節點數S(h)由S(h)=S(h-1)+S(h-2)+1得出,其中S(0)=1,S(1)=2。

如上圖,分別為高度為0,1,2,3的AVL樹所需要的最少節點數。
1.AVL樹的實現,遍歷與查找操作與二叉查找樹相同。
class Node(object):
def __init__(self,key):
self.key=key
self.left=None
self.right=None
self.height=0
class AVLTree(object):
def __init__(self):
self.root=None
def find(self,key):
if self.root is None:
return None
else:
return self._find(key,self.root)
def _find(self,key,node):
if node is None:
return None
elif key<node.key:
return self._find(key,self.left)
elif key>node.key:
return self._find(key,self.right)
else:
return node
def findMin(self):
if self.root is None:
return None
else:
return self._findMin(self.root)
def _findMin(self,node):
if node.left:
return self._findMin(node.left)
else:
return node
def findMax(self):
if self.root is None:
return None
else:
return self._findMax(self.root)
def _findMax(self,node):
if node.right:
return self._findMax(node.right)
else:
return node
def height(self,node):
if node is None:
return -1
else:
return node.height
2.AVL樹的插入操作
插入一個節點可能會破壞AVL樹的平衡,可以通過旋轉操作來進行修正。
插入一個節點后,只有從插入節點到根節點的路徑上的節點的平衡可能被改變。我們需要找出第一個破壞了平衡條件的節點,稱之為K。K的兩顆子樹的高度差2。
不平衡有四種情況:
1.對K的左兒子的左子樹進行一次插入
2.對K的左兒子的右子樹進行一次插入
3.對K的右兒子的左子樹進行一次插入
4.對K的右兒子的右子樹進行一次插入
情況1與4是對稱的,需要進行一次單旋轉操作,清況2與3需要一次雙旋轉操作。
情況1:


def singleLeftRotate(self,node):
k1=node.left
node.left=k1.right
k1.right=node
node.height=max(self.height(node.right),self.height(node.left))+1
k1.height=max(self.height(k1.left),node.height)+1
return k1
情況4:


def singleRightRotate(self,node):
k1=node.right
node.right=k1.left
k1.left=node
node.height=max(self.height(node.right),self.height(node.left))+1
k1.height=max(self.height(k1.right),node.height)+1
return k1
情況3:


相當於進行了兩次單旋轉。
def doubleRightRotate(self,node):
node.right=self.singleLeftRotate(node.right)
return self.singleRightRotate(node)
情況2:

與情況3類似,都是進行了2次單旋轉。
def doubleLeftRotate(self,node):
node.left=self.singleRightRotate(node.left)
return self.singleLeftRotate(node)
一系列插入操作:

插入代碼如下:
def put(self,key):
if not self.root:
self.root=Node(key)
else:
self.root=self._put(key,self.root)
def _put(self,key,node):
if node is None:
node=Node(key)
elif key<node.key:
node.left=self._put(key,node.left)
if (self.height(node.left)-self.height(node.right))==2:
if key<node.left.key:
node=self.singleLeftRotate(node)
else:
node=self.doubleLeftRotate(node)
elif key>node.key:
node.right=self._put(key,node.right)
if (self.height(node.right)-self.height(node.left))==2:
if key<node.right.key:
node=self.doubleRightRotate(node)
else:
node=self.singleRightRotate(node)
node.height=max(self.height(node.right),self.height(node.left))+1
return node
3.AVL樹的刪除操作:
刪除操作比較復雜,如有錯誤,請指正。
1.當前節點為要刪除的節點且是樹葉(無子樹),直接刪除,當前節點(為None)的平衡不受影響。
2.當前節點為要刪除的節點且只有一個左兒子或右兒子,用左兒子或右兒子代替當前節點,當前節點的平衡不受影響。
3.當前節點為要刪除的節點且有左子樹右子樹:如果右子樹高度較高,則從右子樹選取最小節點,將其值賦予當前節點,然后刪除右子樹的最小節點。如果左子樹高度較高,則從左子樹選取最大節點,將其值賦予當前節點,然后刪除左子樹的最大節點。這樣操作當前節點的平衡不會被破壞。
4.當前節點不是要刪除的節點,則對其左子樹或者右子樹進行遞歸操作。當前節點的平衡條件可能會被破壞,需要進行平衡操作。

如上圖,25為當前節點,左子樹刪除17后平衡條件被破壞,需要根據當前節點(25)的右子樹(30)的左子樹(28)高度是否高於右子樹(35)的高度進行判斷,若高於,進行雙旋轉,否則進行單旋轉
def delete(self,key):
self.root=self.remove(key,self.root)
def remove(self,key,node):
if node is None:
raise KeyError,'Error,key not in tree'
elif key<node.key:
node.left=self.remove(key,node.left)
if (self.height(node.right)-self.height(node.left))==2:
if self.height(node.right.right)>=self.height(node.right.left):
node=self.singleRightRotate(node)
else:
node=self.doubleRightRotate(node)
node.height=max(self.height(node.left),self.height(node.right))+1
elif key>node.key:
node.right=self.remove(key,node.right)
if (self.height(node.left)-self.height(node.right))==2:
if self.height(node.left.left)>=self.height(node.left.right):
node=self.singleLeftRotate(node)
else:
node=self.doubleLeftRotate(node)
node.height=max(self.height(node.left),self.height(node.right))+1
elif node.left and node.right:
if node.left.height<=node.right.height:
minNode=self._findMin(node.right)
node.key=minNode.key
node.right=self.remove(node.key,node.right)
else:
maxNode=self._findMax(node.left)
node.key=maxNode.key
node.left=self.remove(node.key,node.left)
node.height=max(self.height(node.left),self.height(node.right))+1
else:
if node.right:
node=node.right
else:
node=node.left
return node
全部代碼:
class Node(object):
def __init__(self,key):
self.key=key
self.left=None
self.right=None
self.height=0
class AVLTree(object):
def __init__(self):
self.root=None
def find(self,key):
if self.root is None:
return None
else:
return self._find(key,self.root)
def _find(self,key,node):
if node is None:
return None
elif key<node.key:
return self._find(key,self.left)
elif key>node.key:
return self._find(key,self.right)
else:
return node
def findMin(self):
if self.root is None:
return None
else:
return self._findMin(self.root)
def _findMin(self,node):
if node.left:
return self._findMin(node.left)
else:
return node
def findMax(self):
if self.root is None:
return None
else:
return self._findMax(self.root)
def _findMax(self,node):
if node.right:
return self._findMax(node.right)
else:
return node
def height(self,node):
if node is None:
return -1
else:
return node.height
def singleLeftRotate(self,node):
k1=node.left
node.left=k1.right
k1.right=node
node.height=max(self.height(node.right),self.height(node.left))+1
k1.height=max(self.height(k1.left),node.height)+1
return k1
def singleRightRotate(self,node):
k1=node.right
node.right=k1.left
k1.left=node
node.height=max(self.height(node.right),self.height(node.left))+1
k1.height=max(self.height(k1.right),node.height)+1
return k1
def doubleLeftRotate(self,node):
node.left=self.singleRightRotate(node.left)
return self.singleLeftRotate(node)
def doubleRightRotate(self,node):
node.right=self.singleLeftRotate(node.right)
return self.singleRightRotate(node)
def put(self,key):
if not self.root:
self.root=Node(key)
else:
self.root=self._put(key,self.root)
def _put(self,key,node):
if node is None:
node=Node(key)
elif key<node.key:
node.left=self._put(key,node.left)
if (self.height(node.left)-self.height(node.right))==2:
if key<node.left.key:
node=self.singleLeftRotate(node)
else:
node=self.doubleLeftRotate(node)
elif key>node.key:
node.right=self._put(key,node.right)
if (self.height(node.right)-self.height(node.left))==2:
if key<node.right.key:
node=self.doubleRightRotate(node)
else:
node=self.singleRightRotate(node)
node.height=max(self.height(node.right),self.height(node.left))+1
return node
def delete(self,key):
self.root=self.remove(key,self.root)
def remove(self,key,node):
if node is None:
raise KeyError,'Error,key not in tree'
elif key<node.key:
node.left=self.remove(key,node.left)
if (self.height(node.right)-self.height(node.left))==2:
if self.height(node.right.right)>=self.height(node.right.left):
node=self.singleRightRotate(node)
else:
node=self.doubleRightRotate(node)
node.height=max(self.height(node.left),self.height(node.right))+1
elif key>node.key:
node.right=self.remove(key,node.right)
if (self.height(node.left)-self.height(node.right))==2:
if self.height(node.left.left)>=self.height(node.left.right):
node=self.singleLeftRotate(node)
else:
node=self.doubleLeftRotate(node)
node.height=max(self.height(node.left),self.height(node.right))+1
elif node.left and node.right:
if node.left.height<=node.right.height:
minNode=self._findMin(node.right)
node.key=minNode.key
node.right=self.remove(node.key,node.right)
else:
maxNode=self._findMax(node.left)
node.key=maxNode.key
node.left=self.remove(node.key,node.left)
node.height=max(self.height(node.left),self.height(node.right))+1
else:
if node.right:
node=node.right
else:
node=node.left
return node
