• 数据结构:AVL树的旋转(高度平衡树)


    1、AVL树简介

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

    • 它的子树都是AVL树
    • 左右子树高度插(平衡因子)的绝对值不超过1

    AVL树还是一个搜索二叉树,只不过因为普通的搜索二叉树有可能变成单只树,这样就使查找效率非常的低。我们就给普通的搜索二叉树增加了一个平衡因子来使AVL左右子树的高度差的绝对值不超过1

    1. template<class K,class V>
    2. struct AVLTreeNode
    3. {
    4. AVLTreeNode<K, V>* _left;
    5. AVLTreeNode<K, V>* _right;
    6. AVLTreeNode<K, V>* _parent;
    7. pair<K, V> _kv; // 存储的键对
    8. int _bf; // balance factor
    9. AVLTreeNode(const pair<K, V>& kv)
    10. :_left(nullptr)
    11. , _right(nullptr)
    12. , _parent(nullptr)
    13. , _kv(kv)
    14. , _bf(0)
    15. {}
    16. };
    17. template<class K, class V>
    18. class AVLTree
    19. {
    20. typedef AVLTreeNode<K, V> Node;
    21. public:
    22. bool Insert(const pair<K, V>& kv);
    23. bool IsBalance();
    24. void InOrder();
    25. void Height();
    26. private:
    27. void RotateL(Node* parent); //左旋转
    28. void RotateR(Node* parent); //右旋转
    29. void RotateRL(Node* parent); //右左旋转
    30. void RotateLR(Node* parent); //左右旋转
    31. bool _IsBalance(Node* root);
    32. void _InOrder(Node* root);
    33. int _Height(Node* root);
    34. Node* _root = nullptr;
    35. };

    2、AVL树的插入

    • AVL树的插入前面和搜索二叉树的插入一模一样,只不过我们要注意平衡因子
    • 因为AVL树保持平衡是要平衡因子的绝对值不超过1,而插入会使平衡因子改变,所以我们也要要相应的旋转,使平衡因子的绝对值不超过一,我们又有几种情况
    1. 假如以pParent为根的子树不平衡,即pParent的平衡因子为2或者-2,分以下情况考虑
    2. parent的平衡因子为2,说明parent的右子树高,设parent的右子树的根为subR,当subR的平衡因子为1时,执行左单旋。当subR的平衡因子为-1时,执行右左双旋
    3. parent的平衡因子为-2,说明parent的左子树高,设parent的左子树的根为subL,当subL的平衡因子为-1是,执行右单旋。当subL的平衡因子为1时,执行左右双旋
    4. 旋转完成后,原parent为根的子树个高度降低,已经平衡,不需要再向上更新
    1. template<class K, class V>
    2. bool AVLTree<K, V>::Insert(const pair<K, V>& kv)
    3. {
    4. if (_root == nullptr)
    5. {
    6. _root = new Node(kv);
    7. return true;
    8. }
    9. Node* parent = nullptr;
    10. Node* cur = _root;
    11. while (cur)
    12. {
    13. if (cur->_kv.first < kv.first)
    14. {
    15. parent = cur;
    16. cur = cur->_right;
    17. }
    18. else if (cur->_kv.first > kv.first)
    19. {
    20. parent = cur;
    21. cur = cur->_left;
    22. }
    23. else
    24. {
    25. return false;
    26. }
    27. }
    28. cur = new Node(kv);
    29. if (parent->_kv.first > kv.first)
    30. {
    31. parent->_left = cur;
    32. }
    33. else
    34. {
    35. parent->_right = cur;
    36. }
    37. cur->_parent = parent;
    38. // 更新平衡因子
    39. while (parent)
    40. {
    41. if (cur == parent->_right)
    42. {
    43. parent->_bf++;
    44. }
    45. else
    46. {
    47. parent->_bf--;
    48. }
    49. if (parent->_bf == 1 || parent->_bf == -1)
    50. {
    51. // 继续更新
    52. parent = parent->_parent;
    53. cur = cur->_parent;
    54. }
    55. else if (parent->_bf == 0)
    56. {
    57. break;
    58. }
    59. else if (parent->_bf == 2 || parent->_bf == -2)
    60. {
    61. // 需要旋转处理 -- 1、让这颗子树平衡 2、降低这颗子树的高度
    62. if (parent->_bf == 2 && cur->_bf == 1)
    63. {
    64. RotateL(parent);
    65. }
    66. else if (parent->_bf == -2 && cur->_bf == -1)
    67. {
    68. RotateR(parent);
    69. }
    70. else if (parent->_bf == -2 && cur->_bf == 1)
    71. {
    72. RotateLR(parent);
    73. }
    74. else if (parent->_bf == 2 && cur->_bf == -1)
    75. {
    76. RotateRL(parent);
    77. }
    78. else
    79. {
    80. assert(false);
    81. }
    82. break;
    83. }
    84. else
    85. {
    86. assert(false);
    87. }
    88. }
    89. return true;
    90. }

    2.1、左单旋

    1. subRL变成parent的右子树 
    2. parent变成subR的左子树
    3. subR变成新根
    4. 更新平衡因子
    1. template<class K, class V>
    2. void AVLTree<K, V>::RotateL(Node* parent)
    3. {
    4. Node* subR = parent->_right;
    5. Node* subRL = subR->_left;
    6. parent->_right = subRL;
    7. subR->_left = parent;
    8. Node* parentParent = parent->_parent;
    9. parent->_parent = subR;
    10. if (subRL)
    11. subRL->_parent = parent;
    12. if (_root == parent)
    13. {
    14. _root = subR;
    15. subR->_parent = nullptr;
    16. }
    17. else
    18. {
    19. if (parentParent->_left == parent)
    20. {
    21. parentParent->_left = subR;
    22. }
    23. else
    24. {
    25. parentParent->_right = subR;
    26. }
    27. subR->_parent = parentParent;
    28. }
    29. parent->_bf = subR->_bf = 0;
    30. }

    2.2、右单旋

    60为parent,30为subL,b为subLR 

    1. subLR变成parent的左子树 
    2. parent变成subL的右子树
    3. subL变成新根
    4. 更新平衡因子
    1. template<class K, class V>
    2. void AVLTree<K, V>::RotateR(Node* parent)
    3. {
    4. Node* subL = parent->_left;
    5. Node* subLR = subL->_right;
    6. parent->_left = subLR;
    7. if (subLR)
    8. subLR->_parent = parent;
    9. Node* parentParent = parent->_parent;
    10. subL->_right = parent;
    11. parent->_parent = subL;
    12. if (_root == parent)
    13. {
    14. _root = subL;
    15. subL->_parent = nullptr;
    16. }
    17. else
    18. {
    19. if (parentParent->_left == parent)
    20. {
    21. parentParent->_left = subL;
    22. }
    23. else
    24. {
    25. parentParent->_right = subL;
    26. }
    27. subL->_parent = parentParent;
    28. }
    29. subL->_bf = parent->_bf = 0;
    30. }

    2.3、左右双旋 

    先对30进行左单旋,先对90右单旋

    1. template<class K, class V>
    2. void AVLTree<K, V>::RotateLR(Node* parent)
    3. {
    4. Node* subL = parent->_left;
    5. Node* subLR = subL->_right;
    6. int bf = subLR->_bf;
    7. RotateL(parent->_left);
    8. RotateR(parent);
    9. if (bf == 0)
    10. {
    11. parent->_bf = subL->_bf = subLR->_bf = 0;
    12. }
    13. else if (bf == -1)
    14. {
    15. parent->_bf = 1;
    16. subLR->_bf = 0;
    17. subL->_bf = 0;
    18. }
    19. else if (bf == 1)
    20. {
    21. parent->_bf = 0;
    22. subLR->_bf = 0;
    23. subL->_bf = -1;
    24. }
    25. else
    26. {
    27. assert(false);
    28. }
    29. }

    2.3、右左双旋 

    先对90进行右单旋,先对30左单旋 

    1. template<class K, class V>
    2. void AVLTree<K, V>::RotateRL(Node* parent)
    3. {
    4. Node* subR = parent->_right;
    5. Node* subRL = subR->_left;
    6. int bf = subRL->_bf;
    7. RotateR(parent->_right);
    8. RotateL(parent);
    9. if (bf == 0)
    10. {
    11. // subRL自己就是新增
    12. parent->_bf = subR->_bf = subRL->_bf = 0;
    13. }
    14. else if (bf == -1)
    15. {
    16. // subRL的左子树新增
    17. parent->_bf = 0;
    18. subRL->_bf = 0;
    19. subR->_bf = 1;
    20. }
    21. else if (bf == 1)
    22. {
    23. // subRL的右子树新增
    24. parent->_bf = -1;
    25. subRL->_bf = 0;
    26. subR->_bf = 0;
    27. }
    28. else
    29. {
    30. assert(false);
    31. }
    32. }

     3、AVL树的性能

    AVL树是带有平衡条件的二叉查找树,一般是用平衡因子差值判断是否平衡并通过旋转来实现平衡,左右子树树高不超过1,和红黑树相比,它是严格的平衡二叉树,平衡条件必须满足(所有节点的左右子树高度差不超过1)。不管我们是执行插入还是删除操作,只要不满足上面的条件,就要通过旋转来保持平衡,而旋转是非常耗时的,由此我们可以知道AVL树适合用于插入删除次数比较少,但查找多的情况。

    如果要对AVL树做一些结构修改的操作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时,有可能一直要让旋转持续到根的位置。因此:如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(即不会改变),可以考虑AVL树,但一个结构经常修改,就不太适合

    4、实现

    1. #include<assert.h>
    2. template<class K,class V>
    3. struct AVLTreeNode
    4. {
    5. AVLTreeNode<K, V>* _left;
    6. AVLTreeNode<K, V>* _right;
    7. AVLTreeNode<K, V>* _parent;
    8. pair<K, V> _kv; // 存储的键对
    9. int _bf; // balance factor
    10. AVLTreeNode(const pair<K, V>& kv)
    11. :_left(nullptr)
    12. , _right(nullptr)
    13. , _parent(nullptr)
    14. , _kv(kv)
    15. , _bf(0)
    16. {}
    17. };
    18. template<class K, class V>
    19. class AVLTree
    20. {
    21. typedef AVLTreeNode<K, V> Node;
    22. public:
    23. bool Insert(const pair<K, V>& kv);
    24. bool IsBalance();
    25. void InOrder();
    26. void Height();
    27. private:
    28. void RotateL(Node* parent); //左旋转
    29. void RotateR(Node* parent); //右旋转
    30. void RotateRL(Node* parent); //右左旋转
    31. void RotateLR(Node* parent); //左右旋转
    32. bool _IsBalance(Node* root);
    33. void _InOrder(Node* root);
    34. int _Height(Node* root);
    35. Node* _root = nullptr;
    36. };
    37. template<class K, class V>
    38. bool AVLTree<K, V>::Insert(const pair<K, V>& kv)
    39. {
    40. if (_root == nullptr)
    41. {
    42. _root = new Node(kv);
    43. return true;
    44. }
    45. Node* parent = nullptr;
    46. Node* cur = _root;
    47. while (cur)
    48. {
    49. if (cur->_kv.first < kv.first)
    50. {
    51. parent = cur;
    52. cur = cur->_right;
    53. }
    54. else if (cur->_kv.first > kv.first)
    55. {
    56. parent = cur;
    57. cur = cur->_left;
    58. }
    59. else
    60. {
    61. return false;
    62. }
    63. }
    64. cur = new Node(kv);
    65. if (parent->_kv.first > kv.first)
    66. {
    67. parent->_left = cur;
    68. }
    69. else
    70. {
    71. parent->_right = cur;
    72. }
    73. cur->_parent = parent;
    74. // 更新平衡因子
    75. while (parent)
    76. {
    77. if (cur == parent->_right)
    78. {
    79. parent->_bf++;
    80. }
    81. else
    82. {
    83. parent->_bf--;
    84. }
    85. if (parent->_bf == 1 || parent->_bf == -1)
    86. {
    87. // 继续更新
    88. parent = parent->_parent;
    89. cur = cur->_parent;
    90. }
    91. else if (parent->_bf == 0)
    92. {
    93. break;
    94. }
    95. else if (parent->_bf == 2 || parent->_bf == -2)
    96. {
    97. // 需要旋转处理 -- 1、让这颗子树平衡 2、降低这颗子树的高度
    98. if (parent->_bf == 2 && cur->_bf == 1)
    99. {
    100. RotateL(parent);
    101. }
    102. else if (parent->_bf == -2 && cur->_bf == -1)
    103. {
    104. RotateR(parent);
    105. }
    106. else if (parent->_bf == -2 && cur->_bf == 1)
    107. {
    108. RotateLR(parent);
    109. }
    110. else if (parent->_bf == 2 && cur->_bf == -1)
    111. {
    112. RotateRL(parent);
    113. }
    114. else
    115. {
    116. assert(false);
    117. }
    118. break;
    119. }
    120. else
    121. {
    122. assert(false);
    123. }
    124. }
    125. return true;
    126. }
    127. template<class K, class V>
    128. void AVLTree<K, V>::RotateL(Node* parent)
    129. {
    130. Node* subR = parent->_right;
    131. Node* subRL = subR->_left;
    132. parent->_right = subRL;
    133. subR->_left = parent;
    134. Node* parentParent = parent->_parent;
    135. parent->_parent = subR;
    136. if (subRL)
    137. subRL->_parent = parent;
    138. if (_root == parent)
    139. {
    140. _root = subR;
    141. subR->_parent = nullptr;
    142. }
    143. else
    144. {
    145. if (parentParent->_left == parent)
    146. {
    147. parentParent->_left = subR;
    148. }
    149. else
    150. {
    151. parentParent->_right = subR;
    152. }
    153. subR->_parent = parentParent;
    154. }
    155. parent->_bf = subR->_bf = 0;
    156. }
    157. template<class K, class V>
    158. void AVLTree<K, V>::RotateR(Node* parent)
    159. {
    160. Node* subL = parent->_left;
    161. Node* subLR = subL->_right;
    162. parent->_left = subLR;
    163. if (subLR)
    164. subLR->_parent = parent;
    165. Node* parentParent = parent->_parent;
    166. subL->_right = parent;
    167. parent->_parent = subL;
    168. if (_root == parent)
    169. {
    170. _root = subL;
    171. subL->_parent = nullptr;
    172. }
    173. else
    174. {
    175. if (parentParent->_left == parent)
    176. {
    177. parentParent->_left = subL;
    178. }
    179. else
    180. {
    181. parentParent->_right = subL;
    182. }
    183. subL->_parent = parentParent;
    184. }
    185. subL->_bf = parent->_bf = 0;
    186. }
    187. template<class K, class V>
    188. void AVLTree<K, V>::RotateRL(Node* parent)
    189. {
    190. Node* subR = parent->_right;
    191. Node* subRL = subR->_left;
    192. int bf = subRL->_bf;
    193. RotateR(parent->_right);
    194. RotateL(parent);
    195. if (bf == 0)
    196. {
    197. // subRL自己就是新增
    198. parent->_bf = subR->_bf = subRL->_bf = 0;
    199. }
    200. else if (bf == -1)
    201. {
    202. // subRL的左子树新增
    203. parent->_bf = 0;
    204. subRL->_bf = 0;
    205. subR->_bf = 1;
    206. }
    207. else if (bf == 1)
    208. {
    209. // subRL的右子树新增
    210. parent->_bf = -1;
    211. subRL->_bf = 0;
    212. subR->_bf = 0;
    213. }
    214. else
    215. {
    216. assert(false);
    217. }
    218. }
    219. template<class K, class V>
    220. void AVLTree<K, V>::RotateLR(Node* parent)
    221. {
    222. Node* subL = parent->_left;
    223. Node* subLR = subL->_right;
    224. int bf = subLR->_bf;
    225. RotateL(parent->_left);
    226. RotateR(parent);
    227. if (bf == 0)
    228. {
    229. parent->_bf = subL->_bf = subLR->_bf = 0;
    230. }
    231. else if (bf == -1)
    232. {
    233. parent->_bf = 1;
    234. subLR->_bf = 0;
    235. subL->_bf = 0;
    236. }
    237. else if (bf == 1)
    238. {
    239. parent->_bf = 0;
    240. subLR->_bf = 0;
    241. subL->_bf = -1;
    242. }
    243. else
    244. {
    245. assert(false);
    246. }
    247. }
    248. template<class K, class V>
    249. void AVLTree<K, V>::InOrder()
    250. {
    251. _InOrder(_root);
    252. cout << endl;
    253. }
    254. template<class K, class V>
    255. void AVLTree<K, V>::_InOrder(Node* root)
    256. {
    257. if (root == nullptr)
    258. return;
    259. _InOrder(root->_left);
    260. cout << root->_kv.first << " ";
    261. _InOrder(root->_right);
    262. }
    263. template<class K, class V>
    264. bool AVLTree<K, V>::IsBalance()
    265. {
    266. return _IsBalance(_root);
    267. }
    268. template<class K, class V>
    269. int AVLTree<K, V>::_Height(Node* root)
    270. {
    271. if (root == nullptr)
    272. return 0;
    273. int leftHeight = _Height(root->_left);
    274. int rightHeight = _Height(root->_right);
    275. return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
    276. }
    277. template<class K, class V>
    278. void AVLTree<K, V>::Height()
    279. {
    280. cout << _Height(_root) << endl;
    281. }
    282. template<class K, class V>
    283. bool AVLTree<K,V>::_IsBalance(Node* root)
    284. {
    285. if (root == nullptr)
    286. return true;
    287. int leftHeight = _Height(root->_left);
    288. int rightHeight = _Height(root->_right);
    289. if (rightHeight - leftHeight != root->_bf)
    290. {
    291. cout << root->_kv.first << "平衡因子异常" << endl;
    292. return false;
    293. }
    294. return abs(rightHeight - leftHeight) < 2
    295. && _IsBalance(root->_left)
    296. && _IsBalance(root->_right);
    297. }

  • 相关阅读:
    Go:定 n 对括号,来生成格式正确的括号的所有组合(附完整源码)
    静电学历史
    【leetcode34----最小差值】
    UE Lyda项目学习 二、距离匹配 步幅适配 同步组
    面试高潮季即将来袭,Android 开发者能否在其中鲤鱼跃龙门?
    人工智能聊天机器人如何帮助您实现工作与生活的平衡
    二、系统知识笔记-系统架构概述
    多测师肖sir_高级讲师_python安装和pycharm(002)
    linux 冷启动热启动
    Stream之flatMap用法
  • 原文地址:https://blog.csdn.net/weixin_74268082/article/details/134227505