平衡二叉树的C语言实现(创建、插入、查找、删除、旋转)【数据结构】

版权声明:转载请先联系并注明出处! https://blog.csdn.net/u010552731/article/details/47393549

平衡二叉树(AVL)或者是一颗空树,或者是具有下列性质的非空二叉搜索树:

(1). 任一结点的左、右子树均为AVL树;

(2). 任一结点的左、右子树高度差的绝对值不超过1。


对于二叉树中任一结点T,其“平衡因子”(Balance Factor, BF)定义为BF(T) = Hl-Hr,其中Hl和Hr分别为T的左、右子树的高度。


有了平衡因子的定义,AVL树“任一结点左右子树高度差的绝对值不超过1”这一性质可以表述为“一棵AVL树中任一结点的平衡因子只能在集合{-1,0,1}中取值”。这就是平衡的量化标准。


当一棵AVL树插入或删除一个结点时,该结点的平衡因子很可能不在上述集合范围内,破坏了树的平衡,这时就需要做“平衡化”处理,即相应的局部“旋转”调整,使得调整后的树达到平衡。


(1). 单旋调整(左左、右右)


(2). 双旋调整(左-右、右-左)



基本操作:

//=========================================================================================
//                              平衡二叉树---AVL
//=========================================================================================
//Define an AVLTree
typedef struct AVLTreeNode *AVLTree;
typedef struct AVLTreeNode{
    int Data;
    AVLTree Left;
    AVLTree Right;
    int Height;
}
//=========================================================================================

//平衡二叉树的插入操作(按中序操作)
AVLTree AVL_Insertion(ElementType X, AVLTree T){//将X插入树T中,并返回调整后的树
    if(!T){
        T = malloc(sizeof(AVLTreeNode));
        T->Data = X;
        T->Height = 0;
        T->Left = T->Right = NULL;
    }
    else if(X < T->Data){
        T->Left = AVL_Insertion(X, T->Left);    //递归比较并插入,将插入后的左子树更新给T-Left
        if(GetHeight(T->Left) - GetHeight(T->Right) == 2)
            if(X < T->Left->Data)
                T = SingleLeftRotation(T);  //左单旋
            else
                T = DoubleLeftRightRotation(T); //左-右双旋
    }
    else if(X > T->Data){
        T->Right = AVL_Insertion(X, T->Right);  //递归比较并插入,将插入后的右子树更新给T->Right
        if(GetHeight(T->Left) - GetHeight(T->Right) == -2)
            if(X > T->Right->Data)                            
                T = SingleLeftRotation(T);  //右单旋               
            else                                         
                T = DoubleRightLeftRotation(T); //右-左双旋            
    }        
    //else X == T->Data, 无需插入
    T->Height = Max(GetHeight(T->Left), GetHeight(T->Right)) + 1;//树高等于子树高度加一
    
    return T;   //返回插入并调整后的树
}
//=========================================================================================

//左单旋算法
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(GetHeight(A->Left), GetHeight(A->Right)) + 1;
    B->Height = Max(GetHeight(B->Left), GetHeight(A->Height)) + 1;
    return B;
}
//=========================================================================================

//左-右双旋算法
AVLTree DoubleLeftRightRotation(AVLTree A){
//注意:A必须有一个左子结点B,且B必须有一个右子结点C
//将A.B与C做单旋两次,返回新的根结点C

    A->Left = SingleRightRotation(A->Left);//将B与C做右单旋,C被返回
    return SingleLeftRotation(A);   //将A与C做左单旋,C被返回
}
//=========================================================================================

//平衡二叉树的查找操作
AVLTree Find(ElementType X, AVLTree T){
    if(!T)
        return NULL;
    if(X < T->Data)
        return Find(X, T->Left);
    else if(X > T->Data)
        return Find(X, T->Right);
    else
        return T;
}
//=========================================================================================

//平衡二叉树的删除操作
//删除方法与二叉查找树一致,区别是,删除完成后,需要从删除节点的父亲开始向上维护树的
//平衡一直到根结点(调整树)。
AVLTree Delete(ElementType X, AVLTree T){
    if(!T){         //树为空,报错
        printf("ERROR!");
        return NULL;
    }
    if(X < T->Data)
        T->Left = Delete(X, T->Left);   //递归查找并删除指定元素X 
    else if(X > T->Data)
        T->Right = Delete(X, T->Right);
    else{
        if(T->Left && T->Right){    //此结点含有左右两个子树        
            AVLTree Tmp = T->Right;
            while(Tmp->Left != NULL)    //查找T的右子树的最小值用于填补删除的元素的位置
                Tmp = Tmp->Left;
            T->Data = Tmp->Data;
            T->Right = Delete(Tmp->Data, T->Right);//删除移位后的Tmp->Data
            if(GetHeight(T->Left) - GetHeight(T->Right) == 2){
                //将T看做根结点,删除的元素在右子树,此时判断左子树与右子树的高度差是不是>=2
                //若是,则判断左子树是左单旋还是左-右双旋
                //若T->Left的右子树比左子树长,则为左-右双旋
                //若T->Left的左子树比右子树长,则为左单旋
                //              A
                //             /            A为T, B为T->Left
                //            B             若C分支长(T->Left->Left),则为左单旋
                //           / \            若D分支长(T->Left->Right),则为左右双旋
                //          C   D
                //          :   :
                if((T->Left->Right != NULL) && GetHeight(T->Left->Right) > GetHeight(T->Left->Left))
                    DoubleLeftRightRotation(T); //调用左-右双旋算法
                else
                    SingleLeftRotation(T);  //调用左单旋算法
            }
        }else{  //此结点含有一个或零个子树
            AVLTree Tmp = T;
            if(!T->Left)
                T = T->Right;
            else if(!T->Right)
                T = T->Left;
            free(Tmp);  //释放Tmp
        }
    }
    T->Height = Max(GetHeight(T->Left), GetHeight(T->Right));
    return T;
}


猜你喜欢

转载自blog.csdn.net/u010552731/article/details/47393549