【AVL树】双旋转,插入以及删除

AVL树的双旋转

  • (D,F,G,C)代表四棵树,树高用h,h-1表示。
    请添加图片描述
  • 插入的方式有两种:
    请添加图片描述
  • 在E得左子树进行插入:需要先进行左旋转,在进行右旋转。

请添加图片描述

总结:
大于0进行左单旋,小于0进行右单选

平衡因子大于0(1),往左边树插入。

平衡因子小于0(-1),往右边的树插入

  • 代码分析:如图所示
    1.判断B结点的平衡因子大小。(右边高)
    请添加图片描述

左边高 (右旋转)

请添加图片描述

右边高

请添加图片描述

  • 判断结点E得平衡因子的大小。(平衡因子等于-1.说明做高右低,)
    1.将ptr和leftsub的平衡因子分别置为1和0。
    2.进行左单旋转和右单旋转。
    请添加图片描述
void LeftBalance(AVLTree* ptree, AVLNode* ptr)
{
	assert(ptree != nullptr && ptr != nullptr);
	AVLNode* leftsub = ptr->leftchild, * rightsub = nullptr;
	switch (leftsub->balance)
	{
	case 0: cout << "tree left balance " << endl; 
		break;
	case -1:   //左树高,右树低  ,一条斜线
		ptr->balance = 0;
		leftsub->balance = 0;
		RotateRight(ptree, ptr);  //进行右单旋
		break;
	case 1:    //左低右高
		rightsub = leftsub->rightchild;
		switch (rightsub->balance)  //得判断该结点得平衡因子,才知道插入的结点在
		{                                         //左子树还是右子树
		case 0: 
			ptr->balance = 0;         
			leftsub->balance = 0;
			break;
		case 1:                    //左低又高,一条斜线
			ptr->balance = 0;
			leftsub->balance = -1
			break;
		case -1:
			ptr->balance = 1;
			leftsub->balance = 0;
			break;
		}
		rightsub->balance = 0;
		RotateLeft(ptree, leftsub);
		RotateRight(ptree, ptr);
		break;
	}
}

右子树

请添加图片描述
AVL树再平衡后,在插入新的节点后,不需要在进行回溯和调平。
原因:因为插入一个新的结点不会使树的高度加2,只会让树的高度加1.并且平衡因子最大为2,最小为-2.

并且当存在左子树或者右子树,插入新的结点到左子树或者右子树,当前插入节点的parent的高度不会发生变化。

  • 和左平衡是镜像的
void RightBalance(AVLTree* ptree, AVLNode* ptr)
{
	assert(ptree != nullptr && ptr != nullptr);
	AVLNode* rightsub = ptr->rightchild, * leftsub = nullptr;
	switch (rightsub->balance)
	{
	case 0: cout << "avl tree right balance " << endl; break;
	case 1:
		ptr->balance = 0;
		rightsub->balance = 0;
		RotateLeft(ptree, ptr);
		break;
	case -1:
		leftsub = rightsub->leftchild;
		switch (leftsub->balance)
		{
		case 0:
			ptr->balance = 0;
			rightsub->balance = 0;
			break;
		case 1:
			ptr->balance = -1;
			rightsub->balance = 0;
			break;
		case -1:
			ptr->balance = 0;
			rightsub->balance = 1;
			break;
		}
		leftsub->balance = 0;
		RotateRight(ptree, rightsub);
		RotateLeft(ptree, ptr);
		break;
	}
}
void Adjust_Insert_Item(AVLTree* ptree, AVLNode* ptr)
{
	assert(ptree != nullptr && ptr != nullptr);
	bool taller = true;  //树的高度,树的高度可能不变
	AVLNode* pa = ptr->parent;
	while (pa != nullptr && taller)
	{
	         //左子树插入
		if (pa->leftchild == ptr)   
		{
			switch (pa->balance)
			{
			case 0: pa->balance = -1; break; //插入后parent为-1
			case 1: pa->balance = 0;         //parent为1,插入变为0
				taller = false;               //高度不变
				break;
			case -1:                        //插入后,需要调平
				LeftBalance(ptree, pa);
				taller = false;
				break;
			}
		}
		
		else    //右子树插入
		{	// ptr pa->rightchild
			switch (pa->balance)
			{
			case 0: pa->balance = 1; break;
			case -1: pa->balance = 0;
				taller = false;
				break;
			case 1:
				RightBalance(ptree, pa);
				taller = false;
				break;
			}
		}
		ptr = pa;
		pa = ptr->parent;
	}
}
bool Insert_Item(AVLTree* ptree, const KeyType kx)
{
	assert(ptree != nullptr);
	AVLNode* ptr = ptree->root, * pa = nullptr;
	while (ptr != nullptr && ptr->key != kx)
	{
		pa = ptr;
		ptr = kx > ptr->key ? ptr->rightchild : ptr->leftchild;
	}
	if (ptr != nullptr && ptr->key == kx) return false;

	ptr = Buynode();
	ptr->key = kx;
	ptr->parent = pa; //
	if (pa != nullptr)
	{
		if (ptr->key > pa->key)
		{
			pa->rightchild = ptr;
		}
		else
		{
			pa->leftchild = ptr;
		}
	}
	else
	{
		ptree->root = ptr;
	}
	Adjust_Insert_Item(ptree, ptr);//最后对整个树调平
	ptree->cursize += 1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值