C语言二叉平衡搜索树

AVL(二叉平衡搜索树)的概念和思路

  • 任意一个节点 左子树高度 - 右子树高度 <= 1
  • 要想让BST保持平衡,必须在每一次插入、删除之后,检查是否其左右子树满足平衡的定义
  • 如果不满足,就做“旋转”操作,使其恢复平衡
  • 加入以上平衡策略算法后的BST,称为AVL,AVL是一种绝对平衡的二叉树

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

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

typedef struct node_tree
{
    int data;
    struct node_tree *l,*r;
    int height;
}tree,*linktree;

int height(linktree root)
{
    if(root == NULL)
        return 0;

    return root->height;
}

linktree new_node(int num)
{
    linktree ne = (linktree)malloc(sizeof(tree));
    if(ne != NULL)
    {
        ne->data = num;
        ne->l = ne->r = NULL;
    }

    return ne;
}

linktree left_rotate(linktree root)
{
    if(root == NULL)
        return NULL;

    linktree tmp = root->r;
    root->r = tmp->l;
    tmp->l = root;

    root->height = MAX(height(root->l), height(root->r)) + 1;
    tmp->height = MAX(height(tmp->l), height(tmp->r)) + 1;

    return tmp;
}

linktree right_rotate(linktree root)
{
    if(root == NULL)
        return NULL;

    linktree tmp = root->l;
    root->l = tmp->r;
    tmp->r = root;

    root->height = MAX(height(root->l), height(root->r)) + 1;
    tmp->height = MAX(height(tmp->l), height(tmp->r)) + 1;

    return tmp;
}

linktree left_right_rotate(linktree root)
{
    root->l = left_rotate(root->l);
    return right_rotate(root);
}

linktree right_left_rotate(linktree root)
{
    root->r = right_rotate(root->r);
    return left_rotate(root);
}

linktree insert_tree(linktree root, linktree ne)
{
    if(root == NULL)
        return ne;

    if(ne->data < root->data)
        root->l = insert_tree(root->l, ne);
    else
        root->r = insert_tree(root->r, ne);

    //插入过后判断树的平衡性

    //左子树不平衡
    if(height(root->l) - height(root->r) >= 2)
    {
        //左左不平衡
        if(ne->data < root->l->data)
        {
            root = right_rotate(root);
        }
        //左右不平衡
        else if(ne->data > root->l->data)
        {
            root = left_right_rotate(root);
        }
    }
    //右子树不平衡
    if(height(root->r) - height(root->l) >= 2)
    {

        if(ne->data > root->r->data)
        {
            root = left_rotate(root);
        }
        else if(ne->data < root->r->data)
        {
            root = right_left_rotate(root);
        }
    }

    root->height = MAX((height(root->l)), (height(root->r))) + 1;

    return root;
}

linktree remove_tree(linktree root, int num)
{
    if(root == NULL)
        return NULL;

    if(num < root->data)
        root->l = remove_tree(root->l, num);
    else if(num > root->data)
        root->r = remove_tree(root->r, num);
    else
    {
        linktree tmp;
        if(root->l != NULL)
        {
            for(tmp = root->l; tmp->r != NULL; tmp = tmp->r);
            root->data = tmp->data;
            root->l = remove_tree(root->l, tmp->data);
        }
        else if(root->r != NULL)
        {
            for(tmp = root->r; tmp->l != NULL; tmp = tmp->l);
            root->data = tmp->data;
            root->r = remove_tree(root->r, tmp->data);
        }
        else
        {
            free(root);
            return NULL;
        }
    }
    
    //删除节点后,判断平衡性
        //左子树不平衡
    if(height(root->l) - height(root->r) >= 2)
    {
        //左左不平衡
        if(height(root->l->l) > height(root->l->r))
        {
            root = right_rotate(root);
        }
        //左右不平衡
        else
        {
            root = left_right_rotate(root);
        }
    }
    //右子树不平衡
    if(height(root->r) - height(root->l) >= 2)
    {

        if(height(root->r->r) > height(root->r>l))
        {
            root = left_rotate(root);
        } 
        else
        {
            root = right_left_rotate(root);
        }
    }

    root->height = MAX((height(root->l)), (height(root->r))) + 1;
    return root;
}

int main()
{
    linktree root = NULL;

    int n;
    while(1)
    {
        scanf("%d", &n);
        if(n == 0)
            break;

        linktree ne = new_node(n);
        root = insert_tree(root, ne);
    }

    while(1)
    {
        scanf("%d", &n);
        if(n == 0)
            break;

        root = remove_tree(root, n);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值