【C--step by step11】AVL平衡树

声明:

这篇是转载的。

删除节点建议懒删除。

节点的旋转细节讲解参看原贴。

出处:https://www.cnblogs.com/skywang12345/p/3576969.html

原贴写的非常好,致敬!

直接上代码

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

/**
 * AVL平衡树
 * 2019-09-27
 */

#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MAX_QUEUE_SIZE 50

typedef int ElementType;

typedef struct Node{
    ElementType data;
    struct Node *left, *right;
    int height;    //节点高度
}Node, *AVLTree;

typedef struct {
    AVLTree queue[MAX_QUEUE_SIZE];
    int front;
    int rear;
}Queue,*QueuePtr;

/**
 * 获取树的高度
 * @param T
 * @return
 */
int getHeight(AVLTree T)
{
    if(NULL == T)
        return 0;
    int lh = getHeight(T->left);
    int rh = getHeight(T->right);
    int max = MAX(lh, rh);

    return max + 1;
}

/**
 * 左单旋转
 * @param k2 失去平衡的结点
 * @return 旋转后的根结点
 */
Node *llRotation(AVLTree k2)
{
    AVLTree k1;
    k1 = k2->left;
    k2->left = k1->right;
    k1->right = k2;

    k2->height = MAX(getHeight(k2->left), getHeight(k2->right));
    k1->height = MAX(getHeight(k1->left), getHeight(k1->right));

    return k1;

}


/**
 * 右单旋
 * @param k1 失去平衡的结点
 * @return 旋转后的根结点
 */
Node *rrRotation(AVLTree k1)
{
    AVLTree k2;
    k2 = k1->right;
    k1->right = k2->left;
    k2->left = k1;

    k1->height = MAX(getHeight(k1->left), getHeight(k1->right));
    k2->height = MAX(getHeight(k2->left), getHeight(k2->right));

    return k2;
}

/**
 * LR 左双旋转
 * @param k3 失去平衡的结点
 * @return 旋转后的根节点
 */
Node *lrRotation(AVLTree k3)
{
    k3->left = rrRotation(k3->left);
    return llRotation(k3);
}

/**
 * RL 右双旋转
 * @param k1 失去平衡的结点
 * @return 旋转后的根节点
 */
Node *rlRotation(AVLTree k1)
{
    k1->right = llRotation(k1->right);
    return rrRotation(k1);
}

/**
 * 将结点插入AVL树中,并返回根结点
 * @param T 根结点
 * @param key
 * @return
 */
Node * insert(AVLTree T, ElementType key)
{
    if(NULL == T)
    {
        T = (Node *)malloc(sizeof(Node));
        if(!T)
        {
            printf("Memory allocated to node Failure!\n");
            exit(-1);
        }
        T->data = key;
        T->left = NULL;
        T->right = NULL;
        T->height = 1;
    }
    else if(key < T->data)
    {
        T->left = insert(T->left, key);
        //插入结点后,若AVL树失去平衡,则进行相应的调节
        if(getHeight(T->left) - getHeight(T->right) ==2)
        {
            if(key < T->left->data)
                T = llRotation(T);
            else
                T = lrRotation(T);
        }

    }
    else if(key > T->data)
    {
        T->right = insert(T->right, key);
        if(getHeight(T->right) - getHeight(T->left) ==2)
        {
            if(key > T->right->data)
                T = rrRotation(T);
            else
                T = rlRotation(T);
        }

    }
    else
    {
        printf("添加失败:不允许添加相同的结点!\n");
    }

    T->height = MAX(getHeight(T->left), getHeight(T->right));

    return T;

}

/**
 * 层遍历树
 * @param T
 */
void levelOrderTraverse(AVLTree T)
{
    if(NULL == T)
    {
        printf("Tree is Empty!\n");
        return;
    }

    QueuePtr Q = (QueuePtr)malloc(sizeof(Queue));
    if(!Q)
    {
        printf("Memory allocate to queue failed!\n");
        exit(-1);
    }

    AVLTree temp;

    //1.初始化,树根节点入队
    Q->front =0;
    Q->rear =0;
    Q->queue[Q->rear++] = T;

    //2.队列不为空
    while(Q->front != Q->rear)
    {
        temp = Q->queue[(Q->front++)%MAX_QUEUE_SIZE];
        printf("%d ", temp->data);
        if(temp->left)
        {
            if((Q->rear+1)%MAX_QUEUE_SIZE == Q->rear)
            {
                printf("队列满!\n");
                exit(-1);
            }
            Q->queue[(Q->rear++)%MAX_QUEUE_SIZE] = temp->left;
        }
        if(temp->right)
        {
            if((Q->rear+1)%MAX_QUEUE_SIZE == Q->rear)
            {
                printf("队列满!\n");
                exit(-1);
            }
            Q->queue[(Q->rear++)%MAX_QUEUE_SIZE] = temp->right;
        }
    }

}

int main() {
    /**
     * 测试1- 3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9
     * 测试2- 88,70,61,96,120,90,65
     */
    int arr[] = {3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9};
    AVLTree root = NULL;

    int length = sizeof(arr)/ sizeof(arr[0]);
    printf("依次添加: ");
    for(int i=0; i<length; i++)
    {
        printf("%d ", arr[i]);
        root = insert(root, arr[i]);
    }
    printf("\n层遍历树: ");
    levelOrderTraverse(root);
    printf("\n");

    int height = getHeight(root);
    printf("树的高度: %d.\n", height);


    printf("done!\n");
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值