二叉查找树(BST)
特点:比父节点小的key都出现在左子树,比父节点大的key都出现在右子树。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczX0xiRGZkRGZ0Xy9GbvNGL2EzXlpXazxSPRRkT1EEVNdXVq1kMVRVT14kMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzkTO5QDNyETMwMjNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
二叉查找树的python实现
class BinarySearchTree(object):
def __init__(self, key): ##初始化
self.key = key
self.left = None
self.right = None
def find(self, x):
if x == self.key:
return True
elif x < self.key and self.left: # 如果x小,则去左子树找
return self.left.find(x)
elif x > self.key and self.right: # 如果x大,则去右子树找
return self.right.find(x)
else:
return None # 找不到返回None
def findMin(self):
if self.left: # 如果左节点存在,最小值一定在左节点的最深处
return self.left.findMin()
else:
return self.key # 如果左节点没有,那么根节点最小
def findMax(self):
if self.right: # 如果右节点存在,最大值一定在右节点的最深处
return self.right.findMax()
else:
return self.key # 如果右节点没有,那么根节点最大
def insert(self, x):
if self.find(x): # 如果找到了该节点,则什么也不做
return None
else: # 如果没有找到则开始插入
if x < self.key: # 如果插入值小,则插入左子树
if self.left: # 先判断左子树是否存在
return self.left.insert(x)
else:
newTree = BinarySearchTree(x)
self.left = newTree # 如果左子树不存在,则把该节点设为左子树
elif x > self.key: # 如果插入值大,则插入右子树
if self.right:
return self.right.insert(x)
else:
newTree = BinarySearchTree(x)
self.right = newTree
def delete(self, x):
if self.find(x): # 首先判断该节点是否存在
if x < self.key: # 如果要删的数据比该数据self.key小,从左子树删起
self.left = self.left.delete(x)
return self
elif x > self.key: # 如果要删的数据比self.key大,从右子树删起
self.right = self.right.delete(x)
return self
else: # 如果就是该数据,判断他是否有左右子树
if self.left and self.right: # 如果左右子树都存在
minkey = self.right.findMin().key # 把右子树中最小的点连接原来x的父节点, 并且右子树中删除该点
self.key = minkey
self.right = self.right.delete(minkey)
return self
else: # 如果左右节点不全存在
if self.left:
return self.left
else:
return self.right
else:
return self
bst = BinarySearchTree(17)
node_list = [17, 5, 29, 38, 35, 2, 9, 8, 16, 11]
for l in node_list:
bst.insert(l)
print(bst.findMax())
print(bst.findMin())
print(bst.find(10))
print(bst.delete(11))
算法分析:
(1)二叉查找树的性能决定因素在于二叉搜索树的高度(最大层次),而高度又受数据项key插入顺序的影响。
(2)若key的列表是随机分布的话,那么两侧的键值大致相等
(3)BST的高度就是log2 n,n是节点的个数,而且该树是平衡树
平衡二叉查找树(AVL树)
特点:能够在key插入是一直保持平衡的二叉查找树。
在AVL实现中,需要对每个节点跟踪“平衡因子”参数,其定义为左右子树的高度差。AVL树的平衡因子都在-1,0,1之间,
AVL树的python实现
1.AVL树的实现,遍历与查找操作与二叉查找树相同。
见上面
2.AVL树的插入操作
插入一个节点可能会破坏AVL树的平衡,可以通过旋转操作来进行修正。插入一个节点后,只有从插入节点到根节点的路径上的节点的平衡可能被改变。
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
算法分析:经过复杂的put方法,AVL树始终能维持平衡,get也始终保持O(log n)的高性能。
AVL树的put方法的时间复杂度还是O((log n)