平衡二叉树(AVL树)

来源:互联网 发布:网络摄像机哪个好 编辑:程序博客网 时间:2024/06/06 04:12

平衡二叉树是在二叉搜索树的基础上增加了限制:

①:树的深度为logN。

②:每个节点的左子树和右子树的高度最多差一的二叉搜索树。


基本操作:调整!!!

引入平衡因子:左右子树的高度差。

当平衡因子绝对值大于等于2的时候,就需要调整。

单旋转比较简单,直接把被破坏节点下一个节点提上去,然后再根据二叉搜索树的特点进行换儿子即可。如下图:


实现:

#include<stdio.h>#include<stdlib.h>#define ElementType inttypedef struct BiNode{    ElementType Data;    int Height;    struct BiNode* Left;    struct BiNode* Right;} BiNode, *BinTree,*Position;int Height(Position P){    if(!p)return 0;    else return P->Height;}//为什么非要用这个函数?直接用结构体中的不行吗?---NULL!!!Position Single_Rotate_With_Left(Position K2)//把k2的左儿子k1提上去,k2当k1的右儿子。{Position K1 = K2->Left;K2->Left = K1->Right;//换儿子K1->Right = K2;//提上去K2->Height = max(Height(K2->Left), Height(K2->Right)) + 1;K1->Height = max(Height(K1->Left), Height(K1->Right)) + 1;return K1;}Position Single_Rotate_With_Right(Position K2){Position K1 = K2->Right;K2->Right = K1->Left;K1->Left = K2;K2->Height = max(Height(K2->Left), Height(K2->Right)) + 1;K1->Height = max(Height(K1->Left), Height(K1->Right)) + 1;return K1;}


双旋转是“麻烦节点”在左儿子的右边,或者右儿子的左边。如下图:这时候是把麻烦节点提上去,然后再进行儿子的交换即可。

实现:可以通过两次单旋转进行完成,避免了换儿子的过程。

Position Double_Rotate_With_Left(Position K3){K3->Left = Single_Rotate_With_Right(K3->Left);return Single_Rotate_With_Left(K3);}Position Double_Rotate_With_Right(Position K3){K3->Right = Single_Rotate_With_Left(K3->Right);return Single_Rotate_With_Right(K3);}Position Double_Rotate_With_Left(Position K3){    Position K2=K3->Left->Right,K1=K3->Left;       K3->Left=K2->Right;//换儿子       K2->Right=K3;//提       K1->Right=K2->Left;//换儿子       K2->Left=K1;//提}



AVL树的插入,在二叉搜索树插入的基础上,增添调整就可以!

注意这里有递归回溯。(拓展GCD有没有)。

至于删除,我的思路是假设是删除左边了,这时候要看根节点右边的树高是否比左边树高大于等于2,然后进而根据右子树对应的左树高和右树高,右大于左,那就要对根节点进行RR旋转,否则RL旋转。(网上都是引入的平衡因子,也就是高度差,我这种想法的正确与否,考完期末再写个例子进行检验~!插入的历程是正确的(直接在黑书上拿来的。))。

BinTree Insert( ElementType X, BinTree BST )if( !BST ){    BST = (Bintree)malloc(sizeof(struct TreeNode));    BST->Data = X;    BST->Left = BST->Right = NULL;    BST->Height=1;}else if( X < BST->Data ){    BST->Left = Insert( X, BST->Left);    if(Height(BST->Left)-Height(BST->Right)==2)//自底向上回溯        if(X<BST->Left->Data)            BST=Single_Rotate_With_Left(BST);        else BST=Position Double_Rotate_With_Left(BST);}else if( X > BST->Data ){    BST->Right = Insert( X, BST->Right);    if(Height(BST->Right)-Height(BST->Left)==2)        if(X>BST->Right->Data)   BST=Single_Rotate_With_Right(BST);        else BST=Double_Rotate_With_Right(BST);}/* else X已经存在,什么都不做 */BST->Height=max(Height(BST->left),Height(BST->Right))+1;//更新树高return BST;}BinTree Delete( ElementType X, BinTree BST ){    Position Tmp;    if( !BST ) printf("要删除的元素未找到");    else if( X < BST->Data )    {        BST->Left = Delete( X, BST->Left); /* 左子树递归删除 */        if(Height(BST->Right)-Height(BST->Left)==2)            if(Height(BST->Right->Right)>=Height(BST->Right->Left))                Single_Rotate_With_Right(BST);            else Double_Rotate_With_Right(BST);    }    else if( X > BST->Data )    {        BST->Right = Delete( X, BST->Right);        if(Height(BST->Left)-Height(BST->Right)==2)            if(Height(BST->Left->Left)>=Height(BST->Left->Right))                Single_Rotate_With_Left(BST);            else Double_Rotate_With_Left(BST);    }/* 右子树递归删除 */    else /*找到要删除的结点 */        if( BST->Left && BST->Right )        {            /*被删除结点有左右两个子结点 */            Tmp = FindMin( BST->Right ); /*在右子树中找最小的元素填充删除结点*/            BST->Data = Tmp->Data;            BST->Right = Delete( BST->Data, BST->Right); /*在删除结点的右子树中删除最小元素*/            if(Height(BST->Right)-Height(BST->Left)==2)                if(Height(BST->Right->Right)>=Height(BST->Right->Left))                    Single_Rotate_With_Right(BST);                else Double_Rotate_With_Right(BST);        }        else        {            /*被删除结点有一个或无子结点*/            Tmp = BST;            if( !BST->Left ) /* 有右孩子或无子结点*/                BST = BST->Right;            else if( !BST->Right ) /*有左孩子或无子结点*/                BST = BST->Left;            free( Tmp );        }    BST->Height=max(Height(BST->left),Height(BST->Right))+1;//更新树高    return BST;}