AVL树C语言代码

普通的二叉查找树很容易导致某一侧的子树高度远远超过另一侧,这就导致了搜索效率的降低。AVL树(自平衡二叉查找树的诞生就是为了解决此类问题),和之前的BST树很类似,但是要添加上平衡因子,并在插入或删除某结点后进行平衡。

上次代码的问题所在就是Delete功能在删除结点进行平衡时出现的错误,Delete操作的时候,要小心的判断是哪种旋转,然后再去解决,同时还要注意,删除结点后应该先判断这个树是否为空,然后再决定是否需要平衡。(现在心力交瘁)

关于平衡说一下个人判断小技巧:

如果一个树(T),进行插入操作插入点在左子树(T->Left)上,那么有两种情况,树仍然平衡,或不再平衡,如果仍然平衡那就不需要进一步操作了,如果不再平衡,那么问题一定是左子树造成的,我们这个时候需要判断左子树(T->Left)的左子树(T->Left->Left)和右子树(T->Left->Right)的高度差,如果差为-1,则代表这个左子树(T->Left)仅有一个右子树,这个时候就需要LR旋转了(本程序的DoubleRotateWithLeft()函数),如果差是1或者0,那么只需要LL旋转即可(本程序的SingleRotateWithLeft()函数)

如果是插入点在右子树上,操作刚好和上述过程相反。

同理删除右子树的结点近似于增添左子树的结点,删除左子树的结点近似于增添右子树的结点

这个还是亲自动手画画图,然后多敲代码多测试吧。

这个树学着挺绕的,但是本质问题只要能理解了,那么LL,RR,LR,RL四种旋转,包括插入删除时候的平衡就很容易了。

测试数据:(Insert一次,Delete两次,每次都以0为结束标志,0不参与树的插入和删除)

15 6 50 4 7 23 71 5 0

在这里插入图片描述

23 0

在这里插入图片描述

71 0

在这里插入图片描述

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

typedef int ElemType;

typedef struct AvlNode
{
    ElemType Element;
    AvlNode *Left;
    AvlNode *Right;
    int Height;
} AvlNode,*AvlTree,*Position;

AvlTree MakeEmpty(AvlTree T);
Position Find(ElemType X,AvlTree T);
Position FindMin(AvlTree T);
Position FindMax(AvlTree T);
AvlTree Insert(ElemType X,AvlTree T);
AvlTree Delete(ElemType X,AvlTree T);
ElemType Retrieve(Position P);

static int Height(Position P)
{
    if(P==NULL)
        return -1;
    else
        return P->Height;
}

AvlTree MakeEmpty(AvlTree T)
{
    if(T!=NULL)
    {
        MakeEmpty(T->Left);
        MakeEmpty(T->Right);
        free(T);
    }
    return NULL;
}

Position Find(ElemType X,AvlTree T)
{
    if(T==NULL)
    {
        printf("Element not found\n");
        return NULL;
    }
    if(X<T->Element)
        return Find(X,T->Left);
    else if(X>T->Element)
        return Find(X,T->Right);
    else
        return T;
}

Position FindMin(AvlTree T)
{
    if(T==NULL)
    {
        printf("Element not found\n");
        return NULL;
    }
    if(T->Left)
        return FindMin(T->Left);
    else
        return T;
}

Position FindMax(AvlTree T)
{
    if(T==NULL)
    {
        printf("Element not found\n");
        return NULL;
    }
    if(T->Right)
        return FindMax(T->Right);
    else
        return T;
}

static int Max(int Lhs,int Rhs)
{
    return Lhs > Rhs ? Lhs : Rhs;
}

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;
    //Height(K1->Right) == K2->Height
    K1->Height = Max(Height(K1->Left),K2->Height)+1;

    return K1;
}

static Position SingleRotateWithRight(Position K1)
{
    Position K2;

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

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

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

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

AvlTree Insert(ElemType X,AvlTree T)
{
	if(T==NULL)
	{
		T = (AvlTree)malloc(sizeof(AvlNode));
		if(T==NULL)
		{
			printf("Malloc Error\n");
			exit(1);
		}
		T->Element = X;
		T->Height = 0;
		T->Left = 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 = DoubleRotateWithLeft(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;
}

AvlTree Delete(ElemType X,AvlTree T)
{
    Position temp;
    if(T==NULL)
    {
        printf("Element not found\n");
        return NULL;
    }
    else if(X<T->Element)
    {
        T->Left = Delete(X,T->Left);
    }
    else if(X>T->Element)
    {
        T->Right = Delete(X,T->Right);
    }
    else if(T->Left && T->Right)
    {
        temp = FindMin(T->Right);
        T->Element = temp->Element;
        T->Right = Delete(T->Element,T->Right);
    }
    else
    {
        temp = T;
        if(T->Left==NULL)
            T = T->Right;
        else if(T->Right==NULL)
            T = T->Left;
        free(temp);
    }

    if(T!=NULL)
    {
        int balance = Height(T->Left)-Height(T->Right);
        if(balance==2)
        {
            int balance2 = Height(T->Left->Left)-Height(T->Left->Right);
            if(balance2==-1)
            {
                T = DoubleRotateWithLeft(T);
            }
            else
            {
                T = SingleRotateWithLeft(T);
            }
        }
        else if(balance==-2)
        {
            int balance2 = Height(T->Right->Left)-Height(T->Right->Right);
            if(balance2==-1)
            {
                T = DoubleRotateWithRight(T);
            }
            else
            {
                T = SingleRotateWithRight(T);
            }
        }
        T->Height = Max(Height(T->Left),Height(T->Right))+1;
    }
    return T;
}

ElemType Retrieve(Position P)
{
    return P->Element;
}
int Depth(AvlTree T)
{
    int Ldepth,Rdepth;
    if(T==NULL)
        return 0;
    if(T->Left)
        Ldepth = Depth(T->Left);
    else
        Ldepth = 0;
    if(T->Right)
        Rdepth = Depth(T->Right);
    else
        Rdepth = 0;
    return Ldepth>Rdepth ? Ldepth+1:Rdepth+1;
}

void PreOrderTraversal(AvlTree T)
{
    if(T==NULL)
        return ;
    printf("%d ",T->Element);
    PreOrderTraversal(T->Left);
    PreOrderTraversal(T->Right);
}

void InOrderTraversal(AvlTree T)
{
    if(T==NULL)
        return ;
    InOrderTraversal(T->Left);
    printf("%d ",T->Element);
    InOrderTraversal(T->Right);
}

void PostOrderTraversal(AvlTree T)
{
    if(T==NULL)
        return ;
    PostOrderTraversal(T->Left);
    PostOrderTraversal(T->Right);
    printf("%d ",T->Element);
}

int main()
{
    AvlTree T=NULL;
    T = MakeEmpty(T);

    int depth = Depth(T);
    printf("The depth of this tree is :%d\n",depth);

    while(1)
    {
        int Element;
        scanf("%d",&Element);
        if(Element==0)
            break;
        else
            T = Insert(Element,T);
    }

    depth = Depth(T);
    printf("The depth of this tree is :%d\n",depth);

    printf("PreOrderTraversal: ");
    PreOrderTraversal(T);
    printf("\n");
    printf("InOrderTraversal: ");
    InOrderTraversal(T);
    printf("\n");
    printf("PostOrderTraversal: ");
    PostOrderTraversal(T);
    printf("\n");

    while(1)
    {
        int Element;
        scanf("%d",&Element);
        if(Element==0)
            break;
        else
            T = Delete(Element,T);
    }
    printf("---After Delete---\n");
    depth = Depth(T);
    printf("The depth of this tree is :%d\n",depth);

    printf("PreOrderTraversal: ");
    PreOrderTraversal(T);
    printf("\n");
    printf("InOrderTraversal: ");
    InOrderTraversal(T);
    printf("\n");
    printf("PostOrderTraversal: ");
    PostOrderTraversal(T);
    printf("\n");

    while(1)
    {
        int Element;
        scanf("%d",&Element);
        if(Element==0)
            break;
        else
            T = Delete(Element,T);
    }
    printf("---After Delete---\n");
    depth = Depth(T);
    printf("The depth of this tree is :%d\n",depth);

    printf("PreOrderTraversal: ");
    PreOrderTraversal(T);
    printf("\n");
    printf("InOrderTraversal: ");
    InOrderTraversal(T);
    printf("\n");
    printf("PostOrderTraversal: ");
    PostOrderTraversal(T);
    printf("\n");


    return 0;
}

The depth of this tree is :0
15 6 50 4 7 23 71 5 0
The depth of this tree is :4
PreOrderTraversal: 15 6 4 5 7 50 23 71
InOrderTraversal: 4 5 6 7 15 23 50 71
PostOrderTraversal: 5 4 7 6 23 71 50 15
23 0
---After Delete---
The depth of this tree is :4
PreOrderTraversal: 15 6 4 5 7 50 71
InOrderTraversal: 4 5 6 7 15 50 71
PostOrderTraversal: 5 4 7 6 71 50 15
 71 0
---After Delete---
The depth of this tree is :3
PreOrderTraversal: 6 4 5 15 7 50
InOrderTraversal: 4 5 6 7 15 50
PostOrderTraversal: 5 4 7 50 15 6

Process returned 0 (0x0)   execution time : 10.002 s
Press any key to continue.
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值