C语言 数据结构与算法---AVL-平衡二叉树

一. 平衡二叉树的概念

1.为什么需要平衡二叉树

在这里插入图片描述
为了避免这种情况发生,提高效率

性质:

  • 一颗平衡二叉树或者空树,或者具有下列性质的二叉排序树
    • 左子树与右子树的高度差的绝对值小于或等于1
    • 左子树与右子树也是平衡二叉排序树

2.平衡因子

BF = 左右子树高度差 = 左子树的深度-右子树深度
(BF = -1,0,1)

平衡二叉树,也被称为高度平衡树。相比于”二叉查找树”,它的特点是:AVL树中任何节点的两个子树的高度最大差别为1。
在这里插入图片描述
在这里插入图片描述

二. 平衡二叉树的分析与调整

1.分析

当我们在一个平衡二叉排序树上插入一个结点时,有可能导致失衡,即出现平衡因子绝对值大于一的结点
在这里插入图片描述

2.平衡调整的四种类型

在这里插入图片描述
在这里插入图片描述
原则:

  • 降低高度
  • 保持二叉排序树的性质

1. LL型

在这里插入图片描述

  • B结点带左子树一起上升
  • A结点成为B的右孩子
  • 原来B结点的右子树作为A的左子树

在这里插入图片描述

2. RR型

在这里插入图片描述

  • B结点带右子树一起上升
  • A结点成为B的左孩子
  • 原来B结点的左子树作为A的右子树

在这里插入图片描述
图例:
在这里插入图片描述
调整后:
在这里插入图片描述

3. LR型

在这里插入图片描述

  • C结点穿过A、B结点上升
  • B结点成为C的左孩子
    A结点成为C的右孩子
  • 原来C结点的子树作为B的子树
    原来C结点的子树作为A的子树

C原来的左子树变成上升后的左子树的右子树;原来的右子树变成上升后的右子树的左子树
在这里插入图片描述

4. RL型

在这里插入图片描述
图例:
在这里插入图片描述
调整后:
在这里插入图片描述
9原来的左子树变成了上升后的左子树的右子树

三. 平衡二叉树的实现

1. 平衡二叉树的结构

与二叉树大致相同,多了节点的高度

typedef struct BinNode
{
	int data;
    int height;  //当前节点的高度
	struct BinNode* lchild;
	struct BinNode* rchild;
}BinNode, * BinTree;

2. 平衡二叉树的调整

前置函数:

//获取当前节点的高度
int GetHeight(BinTree tree){
    if(tree == NULL) 
	{
		return 0;
	}
    return tree->height;
}

//判断是否平衡 
bool IsBalanced(BinTree tree)         
{
    int BF = GetHeight(tree->lchild) - GetHeight(tree->rchild);
    return abs(BF) < 2;
}

int max(int a,int b)
{
	return a > b ? a : b;
}

RR型:

BinTree Rotate_RR(BinTree tree)
{
    BinTree temp = tree->rchild;
    tree->rchild = temp->lchild;
    temp->lchild = tree;
 
    //更新高度,先更新node再更新temp。
    tree->height = max(GetHeight(tree->lchild),GetHeight(tree->rchild))+1;
    temp->height = max(GetHeight(temp->lchild),GetHeight(temp->rchild))+1;
 
    return temp;
}

LL型:

BinTree Rotate_LL(BinTree tree)
{
    BinTree temp = tree->lchild;
    tree->lchild = temp->rchild;
    temp->rchild = tree;
 
    //更新高度,先更新node再更新temp。
    tree->height = max(GetHeight(tree->lchild),GetHeight(tree->rchild))+1;
    temp->height = max(GetHeight(temp->lchild),GetHeight(temp->rchild))+1;
 
    return temp;
}

LR型:

BinTree Rotate_LR(BinTree tree)
{
    BinTree temp = tree->lchild;
    tree->lchild = Rotate_RR(temp);
    return Rotate_LL(tree);
}

RL型:

BinTree Rotate_RL(BinTree tree)
{
    BinTree temp = tree->rchild;
    tree->rchild = Rotate_LL(temp);
    return Rotate_RR(tree);
}

3. 平衡二叉树的插入

BinTree Insert(BinTree T, char X)//将X插入到AVL树中,并且返回调整后的AVL树
{
	if (!T)  //若插入空树,则新建包含一个结点的树
	{
		T = (BinTree)malloc(sizeof(BinNode));
		T->data = X;
		T->height = 0;
		T->lchild = T->rchild = NULL;
	}
	else if (X<T->data)    //插入T的左子树 
	{
		T->lchild = Insert(T->lchild, X);
		if (GetHeight(T->lchild) - GetHeight(T->rchild) == 2)  //如果需要右旋
		{
			if (X<T->lchild->data)
			{
				T = Rotate_LL(T); //右单旋
			}
			else
			{
 				T = Rotate_LR(T);//左右双旋
 			}
		}
	}
	else if (X>T->data)    //插入T的左子树 
	{
		T->rchild = Insert(T->rchild, X);
		if (GetHeight(T->rchild) - GetHeight(T->lchild) == 2)//如果需要左旋
		{
			if (X>T->rchild->Data)
			{
				T = Rotate_RR(T);//左单旋
			}
			else
			{
				T = Rotate_RL(T);//左右双旋
			}
		}
	}
	T->height = max(GetHeight(T->lchild), GetHeight(T->rchild)) + 1;//更新树高
 
	return T;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值