AVL树的操作

概念与特性

AVL树是期每个节点的左子树和右子树的高度最多相差1的二叉查找树

对于一颗高度为h的AVL树而言,最少节点数 S ( h ) S(h) S(h)= S ( h − 1 ) S(h-1) S(h1)+ S ( h − 2 ) S(h-2) S(h2)+1。对于h=0, S ( h ) = 1 S(h)=1 S(h)=1;对于h=1, S ( h ) = 2 S(h)=2 S(h)=2

基本操作

对于AVL树而言,插入一个节点,可能会破坏AVL树的特性。如果发生了这种情况,为了保证其特性,我们需要对其进行一些修正操作。我们将这个操作称之为旋转(rotation)。

我们把需要平衡的结点称之为a,这种不平衡,有以下四种情况:
1.对a的左儿子的左子树进行了一次插入操作;
2.对a的左儿子的右子树进行了一次插入操作;
3.对a的右儿子的右子树进行了一次插入操作;
4.对a的右儿子的左子树进行了一次插入操作;

对于左-左或者右-右情形,我们可以采用单旋转进行调整,对于左-右或者右-左情形,我们需要采用双旋转进行调整。

单旋转

AVLtree* SingerotateWihtleft(AVLtree* T) {
	AVLtree* T1;
	T1 = T->lchild;
	T->lchild = T1->rchild;
	T1->rchild = T;
	T->height = max(returnHeight(T->lchild), returnHeight(T->rchild)) + 1;
	T1->height = max(returnHeight(T1->lchild), T->height) + 1;
	return T1;
}


AVLtree* SingerotateWihtright(AVLtree* T) {
	AVLtree* T1;
	T1 = T->rchild;
	T->rchild = T1->lchild;
	T1->lchild = T;
	T->height = max(returnHeight(T->lchild), returnHeight(T->rchild)) + 1;
	T1->height = max(returnHeight(T1->rchild), T->height) + 1;
	return T1;
}

双旋转

AVLtree* DoublerotateWihtleft(AVLtree* T) {
	T->lchild = SingerotateWihtright(T->lchild);
	return SingerotateWihtleft(T);
}

AVLtree* DoublerotateWihtright(AVLtree* T) {
	T->rchild = SingerotateWihtleft(T->rchild);
	return SingerotateWihtright(T);
}

有了以上单旋转和双旋转的调整操作后,我们就可以写出AVL树的插入操作了

插入操作

AVLtree* insertNode(AVLtree* T,int x) {
	if (T == NULL) {
		T = new AVLtree;
		if (T == NULL) exit(1);
		else {
			T->data = x; T->height = 0;
			T->lchild = NULL; T->rchild = NULL;
		}
	}
	else if (x < T->data) {
		T->lchild = insertNode(T->lchild, x);
		if (returnHeight(T->lchild) - returnHeight(T->rchild) == 2) {
			if (x < T->lchild->data)
				T = SingerotateWihtleft(T);
			else
				T = DoublerotateWihtleft(T);
		}
	}
	else if (x > T->data) {
		T->rchild = insertNode(T->rchild, x);
		if (returnHeight(T->rchild) - returnHeight(T->lchild) == 2) {
			if (x > T->rchild->data)
				T = SingerotateWihtright(T);
			else
				T = DoublerotateWihtright(T);
		}
	}
	return T;
}

删除操作

与普通二叉查找树几乎一样,不过要多一个更新操作,以免破坏树的平衡。


AVLtree* DeleteNode(AVLtree* T, int num) {
	AVLtree* temp = NULL;
	if (T == NULL) cout << "NO data" << endl;
	else if (num < T->data)
		T->lchild = DeleteNode(T->lchild, num);
	else if (num > T->data)
		T->rchild = DeleteNode(T->rchild, num);
	else if (T->lchild && T->rchild) {
		temp = FindMin(T);
		T->data = temp->data;
		T = DeleteNode(T->rchild, T->data);
	}
	else {
		temp = T;
		if (T->lchild == NULL)
			T = T->rchild;
		else if (T->rchild == NULL)
			T = T->lchild;
		free(temp);
	}
	if (T) {
		int lheight = returnHeight(T->lchild), rheight = returnHeight(T->rchild);
		T->height = (lheight > rheight ? lheight : rheight)+1;
		if (lheight - rheight == 2) {
			if (returnHeight(T->lchild->lchild) >= returnHeight(T->lchild->rchild))
				T = SingerotateWihtleft(T);
			else
				T = DoublerotateWihtleft(T);
		}
		else if (rheight - lheight == 2) {
			if (returnHeight(T->rchild->rchild) >= returnHeight(T->rchild->lchild))
				T = SingerotateWihtright(T);
			else
				T = DoublerotateWihtright(T);
		}
	}
	return T;
}

其他的操作,诸如,查找,寻找最小值,寻找最大值,输出等均与二叉查找树相同。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值