个人项目:数据结构之AVL树的实现

AVL树为了防止树的深度过深出现的一种数据结构,在二叉树的基础上添加了一条规则:每个节点的左子数与右子树的高度最多差1。

其中的难点之一为:插入一个节点。删除一个节点更难,在这里采用懒惰删除法。其中,在插入的时候更新根节点路径上那些节点的所有高度。

AVL节点:

struct AvlNode
{
    ElementType Element;
    AvlTree Left;
    AvlTree Right;
    int Height;
};
//问题一:当插入一个节点时,如何知道哪个节点失去平衡

在插入一个节点的时候,可以通过对树进行简单的修正来使新的树满足AVL树的特性----旋转。

把需要平衡的节点叫做a。由于任意节点最多有两个节点,因此高度不平衡时,a点的两棵子树的高度差2。可以猜想出,这种不平衡可能出现在下列四种情况中:

  1. 对a的左儿子的左子树进行一次插入
  2. 对a的左儿子的右子树进行一次插入
  3. 对a的右儿子的右子树进行一次插入
  4. 对a的右儿子的左子树进行一次插入

其中情形1和3,2和4是关于a点镜像对称,具体巧妙可在代码中看出。其中调整1和3的情况是进行一次单旋转,2和4则需要一次双旋转。

1.对a的左儿子的左子树进行一次插入时,出现不平衡的情形为:

个人项目:数据结构之AVL树的实现_第1张图片

旋转代码为:

static Position SingleRotateWithLeft(Position K2)
{
    Position K1;

    K1 = K2->Left;
    K2->Left = K1->Right;
    K1->Right = K2;

    K2->Height = Max(Height(K2->Left), Height(K2->Right)) + 1;
    K1->Height = Max(K2->Height, Height(K1->Right)) + 1;

    return K1;
}

2.对a的左儿子的右子树插入一个节点,出现不平衡的情形为:
个人项目:数据结构之AVL树的实现_第2张图片

旋转代码为:

static Position DoubleRotateWithLeft(Position K3)
{
    K3->Left = SingleRotateWithRight(K3->Left);

    return SingleRotateWithLeft(K3);
}

3和4的旋转代码为:

static Position SingleRotateWithRight(Position K2)
{
    Position K1;

    K1 = K2->Right;
    K2->Right = K1->Left;
    K1->Left = K2;

    K2->Height = Max(Height(K2->Left), Height(K2->Right)) + 1;
    K1->Height = Max(K2->Height, Height(K1->Right)) + 1;

    return K1;
}
static Position DoubleRotateWithRight(Position K3)
{
    K3->Right = SingleRotateWithLeft(K3->Right);

    return SingleRotateWithRight(K3);
}

 AVL树如何插入一个节点:

  • 运用了递归,主要代码为:
    AvlTree Insert( ElementType X,  AvlTree T)
    {
        if ( T == NULL){};
        else if ( X < T->ElementType)
        {
            T->Left = Insert( X, T->Left)
            ...
        }
        else if ( X > T->ElementType)
        {
            T->Right = Insert( X, T->Right)
            ...
        }
        return T; //用于连接整个AVL树
    }

     详细代码在下面

  • 高度的计算决定了你是否能顺利插入,以及执行什么旋转
    AvlTree Insert(ElementType X, AvlTree T)
    {
        if(T == NULL)
        {
            T = malloc(sizeof(struct AvlNode));
            if(T == NULL)
                FatalError("Out of space!");
            else
            {
                T->Element = X;
                T->Height = 0;
                T->Left = NULL;
                T->Right = NULL;
            }
        }
        else if(X < T->Element)
        {
            T->Left = Insert(X, T->Left);
            if(Height(T->Left) - Height(T->Right) == 2)
                if(X < T->Left->Element)
                    T = SingleRotateWithLeft(T);
                else
                    T = DoubleRotateWithRight(T);
        }
        else if(X > T->Element)
        {
            T->Right = Insert(X, T->Right);
            if(Height(T->Right) - Height(T->Left) == 2)
                if(X > T->Right->Element)
                    T = SingleRotateWithRight(T);
                else
                    T = DoubleRotateWithRight(T);
        }
    
        T->Height = Max(Height(T->Left), Height(T->Right)) + 1;
        return T;
    }

     插入详解:

    个人项目:数据结构之AVL树的实现_第3张图片

你可能感兴趣的:(数据结构)