AVL(Adelson-Velskii和Landis)树 - C语言实现(摘自数据结构与算法分析 C语言描述)

来源:互联网 发布:人工智能程序发展 编辑:程序博客网 时间:2024/04/30 05:37

一、概述

        AVL(Adelson-Velskii和Landis)树是带有平衡条件的二叉查找树。一颗AVL树是其每个节点的左子树和右子树的高度最多差1的二叉查找树(空树的高度定义为-1),如图1所示,只有左边的二叉查找树是AVL树。


图1 两颗二叉查找树,只有左边的树是AVL树

二、实现

        AVL树中的每个节点都有一个平衡因子(Balance Factor,以下用BF表示),它表示这个节点的左、右子树的高度差,也就是左子树的高度减去右子树的高度的值。AVL树上所有节点的BF值只可能是-1、0和1.反之,只要二叉查找数上一个节点的BF的绝对值大于1,则该二叉树就不是平衡二叉树。
        如何构造一颗平衡二叉树呢?动态地调整二叉查找数平衡的方法为:每插入一个节点后,首先检查是否破坏了树的平衡性,如果因插入节点而破坏了二叉查找树的平衡,则找出离插入点最近的不平衡节点,然后将该不平衡节点为根的子树进行旋转操作,我们称该不平衡节点为旋转根,让我们把必须重新平衡的节点叫做α,以该旋转根为根的子树称为最小不平衡的子树,失衡状态可归纳为4种,他们对应着4种旋转类型:
1. 对α的左儿子的左子树进行一次插入(LL);
2. 对α的左儿子的右子树进行一次插入(LR);
3. 对α的右儿子的左子树进行一次插入(RL);
4. 对α的右儿子的右子树进行一次插入(RR);
        情形1和4是关于α点的镜像对称,而2和3是关于α点的镜像对称。因此,理论上只有两种情况,当然从编程的角度来看还是四种情形。
        第一种情况是插入发生在“外边”的情况(即左-左的情况或右-右的情况),该情况通过对树的一次单旋转(single rotation,如图2)而完成调整;第二种情况是插入发生在“内部”的情形(即左-右的情况或右-左的情况),该情况通过稍微复杂些的双旋转(double rotation,如图3)来处理。

图2 单旋转(LL型)

图3 双旋转(LR型)
        旋转运算的实质,把树做任何一种旋转(LL、LR、RL、RR):
◎ 新树保持了原来的中序周游顺序;
◎ 旋转处理器中仅需改变少数指针;
◎ 而且新的子树高度为h+2,保持插入前子树的高度不变; 
◎ 原来二叉树在α节点上的其余部分(如还有的话)总是保持平衡的。
        总结:除几种情形外,编程的细节是相当简单的。为将关键字是X的一个新节点插入到一颗AVL树T中去,我们递归地将X插入到T的相应的子树(称为TLR)中。如果的高度不变,那么插入完成。否则,如果在T中出现高度不平衡,那么我们根据X以及T和中的关键字作适当的但旋转或双旋转,更新这些高度(并解决好与树的其余部分的连接),从而完成插入。
文件名:avltree.h
[cpp] view plaincopyprint?
  1. #ifndef _AvlTree_H  
  2.   
  3. typedef int ElementType;  
  4.   
  5. struct AvlNode;  
  6. typedef struct AvlNode *Position;  
  7. typedef struct AvlNode *AvlTree;  
  8.   
  9. AvlTree MakeEmpty( AvlTree T );  
  10. Position Find( ElementType X, AvlTree T );  
  11. Position FindMin( AvlTree T );  
  12. Position FindMax( AvlTree T );  
  13. AvlTree Insert( ElementType X, AvlTree T );  
  14. AvlTree Delete( ElementType X, AvlTree T );  
  15. ElementType Retrieve( Position P );  
  16.   
  17. static Position SingleRotateWithRight( Position K1 );  
  18. static Position SingleRotateWithLeft( Position K2 );  
  19. static Position DoubleRotateWithLeft( Position K3 );  
  20. static Position DoubleRotateWithRight( Position K4 );  
  21.   
  22. ElementType Max( ElementType a, ElementType b );  
  23.   
  24. void PrintElement( AvlTree T );  
  25. void PreOrder( AvlTree T );  
  26. void InOrder( AvlTree T );  
  27. void PostOrder( AvlTree T );  
  28.   
  29. #endif /* _AvlTree_H */  

文件名:avltree.c
[cpp] view plaincopyprint?
  1. #include "avltree.h"  
  2. #include "fatal.h"  
  3.   
  4. struct AvlNode  
  5. {  
  6.     ElementType Element;  
  7.     AvlTree Left;  
  8.     AvlTree Right;  
  9.     int Height;  
  10. };  
  11.   
  12. ElementType  
  13. Max( ElementType a, ElementType b )  
  14. {  
  15.     return (a > b ? a : b);  
  16. }  
  17.   
  18. static int  
  19. Height( Position P )  
  20. {  
  21.     if ( P == NULL )  
  22.         return -1;  
  23.     else  
  24.         return P->Height;  
  25. }  
  26.   
  27. AvlTree  
  28. MakeEmpty( AvlTree T )  
  29. {  
  30.     if ( T != NULL )  
  31.     {  
  32.         MakeEmpty( T->Left );  
  33.         MakeEmpty( T->Right );  
  34.         free( T );  
  35.     }  
  36.     return NULL;  
  37. }  
  38. Position  
  39. Find( ElementType X, AvlTree T )  
  40. {  
  41.     if( T == NULL )  
  42.         return NULL;  
  43.     if( X < T->Element )  
  44.         return Find( X, T->Left );  
  45.     else  
  46.         if( X > T->Element )  
  47.             return Find( X, T->Right );  
  48.         else  
  49.             return T;  
  50. }  
  51.   
  52. Position  
  53. FindMin( AvlTree T )  
  54. {  
  55.     if( T == NULL )  
  56.         return NULL;  
  57.     else  
  58.         if( T->Left == NULL )  
  59.             return T;  
  60.         else  
  61.             return FindMin( T->Left );  
  62. }  
  63.   
  64. Position  
  65. FindMax( AvlTree T )  
  66. {  
  67.     if( T != NULL )  
  68.         while( T->Right != NULL )  
  69.             T = T->Right;  
  70.   
  71.     return T;  
  72. }  
  73.   
  74. AvlTree  
  75. Delete( ElementType X, AvlTree T )  
  76. {  
  77.     printf( "Sorry; delete is unimplemented; %d remains\n", X );  
  78.     return T;  
  79. }  
  80.   
  81. ElementType  
  82. Retrieve( Position P )  
  83. {  
  84.     return P->Element;  
  85. }  
  86.   
  87. AvlTree  
  88. Insert ( ElementType X, AvlTree T )  
  89. {  
  90.     if ( T == NULL )  
  91.     {  
  92.         /* Create and return a one-node tree */  
  93.         T = malloc( sizeofstruct AvlNode ) );  
  94.         if ( T == NULL )  
  95.             FatalError( "Out of space!!!" );  
  96.         else  
  97.         {  
  98.             T->Element = X; T->Height = 0;  
  99.             T->Left = T->Right = NULL;  
  100.         }  
  101.     }  
  102.     else  
  103.     if ( X < T->Element )  
  104.     {  
  105.         T->Left = Insert( X, T->Left );  
  106.         if ( Height( T->Left ) - Height( T->Right ) == 2 )  
  107.             if ( X < T->Left->Element )  
  108.                 T = SingleRotateWithLeft( T );  
  109.             else  
  110.                 T = DoubleRotateWithLeft( T );  
  111.     }  
  112.     else  
  113.     if ( X > T->Element )  
  114.     {  
  115.         T->Right = Insert( X, T->Right );  
  116.         if ( Height( T->Right ) - Height( T->Left ) == 2 )  
  117.             if ( X > T->Right->Element )  
  118.                 T = SingleRotateWithRight( T );  
  119.             else  
  120.                 T = DoubleRotateWithRight( T );  
  121.     }  
  122.     /* Else X is in the tree already;we'll do nothing */  
  123.     T->Height = Max( Height( T->Left ), Height( T->Right ) ) + 1;  
  124.     return T;  
  125. }  
  126.   
  127. /* This function can be called only if K2 has a left child */  
  128. /* Perform a rotate between a node(K2) and its left child */  
  129. /* Update heights, then return new root */  
  130. static Position  
  131. SingleRotateWithLeft( Position K2 )  
  132. {  
  133.     Position K1;  
  134.   
  135.     K1 = K2->Left;  
  136.     K2->Left = K1->Right;  
  137.     K1->Right = K2;  
  138.   
  139.     K2->Height = Max( Height( K2->Left ),   
  140.         Height( K2->Right ) ) +1;  
  141.     K1->Height = Max( Height( K1->Left ),   
  142.         K2->Height ) +1;  
  143.   
  144.     return K1; /* New root */  
  145. }  
  146.   
  147. /* This function can be called only if K1 has a right child */  
  148. /* Perform a rotate between a node(K1) and its right child */  
  149. /* Update heights, then return new root */  
  150. static Position  
  151. SingleRotateWithRight( Position K1 )  
  152. {  
  153.     Position K2;  
  154.   
  155.     K2 = K1->Right;  
  156.     K1->Right = K2->Left;  
  157.     K2->Left = K1;  
  158.   
  159.     K1->Height = Max( Height( K1->Left ),   
  160.         Height( K1->Right ) ) + 1;  
  161.     K2->Height = Max( Height( K2->Right ),   
  162.         K1->Height ) + 1;  
  163.   
  164.     return K2; /* New root */  
  165. }  
  166.   
  167. /* This function can be called only if K3 has a left */  
  168. /* child and K3's left child has a right child */  
  169. /* Do the left-right double rotation */  
  170. /* Update heights,then return new root */  
  171. static Position  
  172. DoubleRotateWithLeft( Position K3 )  
  173. {  
  174.     /* Rotate between K1 and K2 */  
  175.     K3->Left = SingleRotateWithRight( K3->Left );  
  176.   
  177.     /* Rotate between K3 and K2 */  
  178.     return SingleRotateWithLeft( K3 );  
  179. }  
  180.   
  181. /* This function can be called only if K1 has a right */  
  182. /* child and K1's right child has a left child */  
  183. /* Do the left-right double rotation */  
  184. /* Update heights,then return new root */  
  185. static Position  
  186. DoubleRotateWithRight( Position K1 )  
  187. {  
  188.     /* Rotate between K3 and K2 */  
  189.     K1->Right = SingleRotateWithLeft( K1->Right );  
  190.   
  191.     /* Rotate between K1 and K2 */  
  192.     return SingleRotateWithRight( K1 );  
  193. }  
  194.   
  195. void  
  196. PrintElement( AvlTree T )  
  197. {  
  198.     printf( "%3d ", Retrieve( T ) );  
  199. }  
  200.   
  201. void  
  202. PreOrder( AvlTree T )  
  203. {  
  204.     if (T != NULL )  
  205.     {  
  206.         PrintElement( T );  
  207.         PreOrder( T->Left );  
  208.         PreOrder( T->Right );  
  209.     }     
  210. }  
  211.   
  212. void   
  213. InOrder( AvlTree T )  
  214. {  
  215.     if (T != NULL )  
  216.     {  
  217.         InOrder( T->Left );  
  218.         PrintElement( T );  
  219.         InOrder( T->Right );  
  220.     }  
  221. }  
  222.   
  223. void  
  224. PostOrder( AvlTree T )  
  225. {  
  226.     if ( T != NULL )  
  227.     {  
  228.         PostOrder( T->Left );  
  229.         PostOrder( T->Right );  
  230.         PrintElement( T );  
  231.     }  
  232. }  

文件名:main.c
[cpp] view plaincopyprint?
  1. #include "avltree.h"  
  2. #include <stdio.h>  
  3.   
  4. int main()  
  5. {  
  6.     AvlTree T = NULL;  
  7.     int i, n;  
  8.     ElementType tmp;  
  9.     printf( "Number of Elements:" );  
  10.     scanf( "%d", &n );  
  11.     for ( i = 0; i < n; i++)  
  12.     {  
  13.         scanf( "%d", &tmp );  
  14.         T = Insert( tmp, T );  
  15.     }  
  16.     printf( "\nPreOrder :" );  
  17.         PreOrder( T );  
  18.     printf( "\nInOrder  :" );  
  19.     InOrder( T );  
  20.     printf( "\nPostOrder:" );  
  21.     PostOrder( T );  
  22.         printf( "\n" );  
  23.     return 0;  
  24. }  

附录:上述代码中用到了Error、FatalError等函数,其实现如下(即fatal.h文件):
[cpp] view plaincopyprint?
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. #define Error( Str )        FatalError( Str )  
  5. #define FatalError( Str )   fprintf( stderr, "%s\n", Str ), exit( 1 )
0 0
原创粉丝点击