平衡二叉树(AVL树)

Posted kachunyippp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了平衡二叉树(AVL树)相关的知识,希望对你有一定的参考价值。

假设一个二叉查找树中的数据都是链式的(即都集中在左子树或者右子树),那么这时候对该二叉查找树进行查找的时间复杂度就是$O(n)$,背离了二叉查找树用来优化数据查询的目的。而平衡二叉树可以使树的高度在每次插入元素后,查询操作仍然能保持$O(logn)$的时间复杂度。
对平衡二叉树的任意结点来说,要保证其左子树与右子树的高度之差绝对值不超过1,其中左子树与右子树的高度之差称为该结点的平衡因子

 1 // 存储结构 
 2 struct node
 3 {
 4     int data;
 5     int height;
 6     node *lchild;
 7     node *rchild;
 8 };
 9 
10 // 新建结点
11 node *newNode(int n)
12 {
13     node *Node = new node;
14     Node->data = n;
15     Node->height = 1;
16     Node->lchild = Node->rchild = NULL;
17     return Node;
18 }
19 
20 // 获得结点所在子树高度 
21 int getHeight(node *root)
22 {
23     if(root == NULL)
24         return 0;
25     return root->height;
26 }
27 
28 // 计算平衡因子
29 int getBalanceFactor(node *root)
30 {
31     return getHeight(root->lchild) - getHeight(root->rchild);
32 }
33  
34 void updateHeight(node *root)
35 {
36     root->height = max(getHeight(root->lchild),getHeight(root->rchild))+1;
37 }
38 
39 // 查找操作与二叉查找树一样,不过因为AVL树高度为O(logn) 所以时间复杂度也为O(logn)
40 
41 // 左旋 Left Rotation
42 void L(node *&root)
43 {
44     node *temp = root->rchild;
45     root->rchild = temp->lchild;
46     temp->lchild = root;
47     updateHeight(root);
48     updateHeight(temp);
49     root = temp;
50 }
51 
52 // 右旋 (Right Rotation) 
53 void R(node *&root)
54 {
55     node *temp = root->lchild;
56     root->lchild = temp->rchild;
57     temp->rchild = root;
58     updateHeight(root);
59     updateHeight(temp);
60     root = temp;
61 }

 

在往已有的AVL树中插入一个结点,一定会有结点的平衡因子发生变化,此时可能会有结点的平衡因子绝对值大于1(大于1的可能只有2或者-2)。显然只有在从根结点到该插入结点的路径上的结点才可能发生平衡因子变化,因此可以证明,只要把最靠近插入结点的失衡结点调整正常,路径上所有结点就会回复平衡。

假设结点A、B、C的权值满足A>B>C

此时A平衡因子为2,当A的左孩子平衡因子为1时为LL型,A的左孩子平衡因子为-1时为LR型。
LL型:把C为根结点的子树看作整体,以结点A为root进行右旋
LR型:以结点C为root进行左旋,转化为LL型,再按LL型处理

此时A平衡因子为-2,当A的右孩子平衡因子为-1时为RR型,A的右孩子平衡因子为1时为RL型。
RR型:把C为根结点的子树看作整体,以结点A为root进行左旋
RL型:以结点C为root进行右旋,转化为RR型,再按RR型处理

 1 // 往AVL中插入结点 
 2 void insert(node *&root,int v)
 3 {
 4     if(root==NULL)
 5     {
 6         root = newNode(v);
 7         return;
 8     }
 9     if(v <= root->data)
10     {
11         insert(root->lchild,v);
12         updataHeight(root); // 更新树高 
13         if(getBalanceFactor(root) == 2) 
14         {
15             if(getBalanceFactor(root->lchild)==1) // LL型 
16             {
17                 R(root);
18             }
19             else if(getBalanceFactor(root->lchild)==-1) // LR型 
20             {
21                 L(root->lchild);
22                 R(root);
23             }
24         }
25     }
26     else if(v > root->data)
27     {
28         insert(root->rchild,v);
29         updateHeight(root);
30         if(getBalanceFactor(root) == -2)
31         {
32             if(getBalanceFactor(root->rchild) == 1)  // RR型 
33             {
34                 L(root);
35             }
36             else if(getBalanceFactor(root->rchild) == -1)  // RL型 
37             {
38                 R(root->rchild);
39                 L(root);
40             }
41         }
42     }
43 }
44 
45 // 建立AVL树 
46 node *create(int data[],int n)
47 {
48     node *root = new node;
49     for(int i=0;i<n;++i)
50         insert(root,data[i]);
51     return root;
52 }





以上是关于平衡二叉树(AVL树)的主要内容,如果未能解决你的问题,请参考以下文章

数据结构~基础2~树《二叉树二叉搜索树AVL树B树红黑树》的设计~高度平衡二叉树AVL树

算法平衡二叉树 Avl 树

树结构实际应用之平衡二叉树(AVL 树)

其他类型的树1:平衡二叉树和AVL树

C++ 实现平衡二叉树(AVL树)(完整代码)

AVL平衡二叉树