AVL小树转转转转转,我的考试挂挂挂挂挂

开发 前端
AVL 树的意义:是二分查找树 BST 。二分查找树查找某个值时,时间复杂度是 O(h) ,因此,我们让树的尽可能平衡,即最大高度尽可能的小。因此有了 AVL 。

[[423024]]

AVL 树的意义:是二分查找树 BST 。二分查找树查找某个值时,时间复杂度是 O(h) ,因此,我们让树的尽可能平衡,即最大高度尽可能的小。因此有了 AVL 。

参考例题:

  • AcWing:AVL树的根[1]

百度百科[2]:在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。

BST 本质上是维护一个有序序列,AVL 树中的左旋右旋操作,并不会改变树的中序遍历结果。

上图中把 A 右旋是怎么做的呢?把 B 旋转到根节点,然后把 A 变成 B 的右孩子,把 E 补偿给 A 作为 A 的左孩子。

左旋和右旋

对节点 u 右旋:

  • 根 u 的左儿子变成新的根 p
  • 根的左儿子变成新的根 p 原本的右儿子
  • 新的根 p 的右儿子变成了原本的根 u
  • u 和 p 的高度都需要更新
  1. void R(int& u) 
  2.     int p = l[u]; 
  3.     l[u] = r[p], r[p] = u; 
  4.     update(u), update(p); 
  5.     u = p; 

对节点 u 右旋:

  • 根 u 的右儿子变成新的根 p
  • 根的右儿子变成新的根 p 原本的左儿子
  • 新的根 p 的左儿子变成了原本的根 u
  • u 和 p 的高度都需要更新
  1. void L(int& u) 
  2.     int p = r[u]; 
  3.     r[u] = l[p], l[p] = u; 
  4.     update(u), update(p); 
  5.     u = p; 

高度更新由左右儿子决定,因为求高度时,默认其两个儿子已经更新完高度了:

  1. void update(int u) 
  2.     h[u] = max(h[l[u]], h[r[u]]) + 1; 

插入的四种情况

四种情况

(一)新数字插到了左子树,导致左子树比右子树高2;左孩子的左子树比其右子树高1

对于四种情况中的①。应该右旋 A 。

实例如上图,右旋 88 即可。

(二)新数字插到了左子树,导致左子树比右子树高2;左孩子的右子树比其左子树高1

对于四种情况中的③。应该左旋 B 再右旋 A 。

对应的情况如如下:

  1.   70 
  2. 61 
  3.   65 
  4. // 左旋 61 
  5.     70 
  6.   65 
  7. 61 
  8. // 右旋 70 
  9.   65 
  10. 61  70 

(三)新数字插到了右子树,导致右子树比左子树高2;右孩子的右子树比其左子树高1

对于四种情况中的②。应该左旋 A 。

对应的情况如 88 96 120 ,左旋 88 即可。

(四)新数字插到了右子树,导致右子树比左子树高2;右孩子的左子树比其右子树高1

对于四种情况中的④。应该右旋 B 再左旋 A 。

对应的情况如如下:

  1.   70 
  2. 96 
  3.   88 
  4. // 右旋 96 
  5. 70 
  6.   88 
  7.     96 
  8. // 左旋 70 
  9.   96 
  10. 70  88 

插入的代码

  1. void insert(int& u, int w) 
  2.     if (!u) u = ++ idx, v[u] = w; 
  3.     else if (w < v[u]) 
  4.     { 
  5.         insert(l[u], w); 
  6.         if (get_balance(u) == 2) 
  7.         { 
  8.             if (get_balance(l[u]) == 1) R(u); 
  9.             else L(l[u]), R(u); 
  10.         } 
  11.     } 
  12.     else 
  13.     { 
  14.         insert(r[u], w); 
  15.         if (get_balance(u) == -2) 
  16.         { 
  17.             if (get_balance(r[u]) == -1) L(u); 
  18.             else R(r[u]), L(u); 
  19.         } 
  20.     } 
  21.  
  22.     update(u); 

参考资料

[1]AVL树的根: https://www.acwing.com/problem/content/description/1554/

[2]百度百科: https://baike.baidu.com/item/AVL%E6%A0%91/10986648

 

责任编辑:武晓燕 来源: Piper蛋窝
相关推荐

2010-08-27 14:04:47

2023-11-01 07:44:29

转转Flutter业务

2011-03-25 10:23:22

2010-08-27 13:49:56

2021-12-17 07:54:16

Flink SQLTable DataStream

2009-08-10 16:20:13

2009-06-02 09:09:36

2010-09-14 20:02:14

2023-12-27 19:12:42

OLAP自助分析

2022-11-07 14:45:26

转转价格DDD

2010-11-01 16:14:29

2016-10-21 00:03:36

2021-05-19 08:25:24

KubeEventer操作

2009-09-17 12:55:24

2009-04-28 13:18:42

卡饭社区恶意代码金山毒霸

2010-03-26 19:19:02

2023-08-03 09:12:02

2023-02-08 09:42:30

策略方式容量

2022-12-15 08:35:01

用户画像平台
点赞
收藏

51CTO技术栈公众号