数据结构---二叉平衡排序树的删除

数据结构—二叉平衡排序树的删除

原理:参考趣学数据结构

代码:

#include<stdio.h>
#include<stdlib.h>
typedef struct avlTree {
	int data;
	struct avlTree *lchild, *rchild;
	int height;
}avlTree;

int height(avlTree* AVLTree);//声明avl树的深度
void updateHeight(avlTree* &AVLTree);//声明更新avl树每个结点的高度

avlTree* LL(avlTree* &AVLTree) {//单向右旋
	avlTree* temp = AVLTree->lchild;
	AVLTree->lchild = temp->rchild;
	temp->rchild = AVLTree;
	updateHeight(temp);//更新avl树的高度
	updateHeight(AVLTree);
	return temp;
}
avlTree* RR(avlTree* &AVLTree) {//单向左旋
	avlTree* temp = AVLTree->rchild;
	AVLTree->rchild=temp->lchild;
	temp->lchild = AVLTree;
	updateHeight(temp);//更新avl树的高度
	updateHeight(AVLTree);//调整顺序的两个节点都要更新高度
	return temp;
}
avlTree* LR(avlTree* &AVLTree) {//先右后左双向旋转
	AVLTree->lchild=RR(AVLTree->lchild);
	return LL(AVLTree);
}
avlTree* RL(avlTree* &AVLTree) {//先左后右双向旋转
	AVLTree->rchild = LL(AVLTree->rchild);
	return RR(AVLTree);
}
int height(avlTree* AVLTree) {//计算树的高度
	int m, n;
	if (!AVLTree) {
		return 0;
	}
	else {
		m = height(AVLTree->lchild);//左子树深度
		n = height(AVLTree->rchild);//右子树深度
		if (m > n) {
			return m + 1;
		}
		else {
			return n + 1;
		}
	}
}
void updateHeight(avlTree* &AVLTree) {//更新每个结点的高度值
	if (AVLTree) {
		AVLTree->height = height(AVLTree);
		updateHeight(AVLTree->lchild);
		updateHeight(AVLTree->rchild);
	}
}
avlTree* insertAVLTree(avlTree* &AVLTree,int e) {//插入一个结点
	if (!AVLTree) {//如果为空树,生成一个新的结点
		AVLTree = (avlTree*)malloc(sizeof(avlTree));
		AVLTree->data = e;
		AVLTree->lchild = AVLTree->rchild = NULL;//不能写成二个都是左指针
		AVLTree->height = 1;
		return AVLTree;
	}
	else {
		//查找元素要插入的位置
		if (AVLTree->data == e) {
			printf("已经存在元素%d,不需要插入\n", e);
			return AVLTree;//结束
		}
		if (e < AVLTree->data) {
			AVLTree->lchild = insertAVLTree(AVLTree->lchild, e);//插入左边
			if (height(AVLTree->lchild) - height(AVLTree->rchild) == 2) {
				if (e > AVLTree->lchild->data) {
					AVLTree =LR(AVLTree);//一定要有返回值覆盖
				}
				else {
					AVLTree =LL(AVLTree);
				}
			}
		}
		else {
			AVLTree->rchild = insertAVLTree(AVLTree->rchild, e);//插入右边
			if (height(AVLTree->rchild) - height(AVLTree->lchild) == 2) {
				if (AVLTree->rchild->data > e) {
					AVLTree =RL(AVLTree);
				}
				else {
					AVLTree =RR(AVLTree);
				}
			}
		}
	}
	updateHeight(AVLTree);//更新AVL每个结点的高度
	return AVLTree;
}
avlTree * adjustAVLTree(avlTree * &AVLTree) {//调整删除结点后的树
	if (!AVLTree) {
		return NULL;
	}
	if (height(AVLTree->lchild) - height(AVLTree->rchild) == 2) {
		if (height(AVLTree->lchild->lchild) >= height(AVLTree->lchild->rchild)) {
			AVLTree = LL(AVLTree);//单向右旋
		}
		else {
			AVLTree = LR(AVLTree);//先左后右双向旋转
		}
	}
	else if (height(AVLTree->rchild) - height(AVLTree->lchild) == 2) {
		if (height(AVLTree->rchild->rchild) >= height(AVLTree->rchild->lchild)) {
			AVLTree = RR(AVLTree);//单向左旋
		}
		else {
			AVLTree = RL(AVLTree);//先右后左双向旋转
		}
	}
	updateHeight(AVLTree);//更新avl树中每个结点的高度
	return AVLTree;
}
avlTree * deleteElemAVL(avlTree * &AVLTree,int data) {//删除avl的元素
	if (AVLTree == NULL) {
		return AVLTree;
	}
	if (AVLTree->data == data) {//查找到了该元素
		if (!AVLTree->rchild) {//如果右子树为空
			avlTree* temp = AVLTree;
			AVLTree = AVLTree->lchild;
			delete temp;
		}
		else {//右子树不为空
			avlTree* p = AVLTree->rchild;
			while (p->rchild) {
				p = p->lchild;
			}
			AVLTree->data = p->data;//右孩子的右孩子,一直下去
			AVLTree->rchild = deleteElemAVL(AVLTree->rchild, AVLTree->data);
			updateHeight(AVLTree);//更新avl树中每个结点的高度
		}
		return AVLTree;//这个结束后返回
	}
	else if (data < AVLTree->data) {//左子树查找
		AVLTree->lchild = deleteElemAVL(AVLTree->lchild, data);
	}
	else {//右子树查找
		AVLTree->rchild = deleteElemAVL(AVLTree->rchild, data);
	}
	if (AVLTree->lchild) {//先调左右子树,最后调整根节点
		AVLTree->lchild = adjustAVLTree(AVLTree->lchild);
	}
	if (AVLTree->rchild) {
		AVLTree->lchild = adjustAVLTree(AVLTree->rchild);
	}
	if (AVLTree) {
		AVLTree = adjustAVLTree(AVLTree);
	}
	return AVLTree;
}
void prePrint(avlTree*  T) {//前序遍历AVL
	if (T) {
		printf("%d ", T->data);
		prePrint(T->lchild);
		prePrint(T->rchild);
	}
}
int main() {
	avlTree* T = NULL;//一定要初始化为空树
	int count, data;
	printf("开始构造avl:\n输入avl结点的数目:");
	scanf_s("%d", &count);
	int counts = 0;
	while (count--) {//构造avl
		counts += 1;
		printf("输入avl的第%d个结点:", counts);
		scanf_s("%d", &data);
		insertAVLTree(T, data);
	}
	printf("前序遍历avl\n");
	prePrint(T);//前序遍历avl
	printf("\n");
	printf("删除avl的结点:");
	scanf_s("%d", &count);
	deleteElemAVL(T, count);
	printf("删除avl的结点后的前序遍历\n");
	prePrint(T);//前序遍历avl
	printf("\n");
	system("pause");
	return 0;
}

测试截图:

请添加图片描述

时间复杂度:O(logn),空间复杂度O(logn)

如果存在什么问题,欢迎批评指正!谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fighting的码农(zg)-GPT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值