平衡二叉树(AVL树)--笔记

/******************************

备忘关键词:
平衡因子(BF)、树重(树高)
LL(左旋)、RR(右旋)
LR(先左旋后右旋)、RL(先右旋后左旋)

******************************/
#include<iostream>
#include<queue>
using namespace std;
#define max(a, b) (a > b) ? a : b
typedef struct node{
	int value;
	int weight;//等于左右子树中最大的树重 + 1
	struct node *left;
	struct node *right;
}BTNode;
int getWeight(BTNode *N) {//获得当前节点的树重
	if (N == NULL) return 0;//空是零
	return N->weight;
}
int getBalance(BTNode *N) {//计算当前节点的平衡因子(左 - 右)
	if (N == NULL) return 0;
	return getWeight(N->left) - getWeight(N->right);
}
BTNode *get_r_MinValue(BTNode *root) {//获得右子树的最小值,返回指针
	BTNode *T = root;
	while (T->left != NULL) T = T->left;//向左遍历直到为空
	return T;
}
BTNode *lRotate(BTNode *N) {
	BTNode *T = N->right;
	N->right = T->left;
	T->left = N;
	N->weight = max(getWeight(N->left), getWeight(N->right)) + 1;
	T->weight = max(getWeight(T->left), getWeight(T->right)) + 1;
	return T;
}
BTNode *rRotate(BTNode *N) {
	BTNode *T = N->left;
	N->left = T->right;
	T->right = N;
	N->weight = max(getWeight(N->left), getWeight(N->right)) + 1;
	T->weight = max(getWeight(T->left), getWeight(T->right)) + 1;
	return T;
}
BTNode *lrRotate(BTNode *N) {
	BTNode *T = N->left;
	N->left = lRotate(T);
	return rRotate(N);
}
BTNode *rlRotate(BTNode *N) {
	BTNode *T = N->right;
	N->right = rRotate(T);
	return lRotate(N);
}
BTNode *toBalance_in(BTNode *root, int value) {//插入后自平衡
	root->weight = max(getWeight(root->left), getWeight(root->right)) + 1;

	int balance = getBalance(root);

	if (balance < -1 && value > root->right->value) {//左自旋
		return lRotate(root);
	}
	if (balance > 1 && value < root->left->value) {//右自旋
		return rRotate(root);
	}
	if (balance < -1 && value < root->right->value) {//右旋后左旋
		return rlRotate(root);
	}
	if (balance > 1 && value > root->left->value) {//左旋后右旋
		return lrRotate(root);
	}
	return root;
}
BTNode *toBalance_de(BTNode *root) {//删除后自平衡
	root->weight = max(getWeight(root->left), getWeight(root->right)) + 1;

	int balance = getBalance(root);
	//多多画图有助理解
	if (balance < -1 && getBalance(root->right) == 0) {//左自旋
		return lRotate(root);
		//如果当前节点平衡因子 < -1且右节点平衡因子 == 0 左旋即可
	}
	if (balance > 1 && getBalance(root->left) == 0) {//右自旋
		return rRotate(root);
		//如果当前节点平衡因子 > 1且左节点平衡因子 == 0 右旋即可
	}
	if (balance < -1 && getBalance(root->right) > 0) {//右旋后左旋
		return rlRotate(root);
	}
	if (balance > 1 && getBalance(root->left) < 0) {//左旋后右旋
		return lrRotate(root);
	}
	return root;
}
BTNode *insert(BTNode *root,int value) {//平衡二叉树插入节点
	if (root == NULL) {  //一直遍历到空节点
		BTNode *newNode = (BTNode *)malloc(sizeof(struct node));
		newNode->left = NULL;
		newNode->right = NULL;
		newNode->value = value;
		newNode->weight = 1;//新节点默认树重是1
		return newNode;
	}
	if (value > root->value) {//插到右子树
		root->right = insert(root->right, value);
	}
	else if (value < root->value) {//插到左子树
		root->left = insert(root->left, value);
	}
	else return root;//重复的不存放

	root = toBalance_in(root, value);   //插入调整

	return root;
}
BTNode *Delete(BTNode *root, int value) {
	//空节点说明不存在要删除
	if (root == NULL) return root;

	if (root->value < value) {//如果比它小说明在右子树上
		root->right = Delete(root->right, value);
	}
	else if (root->value > value) {//如果比它大说明在左子树上
		root->left = Delete(root->left, value);
	}
	else {//相等就看看是哪一种情况
		//分情况删除
		if (root->left == NULL || root->right == NULL) {//左右子树至少有一个空
			BTNode *T = (root->left == NULL) ? root->right : root->left;

			if (T == NULL) {//都是空叶子节点直接删除
				T = root;
				root = NULL;
			}
			else *root = *T;
			//!直接用 *T 替换 *root,而不是root = T (因为这只是指针指向,free之后会丢失节点)
			free(T);
		}
		else {     
			//左右子树都不为空 就用当前节点右子树的最小值节点替换当前节点,并把最小节点删掉(尽量减少因删除而造成的旋转操作)
			BTNode *T = get_r_MinValue(root->right);
			root->value = T->value;
			root->right = Delete(root->right, root->value);//删掉最小节点
		}
	}

	if (root == NULL) return root;//上面的Delete可能会造成空

	root = toBalance_de(root);//删除调整

	return root;
}
void bfs(BTNode *root) {//层序遍历
	if (root == NULL) return;
	queue<BTNode*> q;
	BTNode *N;
	q.push(root);
	while (!q.empty()) {
		N = q.front();
		cout << N->value << ' ';
		q.pop();
		if (N->left != NULL) q.push(N->left);
		if (N->right != NULL) q.push(N->right);
	}
}
int main() {
	BTNode *root = NULL;
		int num;
		for (int i = 0; i < 10; i++) {//节点数为10的平衡二叉树(AVL树)
			cin >> num;
			root = insert(root, num);
		}
		cout << "初始状态层序遍历:";
		bfs(root);
		cout << '\n';
		while(cin>>num){
			root = Delete(root, num);
			cout << "删除节点 " << num << " 后层序遍历:";
			bfs(root);
			cout << '\n';
		}

	return 0;
}

学习博客。
关于平衡二叉树最需要搞懂的就是它的平衡模式:LL、RR、LR、RL四种。这四种模式有的人根据插入删除的位置来理解,有的则根据旋转方向来理解,重要的是明白其运作过程,多画图往往事半功倍,有助于理解吸收。注释写的还算详细,自己动手敲敲也算大致理解了平衡二叉树。

自己试了试暂时没有发现错误,如果有误希望能够不吝指正。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值