Data structure: AVL balanced tree (c version)

The AVL tree is a very classic example of a balanced tree. Because the ordinary search tree in the process of insertion and deletion may produce a situation where the height of one terminal of the tree is much larger than the other side of the tree, that is, the so-called degeneration to a linked list (search is to find one node), which reduces the search effectiveness.

The AVL balanced tree uses a series of rotations to make the height of the left subtree and the right subtree not much different (<=1), so that the search efficiency will be maintained at a good level.

The method is to
update the height of the parent node after inserting a node to determine whether the height difference between the left and right subtrees of the parent node is 2, if so, perform the corresponding rotation operation (4 types) to reduce the height difference between the left and right subtrees. If not, determine whether the height difference between the left and right subtrees of the parent node's parent is 2, and so on, until the root node (of course it is done in recursion).

Single left-handed, single right-handed, left-right, right-left is to adjust the order between the 3 nodes, the code is as follows, the specific appearance is not drawn, in the process of adjusting the order of these points, we can find that the order of the size of the search tree is still Normally arranged.
That is, the result of the in-order traversal is still 1234567 sorted from small to large.
avl_tree.h

#ifndef _Avltree_h
#define _Avltree_h
#define Max(a,b) ((a)>(b)?(a):(b))

struct AvlNode;
typedef struct AvlNode*Position;
typedef struct AvlNode*AvlTree;
typedef int ElementType ;
Position    Find(ElementType X,AvlTree T);
Position    FindMin(AvlTree T);
Position    FindMax(AvlTree T);
AvlTree MakeEmpty(AvlTree T);
AvlTree Insert(ElementType X,AvlTree T);
void InOrder_2(AvlTree T,int depth);
int  PostOrder_2(AvlTree T,int depth);
void PreOrder_2(AvlTree T,int depth);
void PreOrder(AvlTree T);
void InOrder(AvlTree T);
void PostOrder(AvlTree T);
struct AvlNode
{
    
    
    ElementType Element;
    AvlTree Left;
    AvlTree Right;
    int Height;
};
#endif


avl_tree.c

#include<stdio.h>
#include<stdlib.h>
#include"avl_tree.h"
static  Position    SingleRotateWithLeft(Position K2);
static  Position    DoubleRotateWithLeft(Position   K3);
static  Position    SingleRotateWithRight(Position K2);
static  Position    DoubleRotateWithRight(Position   K3);
static int Height (Position P);
static  Position    SingleRotateWithLeft(Position K2)
{
    
    
    // puts("右旋");

    Position    K1;
    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),K2->Height)+1;
    return  K1;
}
static  Position    DoubleRotateWithLeft(Position   K3)
{
    
    
    //puts("左右");

    K3->Left=SingleRotateWithRight(K3->Left);
    return  SingleRotateWithLeft(K3);
}
static  Position    SingleRotateWithRight(Position K2)
{
    
    
    /* 
        1
    0       2   k2
                4   k1 
                    5
        1
    0       4  k1
            2   5
     */
    // puts("单左旋");
    Position    K1;
    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),K2->Height)+1;
    return  K1;
}
static  Position    DoubleRotateWithRight(Position   K3)
{
    
    
    // puts("右左");
/*     
    //120534
    1                                                       1                                   1               
0        2       k3       --》                   0       2       --》       0           3
            5      k3->right                                3                           2       5   
        3                                                                 5     
                
 */     
  K3->Right=SingleRotateWithLeft(K3->Right);
    return  SingleRotateWithRight(K3);
}
void InOrder(AvlTree T)
{
    
    
    if(T!=NULL){
    
    
        InOrder(T->Left);
        printf("%d\n",T->Element);
        InOrder(T->Right);
    }
}
void PostOrder(AvlTree T)
{
    
    
    if(T!=NULL){
    
    
        PostOrder(T->Left);
        PostOrder(T->Right);
        printf("%d\n",T->Element);
    }
}
void PreOrder_2(AvlTree T,int depth)
{
    
    

    if(T!=NULL){
    
    
        for (int i = 0; i < depth; i++)
            printf("\t");
        printf("%d\n",T->Element);
        PreOrder_2(T->Left,depth+1);
        PreOrder_2(T->Right,depth+1);
    }
}
void InOrder_2(AvlTree T,int depth)
{
    
    

    if(T!=NULL){
    
    
        InOrder_2(T->Left,depth+1);
        for (int i = 0; i < depth; i++)
            printf("\t");
        printf("%d\n",T->Element);
        InOrder_2(T->Right,depth+1);
    }
}
int  PostOrder_2(AvlTree T,int depth)
{
    
    
    int retSize;
    int retSize2;
    if(T!=NULL){
    
    
        retSize=PostOrder_2(T->Left,depth+1);
        retSize2=PostOrder_2(T->Right,depth+1);
        for (int i = 0; i < depth; i++)
            printf("\t");
        printf("%d(%d)\n",T->Element,T->Element+retSize+retSize2);
        return  retSize2+retSize+T->Element;
    }else{
    
    
        return  0;
    }
}
void PreOrder(AvlTree T)
{
    
    
    if(T!=NULL){
    
    
        printf("%d\n",T->Element);
        
        PreOrder(T->Left);
        PreOrder(T->Right);
    }
}

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

static int Height (Position P)
{
    
    
    if(P==NULL)
        return  -1;
    else 
        return  P->Height;
}
Position    Find(ElementType X,AvlTree T)
{
    
    
    if(T==NULL)
        return  NULL;
    if(X<T->Element)
        return  Find(X,T->Left);
    else if(X>T->Element)
        return  Find(X,T->Right);
    else    
        return  T;
}

AvlTree Insert(ElementType X,AvlTree T)
{
    
    
    if(T==NULL){
    
    
        T=malloc(sizeof(struct AvlNode));
        if(T==NULL){
    
    
            fprintf(stderr,"Out of space");
            return NULL;
        }
        else{
    
    
            T->Element=X;
            T->Height=0;
            T->Left=T->Right=NULL;
        }
        //放在左(递归)
    }
    else if(X<T->Element){
    
    
        // printf("%d<%d\n",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;
}

The new traversal function written by myself can print out the effects of preorder traversal (PreOrder_2), inorder traversal (INOrder_2), and postorder traversal (PostOrder_2)

  • Pre-order traversal: middle left and right (maintenance depth, child nodes inherit from parent nodes)
  • Middle order traversal: left, middle and right from small to large
  • Post-order traversal: left and right (maintain the height, the parent node is obtained from the child node) (can be used to count the size of the directory, the size of the child file is added and added to the directory) Here I directly use the number to represent the weight of the node instead File size, and merged into the parent node.

(I think the printed in the middle order is most like a tree)

#include<stdio.h>
#include<stdlib.h>
#include"avl_tree.h"
int main()
{
    
    
    AvlTree T=NULL;
    // int X=1;
    // T=Insert(X,T);
    // X=0;
    // T=Insert(X,T);
    // X=2;
    // T=Insert(X,T);
    // X=5;
    // T=Insert(X,T);
    // X=3;
    // T=Insert(X,T);

    /* 
    
        1                      1                                1
    0   2               0       2                   0           3
            5                           3                       2       5
          3                                   5
    
     */

    for (int i = 0; i < 10; i++)
    {
    
    
        T=Insert((i+1),T);
    }
    
    // if(Find(3,T)->Right){
    
    
    //     printf("r%d\n",Find(3,T)->Right->Element);
    // }
    // if(Find(3,T)->Left){
    
    
    //     printf("l%d\n",Find(3,T)->Left->Element);
    // }
    
     puts("先");
    PreOrder(T);
    
    puts("中");
    InOrder(T);
    puts("后");
    PostOrder(T);
    // puts("后2");
    // PostOrder_2(T,0);
    // PreOrder_2(T,0);
    InOrder_2(T,0);
    MakeEmpty(T);
}
先
4
2
1
3
8
6
5
7
9
10
--------------------------
中
1
2
3
4
5
6
7
8
9
10
--------------------------
后
1
3
2
5
7
6
10
9
8
4
--------------------------
先
4
        2
                1
                3
        8
                6
                        5
                        7
                9
                        10
--------------------------
中
                1
        2
                3
4
                        5
                6
                        7
        8
                9
                        10
--------------------------
后
                1(1)
                3(3)
        2(6)
                        5(5)
                        7(7)
                6(18)
                        10(10)
                9(19)
        8(45)
4(55)
--------------------------

This article does not explain too much, that is, to show you the effect of AVL.
Originally, if you insert 123456789 10, you can imagine how far the tree will grow.
As for the four functions of rotation, it is better to realize it by yourself, and it will always be more useful than reading other people's blogs.

Tucao the people who invented these algorithms back then are really much better than us.

Refer to "Data Structure and Algorithm C Language Description"

Guess you like

Origin blog.csdn.net/adlatereturn/article/details/106845518