二叉搜索树和AVL树基本概念

什么是二叉搜索树

二叉搜索树也叫二叉排序树或二叉查找树

二叉搜索树,一棵二叉树可以为空也可以不空,如果不为空就满足以下性质:

  • 非空左子树的所有键值小于根结点的键值
  • 非空右子树的所有键值大于根结点的键值
  • 左、右子树都是二叉搜索树

二叉搜索树操作的特别函数

Position Find(ElementType X,BinTree BST)
/*从二叉搜索树BST中查找元素X,返回其所在结点的地址*/

Position FindMin(BinTree BST)
/*从二叉搜索树BST中查找并返回最小元素所在结点的地址*/

Position FindMax(BinTree BST)
/*从二叉搜索树BST中查找并返回最大元素所在结点的地址*/

查找操作

从根节点开始,如果树为空,返回NULL
若搜索树非空,则根节点关键字与X进行比较,并进行不同处理

  • 若X小于根结点键值,只需在左子树中继续搜索
  • 若X大于根结点键值,在右子树中进行继续搜索
  • 若两者比较结果相等搜索完成,返回指向此结点的指针
Poosition Find(ElementType X,BinTree BST)
{
	if(!BST) return NULL;/*查找失败*/
	if(x > BST->Data)/*如果大于根结点键值*/
	{
		return Find(X,BST->Right);/*在右子树中继续查找*/
	}
	else if(X < BST->Data)/*如果小于根结点键值*/
	{
		return Find(X,BST->Left);/*在左子树中继续查找*/
	}
	else/*找到了*/
	{
		returnn BST;/*返回结点所在地址*/
	}
}

以上是尾递归效并不高,因此可将其换成非递归函数,即换为迭代函数

Position IterFind(ElementType X,BinTree BST)
{
	while(BST)/*如果树不为空*/
	{
		if(X > BST->Data)/*如果大于根结点键值*/
		{	
			BST = BST->Right;/*向右子树移动继续查找*/
		}
		else if(X <BST->Data)/*如果大于根结点键值*/
		{
			BST = BST->Left;/*向左子树移动继续查找*/
		}
		else
		{
			return BST;/*查找成功,返回结点的地址*/
		}
	return NULL;/*查找失败*/
}

查找效率决定于树的高度

查找最大和最小元素

  • 最大元素一定在树的最右分枝的端结点上
  • 最小元素一定在树的最左分枝的端结点上
    查找最小元素的递归函数
Position FindMin(BinTree BST)
{
	if(!BST) return NULL;/*空的二叉搜索树,返回NULL*/
	else if(!BESt->Left)
	{
		return BST;/*找到最左叶结点并返回*/
	}
	else
	{
		return FindMin(BST->Left);
	}
}

查找最大元素的迭代函数

Position FindMax(BinTree BSST)
{
	if(BST)
	{
		while(BST->Right)
		{
			BST = BSt->Right;
		}
	}
	return BST;
}

二叉搜索树的插入

关键是要找到元素应该插入的位置,即插入后还是一个二叉搜索树
可以采用与Find类似的方法
不过与Find不同的是,由于需要插入元素,所以当找到可以插入的位置时,这个位置一定是空的,所以要重新申请一个空间插入并返回插入的地址。返回上一层时将插入的地址赋值给上一层的Left 或 Right;

 BinTree Insert(ElementType X,BinTree BST)
 {
 	if(!BST)/*若原树为空生成 并返回一个结点的二叉搜索树*/
 	{
 		BST= malloc(sizeof(struct TreeNode));
 		BST->Data = X;
 		BST->Left = BSt->Right = NULL;
 	}
 	else
 	{
 		if(X < BST->Data)
 		{	
 			BST->Left = Insert(X,BST->Left);/*递归插入左子树*/
 		}
 		else if(x > BST->Data)
 		{
 			BST->Right = Insert(X,BST->Right)/*递归插入右子树*/
 		}
 	return BST;
}

二叉搜索树的删除

  • 要删除的是叶结点:直接删除,并修改父结点Left or Right指针置为NULL
  • 要删除的结点为只有一个孩子的结点,将该结点的父结点的指针指向要删除的结点的孩子,即爷爷结点指向孙子结点
  • 要删除的结点有左右两棵子树:用另一个结点替代被删除结点:右子树的最小元素或者左子树的最大元素(因为左子树的最大元素一定在左子树的最右边右子树的最小元素一定在右子树的最左边
BinTree Delete(ElementType X,BinTree BST)
{
	Position Tmp;
	if(!BST) printf("要删除的元素未找到");/*树为空*/
	else if(x < BST->Data)
		BST->Left = Delete(X,BST->Left);/*左子树递归删除*/
	else if(X > BST->Data)
		BST->Right = Delete(X,BST->Right);/*右子树递归删除*/
	else/*找到要删除的结点*/
	{
		if(BST->Left && BST->Right)/*被删除的结点有左右两个孩子*/
		{
			Tmp = FindMin(BST->Right);/*在右子树中找到最小元素填充删除结点*/
			BST->Data = Tmp->Data;
			BST->Riht = Delete(BST->Data,BSt->Right);/*在删除结点的右子树中删除最小元素*/
		}
		else/*被删除的结点有一个孩子或没有孩子*/
		{
			Tmp = BST;
			if(!BST->Left)/*有右孩子或无子结点*/
			{
				BST = BST->Right;
			}
			else if(!BST->Right)
			{
				BST = BST->Left;
			}
			free(Tmp);
		}
	}	
	return BST;
}

什么是平衡二叉树(AVL)

搜索树结点不同插入次序将导致不同的深度和平均查找长度ASL,导致查找效率不同
比如:
ab在这里插入图片描述c
很明显b图的平均查找次数最低,查找的效率也就最高而c图查找效率最低,因为b图更平衡
那么如何来衡量一棵树是否为平衡二叉树呢?

平衡因子(Balance Factor,BF):BF = hl - hr,hl和hr分别为T的左右子树的高度
平衡二叉树(Balanced Binary Tree)(AVL树)空树,或者任一结点左右子树高度差的绝对值不超过1,即|BF(T)| <= 1
wrongright
平衡二叉树的高度能达到log2n吗?
设n高度为h的平衡二叉树的结点数,
0h1h = 1时,结点最少是2个,可以两子结点
h2h = 2时结点最少是4,拿掉任何一个都不平衡且可能不是2层
Nh = Nh-1 + Nh-2 + 1很像
斐波那契

平衡二叉树的调整

按照平衡二叉树插入月份

RR旋转

根据平衡因子来度量是否平衡,如果插入Mar,May,Nov就不平衡了
不平衡的发现者是Mar,麻烦结点Nov在发现者右子树的右边,就叫做RR插入,需要RR旋转(右单旋)
如下图:
首先原本是平衡的,但是RR插入插入了一个结点使得树不平衡,因此需要RR旋转

在这里插入图片描述A是发现者,BR下方插入的结点为破坏者,因此需要RR旋转,将B拎上来。
在这里插入图片描述由于A右边的一定是大于A的,BL一定是小于B的因此将BL插到A的右边在这里插入图片描述这棵树原本是平衡的,插入15后变得不平衡,且是插在右子树的右子树上因此为RR插入,需要RR旋转,5为发现者,15为破坏者,就把10拎上去形成平衡二叉树
RR
13也是破坏者也是插在右子树的右子树上,也是将10拎上去
在这里插入图片描述

LL旋转

现在在平衡状态,我们要插入四月Apr
在这里插入图片描述在这里插入图片描述现在平衡再次被破坏,此时被破坏的是Mar,而这次是插入在左子树的左边上因此需要LL旋转在这里插入图片描述发现者是Mar,麻烦结点Apr在发现者左子树的左边因而叫LL插入,需要LL旋转
如下图:开始时这棵树是平衡的,后来插入了一个结点在左子树的左边在这里插入图片描述经过左左旋转变平衡在这里插入图片描述由于A的左子树一定是小于A的,B的右儿子也一定是大于B的因此将BR插入到A的右边在这里插入图片描述

LR旋转

开始时树是平衡的
在这里插入图片描述插入Jan后破坏了平衡且是May的左子树的右子树上
在这里插入图片描述
这种插入叫做LR插入因此需要LR旋转在这里插入图片描述重点关注这三个结点,其中Mar大于Aug小于May因此将Mar拎上去将Aug作为其左儿子,May作为其右儿子在这里插入图片描述发现者是May,麻烦结点是Jan在左子树的右边,所以交LR插入,需要LR旋转
如下图:在这里插入图片描述
通过LR插入使得树不平衡,因此我们需要LR旋转,将ABC调成CBA在这里插入图片描述

RL旋转

开始时树是平衡的在这里插入图片描述当Feb插入后就不平衡了,且是在右子树的左子树上在这里插入图片描述
因此我们需要RL旋转,将在这里插入图片描述
如下图在这里插入图片描述
需要将ABC调整为CBA在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值