平衡二叉树

原理:每当构建一个二叉树时,先检查插入是否破坏了平衡性。若是,则找出最小不平衡子树,进行对应的操作。

//树结构定义
typedef struct BiTnode {
	int data;
	int bf;
	struct BiTnode* lchild, * rchild;
}BiTnode, *BiTree;

左旋即将最小不平衡子树的根节点变为其右孩子的左子树。原右孩子的左子树变为原根节点的右子树。

//左旋操作
void L_Rotate(BiTree* P) {
	BiTree R;
	R = (*P)->rchild;
	(*P)->rchild = R->lchild;
	R->lchild = (*P);
	*P = R;
}

右旋即将最小平衡子树的根节点变为其左孩子的右子树。原左孩子的右子树变为原根节点的左子树。

//右旋操作
void R_Rotate(BiTree* P) {
	BiTree L;
	L = (*P)->lchild;
	(*P)->lchild = L->rchild;
	L->rchild = (*P);
	*P = L;
}

左平衡操作:对于较复杂情况,例如:即最小子树的根节点的平衡因子bf 为+2但其左孩子的平衡因子为-1。此时我们需要先将左孩子调整为与根节点同号即先对左孩子的右子树进行左旋,再对原根节点的子树进行右旋。同时要修改对应情况下新的平衡因子。

#define LH +1
#define EH 0
#define RH -1

void LeftBalance(BiTree* T) {
    // L为T的左孩子,Lr为L的右孩子
	BiTree L, Lr;
	L = (*T)->lchild;
	//L的平衡因子bf为+1导致T不平衡时
	//调整平衡因子
	//右旋即可
	if (L->bf == LH) {
		(*T)->bf = L->bf = EH;
		R_Rotate(T);
	}
	//L的bf为-1时需要分情况讨论
	else if (L->bf == RH) {
		Lr = L->rchild;
		//L的右孩子也为-1时,在经过调整后T的平衡因子最终为0
		//L的bf最终为+1
		if (Lr->bf == RH) {
			(*T)->bf = EH;
			L->bf = LH;
		}
		//同理,建议自己推一下调整后的情况
		else if (Lr->bf == EH) {
			(*T)->bf = L->bf = EH;
		}
		else if (Lr->bf == LH) {
			(*T)->bf = RH;
			L->bf = EH;
		}
		Lr->bf = EH;
		L_Rotate(&(*T)->lchild);
		R_Rotate(T);
	}
}

右平衡操作同理。
AVL的插入操作:

bool InsertAVL(BiTree* T, int e, bool* taller) {
	if (! *T) {
		*T = (BiTree)malloc(sizeof(BiTnode));
		(*T)->data = e;
		(*T)->lchild = (*T)->rchild = nullptr;
		(*T)->bf = EH;
		*taller = true;
	}
	else {
	    //若插入数值已有
		if (e == (*T)->data) {
			*taller = false;
			return false;
		}
		if (e < (*T)->data) {
		     //若插入数值小于根节点的数值,在左子树寻找
		    //若最终插入不成功
			if (!InsertAVL(&(*T)->lchild, e, taller))
				return false;
		    //若树最终增高
			if (*taller) {
				switch ((*T)->bf) {
				//若插入前左边高
				case LH:
					LeftBalance(T);
					//调整后树未增高
					taller = false;
					break;
			    //插入前为相等
			    //树增高
				case EH:
					(*T)->bf = LH;
					*taller = true;
					break;
			    //插入前右边高
			    //插入完两边相等
			    //树未增高
				case RH:
					(*T)->bf = EH;
					*taller = false;
					break;
				}
			}
		}
		else {
			if (!InsertAVL(&(*T)->rchild, e, taller))
				return false;
			if (*taller) {
				switch ((*T)->bf) {
				case LH:
					(*T)->bf = EH;
					taller = false;
					break;
				case EH:
					(*T)->bf = RH;
					*taller = true;
					break;
				case RH:
					RightBalance(T);
					*taller = false;
					break;
				}
			}
		}
	}
	return true;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值