对于而查找树来说序列{1,2,3,4,5} 会是一个右斜树,这样复杂度就是O(n),起不到使用二叉树查找树来进行数据查询优化的目的。于是需要对树进行调整:
使树的高度在每次插入元素后仍能保持O(logn)的级别;

于是就产生了平衡二叉树

 

平衡因子:左子树与右子树的高度之差称为该结点的平衡因子。

 

只要能随时保证每个结点平衡因子的绝对值不超过1,AVL的高度就始终能保持O(logn),

 

 

由于需要对每个结点都得得到平衡因子,因此需要在树的结构中加入一个变量height,来记录当前结点的为根结点的子树高度:

struct node
{
	int data;//结点权值
	int height;//为当前子树高度
	tree L;
	tree R;
};

 

 

获取结点root所在子树的当前高度:

int getHeight(tree root)
{
	if (root == NULL) return 0;//空结点高度为0
	return root->height;
}

 

 

 

根据平衡因子的定义,可以获取平衡因子:

int getBalanceFactor(tree root)
{
	//左子树高度减去右子树的高度
	return getHeight(root->L) - getHeight(root->R);
}

 

 

 

结点root所在子树的height等于其左子树的height与右子树的height的较大值加1,因此更新height可以如下写法:

void updataHeight(tree root)
{
	root->height = max(getHeight(root->L), getHeight(root->R)) + 1;
}

 

 

 

平衡二叉树的基本操作:

1.查找操作:

int searchh(tree root, int x)
{
	if (root == NULL) return 0;
	if (root->data == x) return 1;
	else if (root->data < x) searchh(root->R, x);
	else searchh(root->L, x);
}

 

2,插入操作:

这个二叉查找树是有区别的,因为,需要考虑平衡因子,所以不能像二叉查找树那样直接插入。

这里引进了   左旋(L)  右旋(R)  

 

L:

就是下图的A和B换位置,A,B换位置的同时,他们的儿子也要相应的根据平衡二叉树来进行变换,下面是变换规则

平衡二叉树(AVL)

步骤:

1.让B的左子树成为A的右子树 

2.让A成为B的左子树

3.让根节点设定为结点B

图中黑色填充代表真个过程中该部分的父节点发生了变化。

void L(tree &root)
{
	tree temp = root->R;//root指向结点A,temp指向结点B
	root->R = temp->L;//步骤1
	temp->L = root;//步骤2
	updataHeight(root);//更新结点A的高度
	updataHeight(temp);//更新结点B的高度
	root = temp;//步骤3
}

 

R:

既然有左旋那么就一定有右旋

如图:右旋

平衡二叉树(AVL)

平衡二叉树(AVL)

右旋步骤:

1.让A的右子树成为B的左子树

2.让B成为A的右子树

3.将根节点设定为结点A

void R(tree &root)
{
	tree temp = root->L;
	root->L = temp->R;
	temp->R = root;
	updataHeight(root);
	updataHeight(temp);
	root = temp;
}

 

 

二者可以发现就是代码R变成L,L变成R的区别

平衡二叉树(AVL)

 

 

对于LL和LR的讨论(LL和LR不是左旋和右旋的意思):

 平衡二叉树(AVL)

按照上图讨论:

当结点A的左孩子的平衡因子是1时为LL型,是-1时为LR型。

 

先考虑LL型:

 平衡二叉树(AVL)

可以把以c为根节点的子树看作一个整体,然后以结点A作为root进行右旋

 

 

考虑LR型:

 平衡二叉树(AVL)

可以先忽略结点A,以结点c为root进行左旋,就可以把情况转化为LL型,然后按照上面的LL型的做法进行一次右旋即可。

 

 

同样的对于RR和RL型是一样的思路:

平衡二叉树(AVL) 

void insertt(tree &root, int x)
{
	if (root == NULL) {
		root = new node;
		root->data = x;
		root->height = 1;
		root->R = root->L = NULL;
		return;
	}
	if (x < root->data) {
		insertt(root->L, x);
		updataHeight(root);
		if (getBalanceFactor(root) == 2) {
			if (getBalanceFactor(root->L) == 1) {//LL型
				R(root);
			}
			else if (getBalanceFactor(root->L) == -1) {//LR型
				L(root->L);
				R(root);
			}
		}
	}
	else {
		insertt(root -> R, x);
		updataHeight(root);
		if(getBalanceFactor(root) == -2) {
			if (getBalanceFactor(root->R) == -1) {//RR型
				L(root);
			}
			else if (getBalanceFactor(root->R) == 1) {//RL型
				R(root->R);
				L(root);
			}
		}
	}
}

 例题链接

相关文章: