AVL树是一种带有平衡条件的二叉查找树,所有节点都是基于平衡的。所谓平衡,即某个节点的左右子树的高度差最多相差1。空树的高度定义为-1。
下面我们通过如下两棵树(图片来自《数据结构与算法分析–C语言描述》)进一步了解怎样的树才是AVL树。
上图只有左边的树才是AVL树,那么下面我们来分析一下左边的树
(某个节点的高 = MAX(子树的高, 右子树的高 )+ 1)
节点3的高为0
节点4的高为1
节点1的高为0
节点7的高为0
节点2的高为2
节点8的高为1
节点5的高为3
你可以看到任一节点的左右子树的差都没有超过2,那么我们再看看右边的树
节点2的高为2
节点8的高为0
所以对于节点7来说,左右子树的高度差相差为2 > 1,失去平衡。
下面我们接着来说AVL的插入、删除、查找操作。
插入和删除操作都有可能导致AVL树的不平衡(为什么呢?原来的树是平衡的,即某个节点的左右子树的高度差小于2,假设左子树的高为1,右子树的高为0,如果这个时候,在这个节点的左子树插入一个节点,那么该节点的左右子树的高度差就为2了,删除操作也是一样的)。
对于出现不平衡的时候,需要通过旋转来解决。下面我们直接来看看插入操作。
插入操作
插入节点==》有可能失去平衡==》通过旋转操作来使树达到平衡
我们把需要重新平衡的节点叫做A,那么出现不平衡的情况,会有下面四种:
1. 对A节点的左儿子的左子树进行插入
2. 对A节点的左儿子的右子树进行插入
3. 对A节点的右儿子的左子树进行插入
4. 对A节点的右儿子的右子树进行插入
下图对应上面四种情况
针对情况一和情况四,我们采取的是单旋转(旋转一次)的操作
针对情况二和情况三,我们采取的是双旋转(旋转两次)的操作
单旋转,其法则是,如果哪边偏高,就往另一边旋转,
如情况一,旋转后的效果如下图
情况四旋转后的效果如下图
下图(来自《数据结构与算法分析–C语言描述》)对应情况一,从图中可以看出,K2的左右节点的高度差为2,不平衡,左边偏高,所以要往右边旋转。
我们直接来看看该单旋转算法的实现
Position * avl_tree_single_rotate_with_left(AVL_TREE * k2)
{
Position * k1;
k1 = k2->lChild;
k2->lChild = k1->rChild;
k1->rChild = k2;
k2->height = avl_tree_max(avl_tree_height(k2->lChild), avl_tree_height(k2->rChild)) + 1;
k1->height = avl_tree_max(avl_tree_height(k1->lChild), avl_tree_height(k1->rChild)) + 1;
return k1;
}
双旋转,先旋转失去平衡节点K3的第一个儿子节点K1,然后再旋转K3。如情况二,旋转后的最终效果如下图
情况三,旋转后的最终效果如下图
下图(来自《数据结构与算法分析–C语言描述》)对应情况二,从图上可以看出,K3节点的左右子树高度差为2,不平衡,需要先旋转K1和K2,然后再旋转K2和K3。
我们来看看该双旋转算法的实现
Position * avl_tree_double_rotate_with_left(AVL_TREE * k3)
{
/* Rotate between k1 and k2 */
k3->lChild = avl_tree_single_rotate_with_right(k3->lChild);
/* Rotate between k2 and k3 */
return avl_tree_single_rotate_with_left(k3);
}
删除操作
删除操作可以参考二叉查找树的删除操作,其实就是分以下三种情况
1. 如果删除的value比tree->value大,那么继续往右边搜索
2. 如果删除的value比tree->value小,那么继续往左边搜索
3. 如果找到删除的value,那么又要分以下两种情况处理
1. 如果该节点有左右孩子的,那么用右子树的最小节点替代这个被删除的节点,然后再递归删除右子树的最小节点
2. 如果该节点只有一个左或者右孩子或者是没有孩子节点的,直接删除,返回相应的tree指针
删除操作,也是有可能造成树的不平衡。比如,删除下面这棵树的节点4,就会引起节点3的不平衡(左孩子的高为2,右孩子的高为0)
有一个很重要的一点,删除之前,树是平衡的,所以删除之后,不管删除节点有几个孩子,其左右子节点的高度差最多是2,不会超过2(删除节点的父节点或者是父父节点,再往上也是一样的),否则原来的树就是不平衡的,删除之后,无非有可能出现下面这四种情况
当删除之后,先要更新tree的高度,然后再判断tree是否失去平衡,如果失去平衡,再按照下面的算法调整
/* Update the height of tree */
tree->height = avl_tree_max(avl_tree_height(tree->lChild), avl_tree_height(tree->rChild)) + 1;
if(avl_tree_height(tree->lChild) - avl_tree_height(tree->rChild) == 2)
{
if(tree->lChild->rChild)
tree = avl_tree_double_rotate_with_left(tree);
else
tree = avl_tree_single_rotate_with_left(tree);
}
else if(avl_tree_height(tree->rChild)- avl_tree_height(tree->lChild) == 2)
{
if(tree->rChild->lChild)
tree = avl_tree_double_rotate_with_right(tree);
else
tree = avl_tree_single_rotate_with_right(tree);
}
查找操作
这个最简单,主要有三种情况:
1. 当查找value比tree->value小的时候,继续往左边查找
2. 当查找value比tree->value大的时候,继续往右边查找
3. 当查找value == tree->value时,返回
下面是上述操作的实现代码(下面代码有用到tree_visual_create.h,该头文件是将二叉树可视化,方便查看结果,具体可以参考二叉树的可视化)
avl_tree.h
#ifndef __AVL_TREE_H__
#define __AVL_TREE_H__
typedef int ElementType;
typedef struct AVL_TREE_T
{
ElementType value;
struct AVL_TREE_T * lChild;
struct AVL_TREE_T * rChild;
int height;
}AVL_TREE;
typedef AVL_TREE Node;
typedef AVL_TREE Position;
extern void avl_tree_main(void);
#endif
avl_tree.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "avl_tree.h"
#include "tree_visual_create.h"
int avl_tree_max(int h1, int h2)
{
if(h1 > h2)
return h1;
else
return h2;
}
int avl_tree_height(AVL_TREE * tree)
{
if(NULL == tree)
return -1;
else
return tree->height;
}
Node * avl_tree_find(AVL_TREE * tree, ElementType value)
{
Node * node = NULL;
if(tree)
{
if(tree->value == value)
node = tree;
else if(tree->value > value)
node = avl_tree_find(tree->lChild, value);
else if(tree->value < value)
node = avl_tree_find(tree->rChild, value);
}
return node;
}
Node * avl_tree_find_min(AVL_TREE * tree)
{
AVL_TREE * node = NULL;
if(tree)
{
if(tree->lChild)
node = avl_tree_find_min(tree->lChild);
else
node = tree;
}
return node;
}
Node * avl_tree_find_max(AVL_TREE * tree)
{
AVL_TREE * node = NULL;
if(tree)
{
if(tree->rChild)
node = avl_tree_find_max(tree->rChild);
else
node = tree;
}
return node;
}
Position * avl_tree_single_rotate_with_left(AVL_TREE * k2)
{
Position * k1;
k1 = k2->lChild;
k2->lChild = k1->rChild;
k1->rChild = k2;
k2->height = avl_tree_max(avl_tree_height(k2->lChild), avl_tree_height(k2->rChild)) + 1;
k1->height = avl_tree_max(avl_tree_height(k1->lChild), avl_tree_height(k1->rChild)) + 1;
return k1;
}
Position * avl_tree_single_rotate_with_right(AVL_TREE * k1)
{
Position * k2;
k2 = k1->rChild;
k1->rChild = k2->lChild;
k2->lChild = k1;
k1->height = avl_tree_max(avl_tree_height(k1->lChild), avl_tree_height(k1->rChild)) + 1;
k2->height = avl_tree_max(avl_tree_height(k2->lChild), avl_tree_height(k2->rChild)) + 1;
return k2;
}
Position * avl_tree_double_rotate_with_left(AVL_TREE * k3)
{
/* Rotate between k1 and k2 */
k3->lChild = avl_tree_single_rotate_with_right(k3->lChild);
/* Rotate between k2 and k3 */
return avl_tree_single_rotate_with_left(k3);
}
Position * avl_tree_double_rotate_with_right(AVL_TREE * k1)
{
/* Rotate between k2 and k3 */
k1->rChild = avl_tree_single_rotate_with_left(k1->rChild);
/* Rotate between k1 and k2 */
return avl_tree_single_rotate_with_right(k1);
}
AVL_TREE * avl_tree_insert(AVL_TREE * tree, ElementType value)
{
if(NULL == tree)
{
tree = (AVL_TREE *)malloc(sizeof(AVL_TREE));
if(NULL == tree)
printf("AVL_TREE malloc failed\n");
else
{
tree->value = value;
tree->height = 0;
tree->lChild = tree->rChild = NULL;
}
}
else if(tree->value > value)
{
tree->lChild = avl_tree_insert(tree->lChild, value);
if(avl_tree_height(tree->lChild) - avl_tree_height(tree->rChild) == 2)
{
if(value < tree->lChild->value)
tree = avl_tree_single_rotate_with_left(tree);
else
tree = avl_tree_double_rotate_with_left(tree);
}
}
else if(tree->value < value)
{
tree->rChild = avl_tree_insert(tree->rChild, value);
if(avl_tree_height(tree->rChild)- avl_tree_height(tree->lChild) == 2)
{
if(value > tree->rChild->value)
tree = avl_tree_single_rotate_with_right(tree);
else
tree = avl_tree_double_rotate_with_right(tree);
}
}
tree->height = avl_tree_max(avl_tree_height(tree->lChild), avl_tree_height(tree->rChild)) + 1;
return tree;
}
Node * avl_tree_delete(AVL_TREE * tree, ElementType value)
{
AVL_TREE * temp = NULL;
if(NULL == tree)
{
printf("Not found the element\n");
}
else if(value > tree->value) /* Go Right */
{
tree->rChild = avl_tree_delete(tree->rChild, value);
}
else if(value < tree->value) /* Go Left */
{
tree->lChild = avl_tree_delete(tree->lChild, value);
}
else if(tree->lChild && tree->rChild) /* Two Children */
{
temp = avl_tree_find_min(tree->rChild);
tree->value = temp->value;
tree->rChild = avl_tree_delete(tree->rChild, tree->value);
}
else /* one or zero Children */
{
temp = tree;
if(NULL == tree->lChild)
{
tree = tree->rChild;
}
else if(NULL == tree->rChild)
{
tree = tree->lChild;
}
free(temp);
}
if(tree) /* Ignore the free node */
{
/* Update the height of tree */
tree->height = avl_tree_max(avl_tree_height(tree->lChild), avl_tree_height(tree->rChild)) + 1;
if(avl_tree_height(tree->lChild) - avl_tree_height(tree->rChild) == 2)
{
if(tree->lChild->rChild)
tree = avl_tree_double_rotate_with_left(tree);
else
tree = avl_tree_single_rotate_with_left(tree);
}
else if(avl_tree_height(tree->rChild)- avl_tree_height(tree->lChild) == 2)
{
if(tree->rChild->lChild)
tree = avl_tree_double_rotate_with_right(tree);
else
tree = avl_tree_single_rotate_with_right(tree);
}
}
return tree;
}
void avl_tree_destroy(AVL_TREE * tree)
{
if(tree)
{
if(tree->lChild)
avl_tree_destroy(tree->lChild);
if(tree->rChild)
avl_tree_destroy(tree->rChild);
free(tree);
}
}
void avl_tree_main(void)
{
AVL_TREE * tree = NULL;
//int i=0;
//for(i=1; i<=127; i++)
// tree = avl_tree_insert(tree, i);
#if 0
tree = avl_tree_insert(tree, 7);
tree = avl_tree_insert(tree, 6);
tree = avl_tree_insert(tree, 10);
tree = avl_tree_insert(tree, 5);
tree = avl_tree_insert(tree, 13);
tree = avl_tree_insert(tree, 8);
tree = avl_tree_insert(tree, 11);
#endif
#if 0
tree = avl_tree_insert(tree, 5);
tree = avl_tree_insert(tree, 3);
tree = avl_tree_insert(tree, 6);
tree = avl_tree_insert(tree, 4);
#endif
#if 0
tree = avl_tree_insert(tree, 5);
tree = avl_tree_insert(tree, 2);
tree = avl_tree_insert(tree, 8);
tree = avl_tree_insert(tree, 1);
tree = avl_tree_insert(tree, 4);
tree = avl_tree_insert(tree, 7);
tree = avl_tree_insert(tree, 3);
#endif
#if 0
tree = avl_tree_insert(tree, 7);
tree = avl_tree_insert(tree, 6);
tree = avl_tree_insert(tree, 8);
tree = avl_tree_insert(tree, 5);
tree = avl_tree_insert(tree, 9);
tree = avl_tree_insert(tree, 10);
#endif
#if 0
tree = avl_tree_insert(tree, 8);
tree = avl_tree_insert(tree, 3);
tree = avl_tree_insert(tree, 10);
tree = avl_tree_insert(tree, 2);
tree = avl_tree_insert(tree, 5);
tree = avl_tree_insert(tree, 9);
tree = avl_tree_insert(tree, 11);
tree = avl_tree_insert(tree, 1);
tree = avl_tree_insert(tree, 4);
tree = avl_tree_insert(tree, 6);
tree = avl_tree_insert(tree, 12);
tree = avl_tree_insert(tree, 7);
#endif
#if 1
tree = avl_tree_insert(tree, 3);
tree = avl_tree_insert(tree, 2);
tree = avl_tree_insert(tree, 4);
tree = avl_tree_insert(tree, 1);
#endif
tree_visual_create(tree, "tree_insert.dot");
Node * min = avl_tree_find_min(tree);
printf("min value : %d\n", min->value);
Node * max = avl_tree_find_max(tree);
printf("max value : %d\n", max->value);
Node * find = avl_tree_find(tree, 2);
if(find)
printf("find value : %d\n", find->value);
else
printf("Cannot find the value\n");
tree = avl_tree_delete(tree, 4);
tree_visual_create(tree, "tree_delete.dot");
avl_tree_destroy(tree);
}
来源:CSDN
作者:Timsley
链接:https://blog.csdn.net/Timsley/article/details/54601205