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)
复制代码