zl程序教程

您现在的位置是:首页 >  其它

当前栏目

AVL树

AVL
2023-09-11 14:19:00 时间

定义

平衡因子(Balance Factor ,简称BF ): BF(T) = hL -hR ,其中 h和 和 h为 分别为 T 的左、右子树的高度    
平衡二叉树又称为AVL树,其定义如下:
        空树,或者任一节点左右子树高度差的绝对值不超过1的二叉搜索树,即|BF(T)| ≤ 1。
 
 

AVL树的插入(旋转)

(1) LL旋转:产生问题的结点在发现问题结点的左子树的左子树上。
 
(2) RR旋转:产生问题的结点在发现问题结点的右子树的右子树上。
 
(3) LR旋转:产生问题的结点在发现问题结点的左子树的右子树上。
 
LR旋转相当于先对以B为根结点的子树做了一次右单旋(RR),再对以A为根结点的子树做了一次左单旋(LL),是两次单旋的合成结果。
 
 
(4) RL旋转:产生问题的结点在发现问题结点的右子树的左子树上。
同理,RL旋转相当于先对以B为根结点的子树做了一次左单旋(LL),再对以A为根结点的子树做了一次右单旋(RR),是两次单旋的合成结果。
 

代码实现

  1 typedef int ElementType;
  2 typedef struct AVLNode *Position;
  3 typedef Position AVLTree;    /* AVL树类型 */
  4 typedef struct AVLNode
  5 {
  6     ElementType Data;    /* 结点数据 */
  7     AVLTree Left;        /* 指向左子树 */
  8     AVLTree Right;        /* 指向右子树 */
  9     int Height;            /* 树的高度 */
 10 };
 11 
 12 /* 直接获取树的高度 */
 13 int getHeight(AVLTree A)
 14 {
 15     if (A != NULL)
 16         return A->Height;
 17     else
 18         return 0;
 19 }
 20 
 21 AVLTree LL(AVLTree A)
 22 {
 23     /* 注意:A必须有一个左子结点B */
 24     /* 将A与B做左单旋,更新A与B的高度,返回新的根结点B */
 25 
 26     AVLTree B = A->Left;
 27     A->Left = B->Right;
 28     B->Right = A;
 29     A->Height = max(getHeight(A->Left), getHeight(A->Right)) + 1;
 30     B->Height = max(getHeight(B->Left), getHeight(B->Right)) + 1;
 31 
 32     return B;    /* 返回根结点 */
 33 }
 34 
 35 AVLTree RR(AVLTree A)
 36 {
 37     /* 注意:A必须有一个右子结点B */
 38     /* 将A与B做右单旋,更新A与B的高度,返回新的根结点B */
 39 
 40     AVLTree B = A->Right;
 41     A->Right = B->Left;
 42     B->Left = A;
 43     A->Height = max(getHeight(A->Left), getHeight(A->Right)) + 1;
 44     B->Height = max(getHeight(B->Left), getHeight(B->Right)) + 1;
 45 
 46     return B;    /* 返回根结点 */
 47 }
 48 
 49 AVLTree LR(AVLTree A)
 50 {
 51     /* 注意:A必须有一个左子结点B,且B必须有一个右子结点C */
 52     /* 将A、B与C做如图4.38所示的两次单旋,返回新的根结点C */
 53 
 54     /* 将B与C做右单旋,C被返回 */
 55     A->Left = RR(A->Left);
 56 
 57     /* 将A与C做左单旋,C被返回 */
 58     return LL(A);    
 59 }
 60 
 61 AVLTree RL(AVLTree A)
 62 {
 63     /* 注意:A必须有一个右子结点B,且B必须有一个左子结点C */
 64     
 65     /* 将B与C做左单旋,C被返回 */
 66     A->Right = LL(A->Right);
 67 
 68     /* 将A与C做右单旋,C被返回 */
 69     return RR(A);
 70 }
 71 
 72 
 73 /* 将X插入AVL树T中,并且返回调整后的AVL树 */
 74 AVLTree Insert(AVLTree T, ElementType X)
 75 {
 76     if (T == NULL)
 77     {
 78         /* 若插入空树,则新建包含一个结点的树 */
 79         T = (AVLTree)malloc(sizeof(struct AVLNode));
 80         T->Data = X;
 81         T->Height = 1;
 82         T->Left = T->Right = NULL;
 83     }
 84     else if (X < T->Data)
 85     {
 86         /* 插入T的左子树 */
 87         T->Left = Insert(T->Left, X);
 88         /* 如果需要左旋 */
 89         if (getHeight(T->Left) - getHeight(T->Right) == 2)
 90         {
 91             if (X < T->Left->Data)
 92                 T = LL(T);    /* 左单旋 */
 93             else
 94                 T = LR(T);    /* 左-右双旋 */
 95         }
 96     }
 97     else if (X > T->Data)
 98     {
 99         /* 插入T的右子树 */
100         T->Right = Insert(T->Right, X);
101         /* 如果需要右旋 */
102         if (getHeight(T->Left) - getHeight(T->Right) == -2)
103         {
104             if (X < T->Right->Data)
105                 T = RL(T);    /* 右-左双旋 */
106             else
107                 T = RR(T);    /* 右单旋 */
108         }
109     }
110 
111     /* else X == T->Data,无需插入 */
112 
113     /* 别忘了更新树高 */
114     T->Height = max(getHeight(T->Left), getHeight(T->Right)) + 1;
115 
116     return T;
117 
118 }

 

测试代码:

 1 void LevelTraverse(AVLTree T)
 2 {
 3     if (!T)
 4         return;
 5 
 6     queue<AVLTree> Q;
 7     Q.push(T);
 8     while (!Q.empty())
 9     {
10         AVLTree A = Q.front();
11         Q.pop();
12         printf("%d ", A->Data);
13         if (A->Left)
14             Q.push(A->Left);
15         if (A->Right)
16             Q.push(A->Right);
17     }
18 }
19 
20 int main()
21 {
22     AVLTree T = NULL;
23     T = Insert(T, 20);
24     T = Insert(T, 18);
25     T = Insert(T, 30);
26     T = Insert(T, 15);
27     T = Insert(T, 19);
28     T = Insert(T, 16);    //破坏平衡
29 
30     LevelTraverse(T);
31 
32     system("pause");
33     return 0;
34 }

 

参考

《 数据结构 (第2版) 》 - 陈越、何钦铭
中国大学MOOC中的浙江大学《数据结构》课程,陈越、何钦铭