平衡二叉树的定义:
平衡二叉树或者是一棵空树,或者是具有以下性质的二叉排序树:
平衡二叉树的左子树和右子树的深度之差小于等于1,且左子树和右子树也是平衡二叉树。
二叉排序树的定义:
二叉排序树或者是一棵空树,或者是具有以下性质的二叉树:
1、若任意结点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2、任意结点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3、任意结点的左、右子树也分别为二叉排序树。
4、没有键值相等的结点。
向一棵平衡二叉树中插入/删除结点可能使平衡二叉树失去平衡,通过使插入点/删除点最近的祖先结点恢复平衡,从而使上一层祖先结点恢复平衡。
因此,为了使平衡二叉树保持平衡,需要从离插入点/删除点最近的结点开始调整。
造成平衡二叉树失衡的类型以及调整方法可以归纳为以下四种情况:
总结如下:
1、针对LL型,需要进行一次右旋操作
2、针对LR型,需要先进行一次左旋操作,然后进行一次右旋操作
3、针对RL型,需要先进行一次右旋操作,然后进行一次左旋操作
4、针对RR型,需要进行一次左旋操作
相关数据结构与函数代码如下:
typedef int KEY_TYPE;
typedef struct AVL{
KEY_TYPE key;
int height;
struct AVL* lchild;
struct AVL* rchild;
}AVL;
AVL* New_Node(KEY_TYPE key, AVL* lchild, AVL* rchild, int height = 0);
inline int getHeight(AVL* node);
AVL* Left_Rotate(AVL* k2);
AVL* Right_Rotate(AVL* k2)
AVL* RR_Rotate(AVL* k2);
AVL* LL_Rotate(AVL* k2);
AVL* LR_Rotate(AVL* k3);
AVL* RL_Rotate(AVL* k3);
AVL* Insert(AVL* root, KEY_TYPE key);
AVL* Delete(AVL* root, KEY_TYPE key);
AVL* New_Node(KEY_TYPE key, AVL* lchild, AVL* rchild, int height)
{
AVL* p_avl = new AVL;
p_avl->key = key;
p_avl->lchild = lchild;
p_avl->rchild = rchild;
p_avl->height = height;
return p_avl;
}
inline int getHeight(AVL* node)
{
return (node==NULL)? -1:node->height;
}
inline int max(int a, int b)
{
return a>b?a:b;
}
/* 左旋操作:
k2 k1
/ \ / \
X k1 ==> k2 Z
/ \ / \
Y Z X Y
*/
AVL* Left_Rotate(AVL* k2)
{
AVL* k1 = k2->rchild;
k2->rchild = k1->lchild;
k1->lchild = k2;
k2->height = max(getHeight(k2->lchild), getHeight(k2->rchild)) + 1;
k1->height = max(getHeight(k1->rchild), k2->height) + 1;
return k1;
}
/* 右旋操作:
k2 k1
/ \ / \
k1 Z ==> X k2
/ \ / \
X Y Y Z
*/
AVL* Right_Rotate(AVL* k2)
{
AVL* k1 = k2->lchild;
k2->lchild = k1->rchild;
k1->rchild = k2;
k2->height = max(getHeight(k2->lchild), getHeight(k2->rchild)) + 1;
k1->height = max(getHeight(k1->lchild), k2->height) + 1;
return k1;
}
/* LL(针对失衡结点调用右旋操作):
k2 k1
/ \ / \
k1 Z ==> X k2
/ \ / \
X Y Y Z
*/
AVL* LL_Rotate(AVL* k2)
{
return Right_Rotate(k2);
}
/* RR(针对失衡结点调用左旋操作):
k2 k1
/ \ / \
X k1 ==> k2 Z
/ \ / \
Y Z X Y
*/
AVL* RR_Rotate(AVL* k2)
{
return Left_Rotate(k2);
}
/* LR(针对失衡结点的左孩子调用左旋操作,针对失衡结点调用右旋操作):
k3 k3 k2
/ \ / \ / \
k1 D k2 D k1 k3
/ \ ==> / \ ==> / \ / \
A k2 k1 C A B C D
/ \ / \
B C A B
*/
AVL* LR_Rotate(AVL* k3)
{
k3->lchild = Left_Rotate(k3->lchild);
return Right_Rotate(k3);
}
/* RL(针对失衡结点的右孩子调用右旋操作,针对失衡结点调用左旋操作):
k3 k3 k2
/ \ / \ / \
A k1 A k2 k3 k1
/ \ ==> / \ ==> / \ / \
k2 B C k1 A C D B
/ \ / \
C D D B
*/
AVL* RL_Rotate(AVL* k3)
{
k3->rchild = Right_Rotate(k3->rchild);
return Left_Rotate(k3);
}
AVL* Insert(AVL* root, KEY_TYPE key)
{
if(root == NULL)
return (root = New_Node(key, NULL, NULL));
else
{
if(key == root->key)
return root;
else if(key < root->key)
root->lchild = Insert(root->lchild, key);
else
root->rchild = Insert(root->rchild, key);
}
root->height = max(getHeight(root->lchild), getHeight(root->rchild)) + 1;
if(getHeight(root->lchild) - getHeight(root->rchild) == 2)
{
if(key < root->lchild->key)
root = LL_Rotate(root);
else
root = LR_Rotate(root);
}
else if(getHeight(root->rchild) - getHeight(root->lchild) == 2)
{
if(key < root->rchild->key)
root = RL_Rotate(root);
else
root = RR_Rotate(root);
}
return root;
}
AVL* Delete(AVL* root, KEY_TYPE key)
{
if(!root)
return NULL;
if(key == root->key)
{
if(root->rchild == NULL)//如果右子树为空,那么左子树只可能为空或者左子树只含有一个根结点
{
AVL* temp = root;
root = root->lchild;
delete(temp);
return root;
}
else
{
AVL* temp = root->rchild;
while(temp->lchild)
temp = temp->lchild;//找到root结点的后继结点
root->key = temp->key;//将后继结点的值赋给root
root->rchild = Delete(root->rchild, temp->key);//将后继结点删除掉
}
}
else if(key < root->key)
root->lchild = Delete(root->lchild, key);
else
root->rchild = Delete(root->rchild, key);
root->height = max(getHeight(root->lchild), getHeight(root->rchild)) + 1;
if(getHeight(root->rchild) - getHeight(root->lchild) == 2)
{
if(getHeight(root->rchild->rchild) >= getHeight(root->rchild->lchild))
root = RR_Rotate(root);
else
root = RL_Rotate(root);
}
else if(getHeight(root->lchild) - getHeight(root->rchild) == 2)
{
if(getHeight(root->lchild->lchild) >= getHeight(root->lchild->rchild))
root = LL_Rotate(root);
else
root = LR_Rotate(root);
}
return root;
}