Equilibrium Binary Tree-Implementation of AVL Tree

Equilibrium Binary Tree-Implementation of AVL Tree

Reproduced from http://blog.chinaunix.net/uid-24948645-id-3913917.html

Classification: data structure 2013-09-05 10:44 48 person reading comment(0) Collection Report
AVL treebalanced binary treedata structure

AVL tree is the first self-balancing binary search algorithm invented, and it is a kind of balanced binary tree. In AVL, the maximum height difference between the two son subtrees of any node is 1, so it is also called a height balance tree. Finding, inserting and deleting are O(log n) in average and worst case. Adding and deleting a tree may require one or more tree rotations to balance the tree.

Suppose that the node that needs to be rebalanced during the construction of AVL tree is called a. Since there are at most two sons at any node, the height difference between the two subtrees at point alpha is 2 when the height is unbalanced. This imbalance may occur in the following four situations:

1) Insert the left subtree of alpha's left son once (left-handed)

Among them, D is the newly inserted node and K2 is the unbalanced node. K1 and K2 need to be left-handed adjusted, that is, K1 as the root, K2 as the left subtree of K1, and K1 as the right subtree of K2. As shown in the following figure

Left-handed transformation

The code is as follows:

  1. static Position SingleRotateWithLeft(Position K2)  
  2. {  
  3.     Position K1;  
  4.   
  5.     K1 = K2->Left;  
  6.     K2->Left = K1->Right;  
  7.     K1->Right = K2;  
  8.     //Update node height  
  9.     return K1;  
  10. }  

2) Insert the right subtree of alpha's left son once (right-left double rotation)

Left and right double rotation here refers to the need to rotate when inserting the right subtree of alpha's left son. Firstly, K1 and K2 are rotated right (similar to the fourth case), then K3 and K2 are rotated left, eventually achieving balance. As shown in the following figure

Do a right-handed turnMake a left-handed turn

The code is as follows:

  1. static Position DoubleRotateWithLeft(Position K3)  
  2. {  
  3.     K3->Left = SingleRotateWithRight(K3->Left);  
  4.     return SingleRotateWithLeft(K3);  
  5. }  

3) Insert the left subtree of alpha's right son once (right-left double-rotation)

Right-left double-rotation: first, K1 and K2 are left-handed, then K2 and K3 are right-handed, and finally achieve balance. As shown in the following figure

Make a left-handed turnDo a right-handed turn

The code is as follows:

  1. static Position DoubleRotateWithRight(Position K3)  
  2. {  
  3.     K3->Right = SingleRotateWithLeft(K3->Right);  
  4.     return SingleRotateWithRight(K3);  
  5. }  

4) Insert the right subtree of alpha's right son once (right-handed)

Change the right subtree of K2 to the left subtree of K1, and the left subtree of K1 to the right subtree of K2, as shown in the following figure

Dextral rotation

The code is as follows:

  1. static Position SingleRotateWithRight(Position K2)  
  2. {  
  3.     Position K1;  
  4.   
  5.     K1 = K2->Right;  
  6.     K2->Right = K1->Left;  
  7.     K1->Left = K2;  
  8.     //Update node height  
  9.     return K1;  
  10. }  
The four rotations of AVL tree are described above, and the next one is to implement AVL tree. The implementation of AVL tree is similar to that of the binary search tree mentioned in the previous chapter. The difference is that when inserting and deleting nodes, the tree needs to be adjusted to meet the balance conditions.

avltree.h gives the function declaration

  1. typedef int ElementType;  
  2.   
  3. #ifndef AVLTREE_H  
  4. #define AVLTREE_H  
  5.   
  6. struct TreeNode  
  7. {  
  8.     ElementType Element;  
  9.     int Height;  
  10.     struct TreeNode *Left;  
  11.     struct TreeNode *Right;  
  12. };  
  13.   
  14. typedef struct TreeNode *AvlTree;  
  15. typedef struct TreeNode *Position;  
  16.   
  17. AvlTree MakeEmpty(AvlTree T);  
  18. AvlTree Insert(ElementType X, AvlTree T);  
  19. Position Find(ElementType X ,AvlTree T);  
  20. Position FindMax(AvlTree T);  
  21. Position FindMin(AvlTree T);  
  22.   
  23. #endif  
Implementation of avltree.c Function
  1. #include "fatal.h"  
  2. #include "avltree.h"  
  3.   
  4. AvlTree MakeEmpty(AvlTree T)  
  5. {  
  6.     if(T != NULL)  
  7.     {  
  8.         MakeEmpty(T->Left);  
  9.         MakeEmpty(T->Right);  
  10.         free(T);  
  11.     }  
  12.     return NULL;  
  13. }  
  14.   
  15. static int Height(Position P)  
  16. {  
  17.     if(P == NULL)  
  18.         return -1;  
  19.     else  
  20.         return P->Height;  
  21. }  
  22.   
  23. static int Max(int Lhs, int Rhs)  
  24. {  
  25.     return Lhs > Rhs ? Lhs : Rhs;  
  26. }  
  27.   
  28. static Position SingleRotateWithLeft(Position K2)  
  29. {  
  30.     Position K1;  
  31.   
  32.     K1 = K2->Left;  
  33.     K2->Left = K1->Right;  
  34.     K1->Right = K2;  
  35.   
  36.     K1->Height = Max(Height(K1->Left), Height(K1->Right)) + 1;  
  37.     K2->Height = Max(Height(K2->Left), Height(K2->Right)) + 1;  
  38.   
  39.     return K1;  
  40. }  
  41.   
  42. static Position SingleRotateWithRight(Position K2)  
  43. {  
  44.     Position K1;  
  45.   
  46.     K1 = K2->Right;  
  47.     K2->Right = K1->Left;  
  48.     K1->Left = K2;  
  49.   
  50.     K1->Height = Max(Height(K1->Left), Height(K1->Right)) + 1;  
  51.     K2->Height = Max(Height(K2->Left), Height(K2->Right)) + 1;  
  52.   
  53.     return K1;  
  54. }  
  55.   
  56. static Position DoubleRotateWithLeft(Position K3)  
  57. {  
  58.     K3->Left = SingleRotateWithRight(K3->Left);  
  59.     return SingleRotateWithLeft(K3);  
  60. }  
  61.   
  62. static Position DoubleRotateWithRight(Position K3)  
  63. {  
  64.     K3->Right = SingleRotateWithLeft(K3->Right);  
  65.     return SingleRotateWithRight(K3);  
  66. }  
  67.   
  68. AvlTree Insert(ElementType X, AvlTree T)  
  69. {  
  70.     if(T == NULL)  
  71.     {  
  72.         T = (Position)malloc(sizeof(struct TreeNode));  
  73.         if(T == NULL)  
  74.             FatalError("Out of space");  
  75.         T->Element = X;  
  76.         T->Height = 0;  
  77.         T->Left = T->Right = NULL;  
  78.     }  
  79.     else if(X < T->Element)//Insert a new node into the left subtree  
  80.     {  
  81.         T->Left = Insert(X, T->Left);  
  82.         if(Height(T->Left) - Height(T->Right) == 2)//The left subtree inserts nodes, so the height of the left subtree is higher than that of the right subtree.  
  83.         {  
  84.             if(X < T->Left->Element)//To insert the left subtree of alpha's left son once, we need to turn left.  
  85.                 T = SingleRotateWithLeft(T);  
  86.             else //To insert the right subtree of alpha's left son once, double rotation is required.  
  87.                 T = DoubleRotateWithLeft(T);  
  88.         }  
  89.     }  
  90.     else if(X > T->Element)//Insert a new node into the right subtree  
  91.     {  
  92.         T->Right = Insert(X, T->Right);  
  93.         if(Height(T->Right) - Height(T->Left) == 2)//Because the right subtree inserts new nodes, the height of the right subtree is higher than that of the left subtree.  
  94.         {  
  95.             if(X > T->Right->Element)//To insert the right subtree of alpha's right son once, it needs to be right-handed.  
  96.                 T = SingleRotateWithRight(T);  
  97.             else//To insert the left subtree of alpha's right son once, double rotation is required.  
  98.                 T = DoubleRotateWithRight(T);  
  99.         }  
  100.     }  
  101.     T->Height = Max(Height(T->Left), Height(T->Right)) + 1;  
  102.     return T;  
  103. }  
  104.   
  105. Position Find(ElementType X, AvlTree T)  
  106. {  
  107.     if(T == NULL)  
  108.         return NULL;  
  109.     if(X < T->Element)  
  110.         return Find(X, T->Left);  
  111.     else if(X > T->Element)  
  112.         return Find(X, T->Right);  
  113.     else  
  114.         return T;  
  115. }  
  116.   
  117. Position FindMin(AvlTree T)  
  118. {  
  119.     if(T == NULL)  
  120.         return NULL;  
  121.     else if(T->Left == NULL)  
  122.         return T;  
  123.     else  
  124.         return FindMin(T->Left);   
  125. }  
  126.   
  127. Position FindMax(AvlTree T)  
  128. {  
  129.     if(T == NULL)  
  130.         return NULL;  
  131.     else if(T->Right == NULL)  
  132.         return T;  
  133.     else  
  134.         return FindMax(T->Right);  
  135. }  

Implementation of Tesavl.c Testing AVL Tree

  1. #include "avltree.h"  
  2. #include   
  3. #include   
  4.   
  5. void InOrder(AvlTree T)  
  6. {  
  7.     if(T != NULL)  
  8.     {  
  9.         InOrder(T->Left);  
  10.         printf("%d ", T->Element);  
  11.         InOrder(T->Right);  
  12.     }  
  13. }  
  14.   
  15. void PreOrder(AvlTree T)  
  16. {  
  17.     if(T != NULL)  
  18.     {  
  19.         printf("%d ", T->Element);  
  20.         PreOrder(T->Left);  
  21.         PreOrder(T->Right);  
  22.     }  
  23. }  
  24.   
  25. int main(void)  
  26. {  
  27.     AvlTree T;  
  28.     Position P;  
  29.     int i;  
  30.   
  31.     T = MakeEmpty(NULL);  
  32.     for(i = 1; i <= 7; i++)  
  33.         T = Insert(i, T);  
  34.     for(i = 16; i >= 10; i--)  
  35.         T = Insert(i, T);  
  36.     T = Insert(8, T);  
  37.     T = Insert(9, T);  
  38.     printf("Root: %d\n", T->Element);  
  39.     printf("InOrder:  ");  
  40.     InOrder(T);  
  41.     printf("\nPreOrder: ");  
  42.     PreOrder(T);  
  43.     putchar('\n');  
  44.     system("Pause");  
  45.   
  46.     return 0;  
  47. }  

Test: First insert 1 to 7, then insert 16 to 10, and finally insert 8 and 9. The AVL tree should look like the following

The test results are shown in the following figure.

  1.   
  2.   
  3.   
  4.   
  5.   
  6.   
  7.   
Share to:

Posted by ubunken on Sat, 23 Mar 2019 13:21:52 -0700