patA1066

代码的注意点:
AVL树重新平衡最核心的思想是找到离新加入的节点最近的失衡节点。
insert操作的基础是插入新节点前子树已经是一个AVL树,这是根据平衡因子判断树型的依据。
不要把BF作为node的成员变量,因为在左旋/右旋后BF的实际值就会改变,而在判断LL/LR/RR/RL型树时使用未更新的BF成员会引发错误。正确的做法是在使用平衡因子时通过左右子树的高度来计算。
一定要有getHeight函数,并用它来获取子树的高度,否则很可能会因为使用空指针造成段错误。
正确的AVL树的根节点对应的数据一定是树中所有数据的根节点,可据此判断结果是否正确。
左旋与右旋的实现中不要遗漏掉更新root和temp节点的height值

代码:

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

//AVL树的节点
struct node {
	int v;
	int height;	//以node为根节点的子树的高度
	struct node* lchild;
	struct node* rchild;
	node(int _v) { v = _v; height = 1; lchild = rchild = NULL; }
};

const int MAX = 25;
int N;
int num[MAX] = { 0 };
struct node* Root=NULL;	//树根

void input() {
	cin >> N;
	for (int i = 0; i < N; i++) {
		cin >> num[i];
	}
}


//获取当前子树的树高
int getHeight(struct node* root) {
	int height = root == NULL ? 0 : root->height;
	return height;
}

//更新当前子树的树高
void updateHeight(struct node* root) {
	int lheight = getHeight(root->lchild);
	int rheight = getHeight(root->rchild);
	root->height = max(lheight, rheight) + 1;
}

//左旋
void lo(struct node* &root) {
	struct node* temp = root->rchild;
	root->rchild = temp->lchild;
	temp->lchild = root;
	updateHeight(root); 
	updateHeight(temp);
	root = temp;
}

//右旋
void ro(struct node* &root){
	struct node* temp = root->lchild;
	root->lchild = temp->rchild;
	temp->rchild = root;
	updateHeight(root);
	updateHeight(temp);
	root = temp;
}

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

//计算当前结点的平衡因子BF
int getBF(struct node* root) {
	return getHeight(root->lchild)-getHeight(root->rchild);
}

//向AVL树插入一个节点,注意root必须是指针的引用,这样才能起到更新的作用
void insert(struct node* &root,int v) {
	//递归边界
	if (root == NULL) {
		root = new struct node(v);
		return;
	}

	//转左子树
	if (root->v > v) {
		insert(root->lchild, v);

		//更新当前子树的高度
		updateHeight(root);
		//递归调用结束后判断当前子树是否失衡
		int BF = getBF(root);	//平衡因子BF
		//BF==2说明当前节点为失衡节点
		if (BF == 2) {
			//判断是LL还是LR
			if (getBF(root->lchild) == 1) {
				//LL型树,右旋
				ro(root);
			}
			else if (getBF(root->lchild) == -1) {
				//LR型树
				lo(root->lchild);
				ro(root);
			}
		}
	}
	//转右子树
	else {
		insert(root->rchild, v);
		updateHeight(root);
		int BF = getBF(root);
		if (BF == -2) {
			if (getBF(root->rchild)==-1) {
				lo(root);
			}
			else if (getBF(root->rchild) == 1) {
				ro(root->rchild);
				lo(root);
			}
		}
	}
}

//创建一棵AVL树
void create() {
	for (int i = 0; i < N; i++) {
		insert(Root, num[i]);
	}
}

int main(void) {
	input();
	create();
	cout << Root->v << endl;
}
posted @ 2022-05-15 17:41  带带绝缘体  阅读(25)  评论(0)    收藏  举报