平衡二叉树的基本操作

点击查看代码
#include<cstdio>
#include<algorithm>
using namespace std;
#pragma warning(disable:4996)

//平衡二叉树AVL的定义
struct node {
	int data; //数据域
	int height; //以当前结点为根结点的左右子树高度差 
	node* lchild, * rchild; //左右孩子结点地址
};

//新建一个权值为data的结点
node* newNode(int data) {  
	node* Node = new node; //申请新结点内存
	Node->data = data; //存储结点权值
	Node->height = 1; //新结点高度初始为1
	Node->lchild = Node->rchild = NULL; //结点左右孩初始为空结点
	return Node; //返回新结点地址
}

//获取以root为根结点的子树的当前高度
int getHeight(node* root) {	
	if (root == NULL) return 0; //空结点高度为0
	return root->height; //返回结点高度
}

//计算根结点root的平衡因子
int getBalanceFactor(node* root) { 
	return getHeight(root->lchild) - getHeight(root->rchild); //左子树高度减右子树高度
}

//更新根结点root的高度
void updateHeight(node* root) { 
	//根结点高度等于其左子树高度或右子树高度的较大者加一
	root->height = max(getHeight(root->lchild), getHeight(root->rchild)) + 1;
}

//平衡二叉树AVL的基本操作
//AVL是二叉查找树,查找操作与二叉查找树一样
void search(node* root, int data) {	//查找权值为data的结点
	if (root == NULL) {	//遇到空结点时查找失败
		printf("search failed\n");
		return; //结束递归,返回上一层
	}
	if (root->data == data) { //找到权值为data的结点
		printf("%d\n", root->data); //输出结点权值
	}
	else if (data < root->data) { //待查权值data小于根结点权值
		search(root->lchild, data); //进入左子树中查找
	}
	else { //待查权值data大于根结点权值
		search(root->rchild, data); //进入右子树中查找
	}
}

//AVL的插入操作是在BST的插入操作基础上,增加二叉树的平衡操作
//在AVL中插入一个新结点后如果出现不平衡,则要使用左旋或右旋重新平衡AVL
void L(node*& root) { //左旋left rotation,root会被修改地址,使用引用指针型
	node* temp = root->rchild; //temp指向root的右孩
	root->rchild = temp->lchild; //root的右孩指向temp的左孩
	temp->lchild = root; //temp的左孩指向root
	updateHeight(root); //更新root的高度
	updateHeight(temp); //更新temp的高度
	root = temp; //root重新指向根结点
}

//右旋就是把左旋中的所有lchild和rchild互换,它们是互为逆操作
void R(node*& root) { 
	node* temp = root->lchild; //temp指向root的左孩
	root->lchild = temp->rchild; //root的左孩指向temp的右孩
	temp->rchild = root; //temp的右孩指向root
	updateHeight(root); //更新root的高度
	updateHeight(temp); //更新temp的高度
	root = temp; //root重新指向根结点
}

/*在AVL树中插入一个结点后,可能出现4种不平衡情况:(BF是指平衡因子,如BF(root)=2表示根结点的平衡因子为2)
(1)在左子树中插入新结点出现不平衡
	1)LL型:BF(root)=2, BF(root->lchild)=1,对root进行右旋
	2)LR型:BF(root)=2, BF(root->lchild)=-1, 先对root->lchild进行左旋变为LL型,再对root进行右旋
(2)在右子树中插入新结点出现不平衡
	1)RR型:BF(root)=-2, BF(root->rchild)=-1, 对root进行左旋
	2)RL型:BF(root)=-2, BF(root->rchild)=1, 先对root->rchild进行右旋变为RR型,再对root进行左旋
*/
void insert(node*& root, int data) { //插入权值为data的结点到AVL中
	if (root == NULL) {	//root是空结点找到插入位置
		root = newNode(data); //新建一个权值为datat的结点,地址赋给root
		return; //结束递归,返回上一层
	}
	if (data < root->data) { //权值data小于root
		insert(root->lchild, data); //递归进入左子树中查找插入位置
		updateHeight(root); //插入完成后,更新根结点高度
		if (getBalanceFactor(root) == 2) { //如果根结点平衡因子为2,则发生不平衡
			if (getBalanceFactor(root->lchild) == 1) { //左孩平衡因子为1,则变为LL型
				R(root); //对root进行右旋恢复平衡
			}
			else if (getBalanceFactor(root->lchild) == -1) { //左孩平衡因子为-1,则变为LR型
				L(root->lchild); //先对左孩进行左旋变为LL型
				R(root); //再对root进行右旋恢复平衡
			}
		}
	}
	else { //权值data大于等于root
		insert(root->rchild, data); //进入右子树中查找插入位置
		updateHeight(root); //插入完成后,更新根结点高度
		if (getBalanceFactor(root) == -2) { //如果根结点平衡因子为-2,则发生不平衡
			if (getBalanceFactor(root->rchild) == -1) { //右孩平衡因子为-1,则变为RR型
				L(root); //对root进行左旋恢复平衡
			}
			else if (getBalanceFactor(root->rchild) == 1) { //右孩平衡因子为1,则变为RL型
				R(root->rchild); //先对右孩进行右旋变为RR型
				L(root); //再对root进行左旋恢复平衡
			}
		}
	}
}

//建立AVL树
node* create(int data[], int n) { 
	node* root = NULL; //新建树的根结点root,初始为空结点
	for (int i = 0; i < n; i++) {
		insert(root, data[i]); //将data[0]~data[n-1]插入AVL树中
	}
	return root;
}

posted @ 2022-09-30 21:11  zhaoo_o  阅读(8)  评论(0编辑  收藏  举报