Python之平衡二叉搜索树(AVL树)

平衡二叉搜索树(Balanced Binary Tree):
是一种结构平衡的二叉搜索树,即叶节点高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。它能在O(log n)内完成插入、查找和删除操作,最早被发明的平衡二叉搜索树为AVL树。

常见的平衡二叉搜索树有:AVL树、红黑树、Treap、节点大小平衡树。

注意:移动树的节点时,被移动节点及其原新两个位置的父、子节点的指向均需重新指向,保证各节点指向正确。

平衡二叉搜索树(AVL树),可以自动进行调整,以确保树时时保持平衡。

平衡因子(balance factor):为实现AVL树,需要在树的每个节点加入一个平衡因子(balance factor)以跟踪其变化情况。

一个节点的平衡因子为其左子树的高度和右子树的高度之差,即balanceFactor=height(leftSubTree)−height(rightSubTree)。
如果平衡因子大于零,则子树左重(left-heavy)。如果平衡因子小于零,则子树右重(right-heavy)。如果平衡因子是零,那么树完美平衡。

为实现AVL树,定义平衡因子为-1、0或1时这个树是平衡的,一旦树的节点的平衡因子超出了这个范围,则需要将树恢复平衡。

此例与BST二叉查找树的代码区别:
1、TreeNode类中,__init__多了balanceFactor属性;
2、BinarySearchTree类中,_put()中多了2行更新平衡因子的代码;
3、BinarySearchTree类中,多了updateBalance()、rotateLeft()、rotateRight()、rebalance()四个函数;
4、此例中删除节点时的平衡未实现。

示例:

# 创建树的节点类
class TreeNode(object):
	# 初始化树的节点
	def __init__(self, key, val, left=None, right=None, parent=None, balanceFactor=0):
		self.key = key 									#节点值,节点位置,索引
		self.payload = val 								#有效载荷,节点显示的值
		self.leftChild = left 							#左子节点
		self.rightChild = right 						#右子节点
		self.parent = parent 							#父节点
		self.balanceFactor = balanceFactor				#节点的平衡因子

	# 判断是否有左子节点,若有则返回左子节点
	def hasLeftChild(self):
		return self.leftChild

	# 判断是否有右子节点,若有则返回右子节点
	def hasRightChild(self):
		return self.rightChild

	# 判断是否是左子节点(父节点存在,并且self与self父节点的左子节点相同)
	def isLeftChild(self):
		# 下面的含义是(self.parent is not None) and (self.parent.leftChild == self)
		return self.parent and self.parent.leftChild == self

	# 判断是否是右子节点
	def isRightChild(self):
		return self.parent and self.parent.rightChild == self

	# 判断是否是根节点
	def isRoot(self):
		return not self.parent	 						#没有父节点

	# 判断是否是叶节点
	def isLeaf(self):
		return not (self.rightChild or self.leftChild)	#没有左右子节点

	# 判断是否有子节点
	def hasAnyChildren(self):
		return self.rightChild or self.leftChild 		#有左或右子节点

	# 判断是否有2个子节点
	def hasBothChildren(self):
		return self.rightChild and self.leftChild 		#有左右2个子节点

	# 替换节点数据
	def replaceNodeData(self, key, value, lc, rc):
		self.key = key 									#更新节点值
		self.payload = value 							#更新有效载荷
		self.leftChild = lc 							#更新左子节点
		self.rightChild = rc 							#更新右子节点
		if self.hasLeftChild():							#若有左子节点
			self.leftChild.parent = self 				#将该节点的左子节点的父节点指向self
		if self.hasRightChild():						#若有右子节点
			self.rightChild.parent = self 				#将该节点的右子节点的父节点指向self

	# 中序遍历
	# 只要用了yield语句,普通函数就是生成器,也是迭代器,在定义过程中不需要像迭代器那样写__iter__()和__next__()方法。yield语句的作用就是在调用的时候返回相应的值和作为生成器的标志。
	def __iter__(self):
		if self:										#若当前节点存在,则
			if self.hasLeftChild():						#若当前节点有左子节点,则
				for elem in self.leftChild:				#循环输出当前节点的左子树的节点值
					yield elem 							#在for循环中,每次执行到yield时,就返回一个迭代值,且不会终止循环;下个循环时,代码从yield返回值的下一行继续返回
			yield self.key 								#返回当前节点值
			if self.hasRightChild():					#若当前节点有右子节点,则
				for elem in self.rightChild:			#循环输出当前节点的右子树的节点值
					yield elem 				

	# 将被删除节点的继任者拼接到被删除的节点位置
	def spliceOut(self):
		if self.isLeaf():								#若被删除节点是叶节点,则无
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值