Fork me on GitHub

04-树5 Root of AVL Tree + AVL树操作集

  An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Figures 1-4 illustrate the rotation rules.

 

     

 

     

Now given a sequence of insertions, you are supposed to tell the root of the resulting AVL tree.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer NN (\le 2020) which is the total number of keys to be inserted. Then NN distinct integer keys are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the root of the resulting AVL tree in one line.

Sample Input 1:

5
88 70 61 96 120

Sample Output 1:

70

/*!
 * \file 04-树5 Root of AVL Tree.cpp
 *
 * \author ranjiewen
 * \date 2017/04/01 18:54
 *
 * 
 */

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

typedef struct AVLNode *Position;
typedef Position AVLTree;
typedef int ElementType;
struct AVLNode{
    ElementType Data;
    AVLTree Left;
    AVLTree Right;
    int Height;  //树高
};

int Max(int a, int b)
{
    return a > b ? a : b;
}

//可将程序中用到的GetTreeHeight()替换掉
int GetHeight(Position p)
{
    if (!p)
        return -1;
    return p->Height;
}

int GetTreeHeight(AVLTree T)
{
    int HL = 0, HR = 0;
    int Max_H = 0;
    if (T)
    {
        if (T->Left)
        {
            HL = GetTreeHeight(T->Left);
        }
        if (T->Right)
        {
            HR = GetTreeHeight(T->Right);
        }
        Max_H = (HL > HR) ? (HL + 1) : (HR + 1);
    }
    return  Max_H;
}

AVLTree SingleLeftRotation(AVLTree A)
{
    //A必须有一个左子结点B
    //将A与B做左单旋,更新A,B的高度,返回新的根节点B
    AVLTree B = A->Left;
    A->Left = B->Right;
    B->Right = A;
    A->Height = Max(GetTreeHeight(A->Left), GetTreeHeight(A->Right)) + 1;
    B->Height = Max(GetTreeHeight(B->Left), A->Height) + 1;
    return B;
}

AVLTree SingleRightRotation(AVLTree A)
{
    //A必须有一个右子节点B
    //将A,B做右单旋,更新A,B的高度,返回新的根节点B
    AVLTree B = A->Right;
    A->Right = B->Left;
    B->Left = A;
    A->Height = Max(GetTreeHeight(A->Left),GetTreeHeight(A->Right))+1;
    B->Height = Max(GetTreeHeight(B->Right), A->Height) + 1;

    return B;
}

AVLTree DoubleLeftRightRotation(AVLTree A)
{
    //A必须有一个左子节点B,且B必须有一个右子节点C
    //将A,B与C做两次单旋,返回新的根节点C
    
    //将B,C做右单旋,C被返回
    A->Left = SingleRightRotation(A->Left);
    //将A与C做左单旋,C被返回
    return SingleLeftRotation(A);
}

AVLTree DoubleRightLeftRotation(AVLTree A)
{
    //A必须有一个右子节点B,且B必须有一个左子节点C
    
    //将B,C做左单旋,C被返回
    A->Right = SingleLeftRotation(A->Right);
    //将A,C做右单旋,C被返回
    return SingleRightRotation(A);
}

//将x插入到AVL树中,并且返回调整后的AVL树
AVLTree Insert(AVLTree T, ElementType x)
{
    if (!T)
    {
        //若为空树,则新建包含一个结点的树
        T = (AVLTree)malloc(sizeof(struct AVLNode));
        T->Data = x;
        T->Left = T->Right = NULL;
        T->Height = 0;
    }
    else if (x<T->Data)
    {
        //插入T的左子树
        T->Left = Insert(T->Left,x);
        //如果需要左旋
        if (GetTreeHeight(T->Left)-GetTreeHeight(T->Right)==2)
        {
            if (x < T->Left->Data) //需要左单旋
            {
                T = SingleLeftRotation(T);
            }
            else
                T = DoubleLeftRightRotation(T); //左-右双旋
        }
    }
    else if (x>T->Data)
    {
        T->Right = Insert(T->Right,x);
        //如果需要右旋
        if (GetTreeHeight(T->Left)-GetTreeHeight(T->Right)==-2)
        {
            if (x>T->Right->Data) //右单旋
            {
                T = SingleRightRotation(T);
            }
            else
            {
                T = DoubleRightLeftRotation(T); //右-左双旋
            }
        }
    }
    // else x==T->Data 无需插入
    
    //别忘了更新树高
    T->Height = Max(GetTreeHeight(T->Left), GetTreeHeight(T->Right)) + 1;
    return T;
}

static int FindMin(AVLTree T){
    if (T == NULL){
        return -1;
    }
    while (T->Left != NULL){
        T = T->Left;
    }
    return T->Data;
}

//返回-1表示,树中没有该数据,删除失败,
int Delete(AVLTree *T, ElementType D){ //指针的指针
    static Position tmp;
    if (*T == NULL){
        return -1;
    }
    else{
        //找到要删除的节点
        if (D == (*T)->Data){
            //删除的节点左右子支都不为空,一定存在前驱节点
            if ((*T)->Left != NULL && (*T)->Right != NULL){

                D = FindMin((*T)->Right);//找后继替换
                (*T)->Data = D;
                Delete(&(*T)->Right, D);//然后删除后继节点,一定成功

                //在右子支中删除,删除后有可能左子支比右子支高度大2
                if (GetHeight((*T)->Left) - GetHeight((*T)->Left) == 2){
                    //判断哪一个左子支的的两个子支哪个比较高
                    if (GetHeight((*T)->Left->Left) >= GetHeight((*T)->Left->Right)){
                        *T=SingleRightRotation(*T);
                    }
                    else{
                        *T = DoubleLeftRightRotation(*T);
                        /*LeftRotate(&(*T)->left);
                        RightRotate(T);*/
                    }
                }
            }
            else
            if ((*T)->Left == NULL){//左子支为空
                tmp = (*T);
                (*T) = tmp->Right;
                free(tmp);
                return 0;
            }
            else
            if ((*T)->Right == NULL){//右子支为空
                tmp = (*T);
                (*T) = tmp->Right;
                free(tmp);
                return 0;
            }
        }
        else
        if (D > (*T)->Data){//在右子支中寻找待删除的节点
            if (Delete(&(*T)->Right, D) == -1){
                return -1;//删除失败,不需要调整,直接返回
            }
            if (GetHeight((*T)->Left) - GetHeight((*T)->Right) == 2){
                if (GetHeight((*T)->Left->Left) >= GetHeight((*T)->Left->Right)){
                    *T=SingleRightRotation(*T);
                }
                else{
                    *T = DoubleLeftRightRotation(*T);
                    /*LeftRotate(&(*T)->left);
                    RightRotate(T);*/
                }
            }
        }
        else
        if (D < (*T)->Data){//在左子支中寻找待删除的节点
            if (Delete(&(*T)->Left, D) == -1){
                return -1;
            }
            if (GetHeight((*T)->Right) - GetHeight((*T)->Right) == 2){
                if (GetHeight((*T)->Right->Right) >= GetHeight((*T)->Right->Left)){
                    *T=SingleLeftRotation(*T);
                }
                else{
                    *T = DoubleRightLeftRotation(*T);
                    /*RightRotate(&(*T)->right);
                    LeftRotate(T);*/
                }
            }
        }
    }
    //更新当前节点的高度
    (*T)->Height = Max(GetHeight((*T)->Left), GetHeight((*T)->Right)) + 1;
    //printf("%d\n", (*T)->Data);
    return 0;
}

int main()
{
    int N,data;
    AVLTree root=nullptr;
    scanf("%d", &N);
    for (int i = 0; i < N;i++)
    {
        scanf("%d", &data);
        root = Insert(root, data);
    }
    printf("%d\n",root->Data);

    Delete(&root, 70);
    printf("%d\n", root->Data);

    return 0;
}
AVL树原理及实现 +B树

 
C/C++基本语法学习 STL C++ primer
posted @ 2017-04-02 00:05  ranjiewen  阅读(686)  评论(0编辑  收藏  举报