平衡二叉树(AVL)

AVL树是基于二叉搜索树的,它要求它的左右子树的高度差绝对值不超过1。

AVL树主要用在对一颗二叉搜索树进行插入时,如何保证树的平均查找长度最小?

这就需要在插入时进行相应的调整,使AVL树的左右高度差不超过1。

 

代码如下:

 

//AVL.h

/*************************************************************
平衡二叉树,是建立在二叉搜索树上,在旋转调整
过程中一定要注意,要满足二叉搜索树的定义。


设A为平衡被破坏节点,B为A的儿子,C为B的儿子
单旋转:LL和RR俩种,
左单旋(LL,顺时针): 若: B = A->Left,  C =B->Right
则: B ->Right = A , A ->Left = C;
最后把B挂在A原来的父亲后面

右单旋(RR,逆时针):若:B =A-Right, C =B->Left
则:B ->Left = A, A->Right = C;
最后把B挂在A原来的父亲后面
双旋转:LR和RL两种,
LR: 先RR调整后LL调整。大致情况如下:
条件: B = A->Left, C =B->Right;
则: B ->Right =C->Left , C ->Left= B
A->Left = C->Right, C->Right = A

RL:先LL后RR.
条件: B=A->Right, C =B->Left;
则:B->Left = C->Right  ,  C->Right =B;
A->Right =C->Left ,C = C ->Left  = C;

注意理解旋转,左单旋顺时针,右单旋逆时针。
*****************************************************************/



typedef struct AVLNode *Position;
typedef Position AVLTree;

struct AVLNode{
    int Data;
    AVLTree Left;
    AVLTree Right;
    int Height;
};

int GetHeight(AVLTree);

AVLTree SingleLeftRotation(AVLTree);

AVLTree SingleRightRotation(AVLTree);

AVLTree DoubleLeftRightRotation(AVLTree);

AVLTree DoubleRightLeftRotation(AVLTree);

AVLTree Insert(AVLTree, int);

void PreOrderTraversal(AVLTree);

AVLTree BuildTree();

 

//.cpp



#include <stdio.h>
#include <stdlib.h>
#include "AVL.h"


int Max(int a, int b)
{
    return a > b ? a : b;
}
/**********************************************
    用后序遍历改编,即用递归先找到
    叶子节点,然后每退一次 高度就加一;
    
***********************************************/
int GetHeight(AVLTree A)
{
    int MaxH, HR, HL;
    if (A){
        HL = GetHeight(A->Left);
        HR = GetHeight(A->Right);
        MaxH = (HL > HR) ? HL : HR;    
        return MaxH+1;                
    }
    return -1;      //如果树为空树高为 -1,叶子节点为0;
}
/*LL旋转*/
AVLTree SingleLeftRotation(AVLTree A)
{
    AVLTree B = A->Left;
    A->Left = B->Right;
    B->Right = A;
    A->Height = Max(GetHeight(A->Left), GetHeight(A->Right)) + 1;
    B->Height = Max(GetHeight(B->Left), A->Height) + 1;
    return B;
}

/*RR旋转*/
AVLTree SingleRightRotation(AVLTree A)
{
    AVLTree B = A->Right;
    A->Right = B->Left;
    B->Left = A;
    A->Height = Max(GetHeight(A->Left), GetHeight(A->Right)) + 1;
    B->Height = Max(A->Height, GetHeight(B->Right)) + 1;

    return B;
}

/*LR旋转*/
AVLTree DoubleLeftRightRotation(AVLTree A)
{
    A->Left = SingleRightRotation(A->Left);

    return SingleLeftRotation(A);
}

/*RL旋转*/
AVLTree DoubleRightLeftRotation(AVLTree A)
{
    A->Right = SingleLeftRotation(A->Right);

    return SingleRightRotation(A);
}

AVLTree Insert(AVLTree T, int x)
{
    if (!T){
        T = (AVLTree)malloc(sizeof(struct AVLNode));
        T->Data = x;
        T->Height = 0;
        T->Left = T->Right = NULL;
    }
    else {
        //x 插在左边
        if (x < T->Data){
            T->Left = Insert(T->Left, x);
            if (GetHeight(T->Left) - GetHeight(T->Right) == 2){
                if (x<T->Left->Data)           //判断x在T的左儿子那边
                    T = SingleLeftRotation(T);
                else
                    T = DoubleLeftRightRotation(T);
            }
        }
        //x插在右边
        else if (x>T->Data){
            T->Right = Insert(T->Right, x);
            if (GetHeight(T->Left) - GetHeight(T->Right) == -2){
                if (x > T->Right->Data)
                    T = SingleLeftRotation(T);
                else
                    T = DoubleRightLeftRotation(T);
            }
        }
    }
    //加1更新高度
        T->Height = Max(GetHeight(T->Left), GetHeight(T->Right)) + 1;  
    return T;
}

void PreOrderTraversal(AVLTree A)
{
    if (A){
        printf("value =%d  height=%d\n", A->Data, A->Height);
        PreOrderTraversal(A->Left);
        PreOrderTraversal(A->Right);
    }

}

AVLTree BuildTree()
{
    AVLTree A = NULL;

    int n;
    while (scanf_s("%d", &n) != EOF)
        A = Insert(A,n);

    return A;

}

int main()
{
    AVLTree A;
    A = BuildTree();
    
    PreOrderTraversal(A);
    putchar('\n');
    printf("请输入你要插入的数 \n");
    int n;
    while (scanf_s("%d", &n) != EOF){
        Insert(A, n);
        PreOrderTraversal(A);

        printf("Next number:\n");
    }

    return 0;
    
}

 

推荐:VisuAlgo(https://visualgo.net/en) 可视化工具

 

 

坚持!!!!!!!!!!!!

 

 

 

 

 

 

 

 

posted @ 2017-10-27 17:21  hytt-  阅读(547)  评论(0)    收藏  举报