数据结构与算法分析(C语言描述) -- 学习&理解 AVL树

1、AVL树概念

AVL树是带有一种平衡条件的二叉查找树,树的深度为O(logN);左右子树看起来相对平衡,一颗不平衡的树可能意味着树的操作会大于O(logN),AVL树就是能很好的保持在O(logN)的一种算法;

性质1:左右子树深度最多差1的二叉查找树;

性质2:左右子树都是平衡二叉树;

除叶子结点以外,其他结点均有两个children的树称为完全二叉树或理想平衡树,或者也可以说左右子树深度相同,但是实现的难度较大;当然也是AVL树;

2、AVL树的操作

对于普通的二叉查找树,可能会因为删除或添加的频繁操作而导致一颗树越来越不平衡;而AVL树是对这些操作之后的树进行一些修正生成的树,这些修正被称为旋转操作,一般可以分为四种情况:

情况1:插入节点位于X的左子节点的左子树--左左;

情况2:插入节点位于X的左子节点的右子树--左右;

情况3:插入节点位于X的右子节点的左子树--右左;

情况4:插入节点位于X的右子节点的右子树--右右。

情况1和情况4是镜像的,只需单旋转一次操作即可完成平衡操作;情况2和情况3是镜像的,需要双旋转两次操作才能完成平衡操作;

附几张图解释一下;

左左单旋转:在18的左结点14的左子树插入11,打破了平衡性;将18作为14的右子树,14的右子树作为18的左子树;

左右双旋转:在18的左结点的右子树插入15,打破了平衡性;将14和16做左旋转,再将16和18做右旋转;

3、AVL树代码示例

数据结构描述

struct AvlTree
{
	int element;
	struct AvlTree *left;
	struct AvlTree *right;
	int height;
};

测试代码:

#include 
#include 


struct AvlTree
{
    int element;
    struct AvlTree *left;
    struct AvlTree *right;
    int height;
};

int printf_tree_inorder_traversal(struct AvlTree *tree)
{
    if (tree == NULL)
    {
        return 0;
    }  

    if (tree->left != NULL)
    {
        printf_tree_inorder_traversal(tree->left);
    }

    printf("%d:%dh ", tree->element, tree->height);

    if (tree->right != NULL)
    {
        printf_tree_inorder_traversal(tree->right);
    }

    return 0;
}

int get_tree_height(struct AvlTree *tree)
{
    if (tree == NULL)
    {
        return -1;
    }
    else
    {
        return tree->height;
	}
}

int get_max_tree_height(struct AvlTree *tree)
{
    int letf_height, right_height;

    letf_height = get_tree_height(tree->left);
    right_height = get_tree_height(tree->right);

    return (letf_height > right_height) ? letf_height : right_height;
}

struct AvlTree *make_empty(struct AvlTree *tree)
{
    if (tree != NULL)
    {
        make_empty(tree->left);
        make_empty(tree->right);
        free(tree);
    }

    return NULL;
}

/* 0 means right, 1 means left */
static struct AvlTree *single_rotate(struct AvlTree *tree, int operate)
{
    struct AvlTree *tree_tmp;

    //printf("tree->element %d get in single rotate\n", tree->element);
    if (operate == 0)
    {
        tree_tmp = tree->left;
        tree->left = tree_tmp->right;
        tree_tmp->right = tree;

        tree_tmp->height = get_max_tree_height(tree_tmp) + 1;
        tree->height = get_max_tree_height(tree) + 1;
    }
    else if (operate == 1)
    {
        tree_tmp = tree->right;
        tree->right = tree_tmp->left;
        tree_tmp->left = tree;

        tree_tmp->height = get_max_tree_height(tree_tmp) + 1;
        tree->height = get_max_tree_height(tree) + 1;
    }
    else
    {
        printf("not support this %d operate !\n", operate);
    }

    return tree_tmp;
}

struct AvlTree *double_rotate(struct AvlTree *tree, int operate)
{
    //printf("tree->element %d get in double rotate\n", tree->element);
    if (operate == 0)
    {
        tree->right = single_rotate(tree->right, 0);
        return single_rotate(tree, 1);
    }
    else if (operate == 1)
    {
        tree->left = single_rotate(tree->left, 1);
        return single_rotate(tree, 0);
    }

    return tree;
}

/* 0 means right, 1 means left */
struct AvlTree *insert_node(struct AvlTree *tree, int element)
{
    if (tree == NULL)
    {
        tree = (struct AvlTree *)malloc(sizeof(struct AvlTree));
        if (tree == NULL)
        {
            printf("malloc failed!\n");
            return NULL;
        }
        else
        {
            tree->element = element;
            tree->left = NULL;
            tree->right = NULL;
            tree->height = 0;
            printf("add element : %d success\n", element);
        }
    }
    else if (element < tree->element)
    {
        //printf("element %d < tree->element %d\n", element, tree->element);
        tree->left = insert_node(tree->left, element);

        if ((get_tree_height(tree->left) - get_tree_height(tree->right)) == 2)
        {
            if (tree->left->element > element)
            {
                tree = single_rotate(tree, 0);
            }
            else
            {
                tree = double_rotate(tree, 1);
            }
        }
    }
    else if (element > tree->element)
    {
        //printf("element %d > tree->element %d\n", element, tree->element);
        tree->right = insert_node(tree->right, element);

        if ((get_tree_height(tree->right) - get_tree_height(tree->left)) == 2)
        {
            if (tree->right->element < element)
            {
                tree = single_rotate(tree, 1);
            }
            else
            {
                tree = double_rotate(tree, 0);
            }
        }
    }

    tree->height = get_max_tree_height(tree) + 1;

    printf_tree_inorder_traversal(tree);
    printf("\n");

    return tree;
}

struct AvlTree *find_node(struct AvlTree *tree, int element)
{
    if (tree == NULL)
    {
        printf("can't find element %d\n", element);
        return NULL;
    }
    else if (element < tree->element)
    {
        //printf("element %d < tree->element %d\n", element, tree->element);
        return find_node(tree->left, element);
    }
    else if (element > tree->element)
    {
        //printf("element %d > tree->element %d\n", element, tree->element);
        return find_node(tree->right, element);
    }
    else if (element == tree->element)
    {
        printf("find element : %d success\n", element);
    }

    return tree;
}

struct AvlTree *find_min_node(struct AvlTree *tree)
{
    if (tree == NULL)
    {
        printf("find min node Tree is NULL!\n");
        return NULL;
    }

    if (tree->left == NULL)
    {				
        return tree;	
    }
    else
    {
        return find_min_node(tree->left);
    }
}


struct AvlTree *delete_node(struct AvlTree *tree, int element)
{
    struct AvlTree *tree_tmp;

    if (tree == NULL)
    {		
        printf("Tree is NULL\n");	
        return NULL;	
    }
    else if (element < tree->element)
    {
        //printf("element %d < tree->element %d\n", element, tree->element);
        tree->left = delete_node(tree->left, element);

        if ((get_tree_height(tree->left) - get_tree_height(tree->right)) == 2)
        {
            if (tree->left->element > element)
            {
                tree = single_rotate(tree, 0);
            }
            else
            {
                tree = double_rotate(tree, 1);
            }
        }
    }
    else if (element > tree->element)
    {
        //printf("element %d > tree->element %d\n", element, tree->element);
        tree->right = delete_node(tree->right, element);

        if ((get_tree_height(tree->right) - get_tree_height(tree->left)) == 2)
        {
            if (tree->right->element < element)
            {
                tree = single_rotate(tree, 1);
            }
            else
            {
                tree = double_rotate(tree, 0);
            }
        }
    }
    else
    {
        //two children
        if (tree->right != NULL && tree->left != NULL)
        {
            tree_tmp = find_min_node(tree->right);
            tree->element = tree_tmp->element;
            tree->right = delete_node(tree->right, tree->element);
        }
        //one or zero children
        else
        {
            tree_tmp = tree;
            if (tree->right == NULL)
            {
                tree = tree->left;
            }
            else if (tree->left == NULL)
            {
                tree = tree->right;
            }

            free(tree_tmp);
            printf("delete element %d success\n", tree_tmp->element);

        }
    }

    if (tree)
    tree->height = get_max_tree_height(tree) + 1;

    return tree;
}

int main(void)
{
    struct AvlTree tree;
    struct AvlTree *tmp_node = NULL;

    int num[10] = {30, 4, 31, 10, 18, 16, 28, 15, 12, 14};
    int i;

    tree.element = 5;
    tree.left = NULL;
    tree.right = NULL;

    tmp_node = &tree;

    printf("root element : %d\n", tree.element);
    for (i = 0; i < 10; i++)
    {      
        tmp_node = insert_node(tmp_node, num[i]);
        printf("\n");
    }

    printf_tree_inorder_traversal(tmp_node);
    printf("\n");

    delete_node(tmp_node, 18);

    printf_tree_inorder_traversal(tmp_node);
    printf("\n");

    return 0;   
}

执行结果:

root element : 5
add element : 30 success
30:0h
5:1h 30:0h

add element : 4 success
4:0h
4:0h 5:1h 30:0h

add element : 31 success
31:0h
30:1h 31:0h
4:0h 5:2h 30:1h 31:0h

add element : 10 success
10:0h
10:0h 30:1h 31:0h
4:0h 5:2h 10:0h 30:1h 31:0h

add element : 18 success
18:0h
10:1h 18:0h
10:1h 18:0h 30:2h 31:0h
4:0h 5:1h 10:2h 18:0h 30:1h 31:0h

add element : 16 success
16:0h
16:0h 18:1h
16:0h 18:1h 30:2h 31:0h
4:0h 5:1h 10:3h 16:0h 18:1h 30:2h 31:0h

add element : 28 success
28:0h
16:0h 18:1h 28:0h
16:0h 18:1h 28:0h 30:2h 31:0h
4:0h 5:1h 10:3h 16:0h 18:1h 28:0h 30:2h 31:0h

add element : 15 success
15:0h
15:0h 16:1h
15:0h 16:1h 18:2h 28:0h
15:0h 16:1h 18:2h 28:0h 30:1h 31:0h
4:0h 5:1h 10:3h 15:0h 16:1h 18:2h 28:0h 30:1h 31:0h

add element : 12 success
12:0h
12:0h 15:1h
12:0h 15:1h 16:0h
12:0h 15:1h 16:0h 18:2h 28:0h 30:1h 31:0h
4:0h 5:1h 10:3h 12:0h 15:1h 16:0h 18:2h 28:0h 30:1h 31:0h

add element : 14 success
14:0h
12:1h 14:0h
12:1h 14:0h 15:2h 16:0h
12:1h 14:0h 15:2h 16:0h 18:3h 28:0h 30:1h 31:0h
4:0h 5:1h 10:2h 12:1h 14:0h 15:3h 16:0h 18:2h 28:0h 30:1h 31:0h

4:0h 5:1h 10:2h 12:1h 14:0h 15:3h 16:0h 18:2h 28:0h 30:1h 31:0h
delete element 28 success
4:0h 5:1h 10:2h 12:1h 14:0h 15:3h 16:0h 28:2h 30:1h 31:0h

 

你可能感兴趣的:(数据结构与算法分析)