• 【STL】平衡二叉树


    目录

    前言

    AVL树

    1. AVL树的概念和性质

    2. AVL树类的属性​​​​​​​

    3. AVL树的插入函数

    4. 总结

    红黑树

    1. 红黑树的概念和性质(什么是红黑树,并且作为一颗红黑树的要求)

    2. 红黑树类的属性

    3. 红黑树的插入函数

    4. 总结


    前言

    对于之前普通的二叉搜索树,其搜索的效率依靠树的形状来决定,如下:

    d6b39cc3ecbe4318a5bbd780ecefb9b3.png

    可以看到 A图 中的树比较彭亨,搜索一个元素的效率接近 O(logN) ;而 B图 中的形状也符合搜索二叉树,但是很不平衡,这时的搜索效率就变成 O(N) 了(如搜索值为4的节点)

    可以看到,如果搜索二叉树不平衡,他的搜索的效率不确定,在 O(logN) 和 O(N) 之间,可能有暴击;

    那么对此,既然不平衡,那我们就给出平衡的两种方法:

    1.构成AVL树

    2.构成红黑树

    这两种方法都是为了平衡搜索二叉树而生

    AVL树

    1. AVL树的概念和性质

    它的出现是为了 搜索二叉树的平衡,那就来了解AVL树的概念和性质,也就是什么是AVL,并且作为一颗AVL树的要求是什么

    首先AVL树是一颗树,它要求任何一个节点的左右子树的高度差不超过一,以此来保证平衡,是AVL树的核心

    来看看它的做法

    与搜索二叉树不同,它将二叉链,变成了三叉链(多了指向父节点的指针),并且引入了平衡因子这个东西;这些都是为了方便并且为了树的一个平衡引入

    三叉链和平衡因子和下面AVL树属性的图结合起来看更直观

    三叉链也就是多了一个 parent指针 指向该节点的父节点,这一操作可以让节点找到其祖先

    平衡因子是指该节点的 右子树高度 减去 左子树高度的值,而根据AVL树的性质(要求任何一个节点的左右子树的高度差不超过一),也就是平衡因子 _bf 的值域为 { -1, 0, 1 } ,如果平衡因子 _bf 的值出现为 2 或者 -2 ,说明该树已经不平衡,此时需要进行停止调整,先进行旋转操作

    2. AVL树类的属性

    这里的节点值类型简化为了int类型,原为 pair

    8d3c11a09a094a64b8137292a659eedc.png

    bd509a65fd8946ffbb38ca7fb689e048.png

    3. AVL树的插入函数

    而AVL树的重点呢,也就是AVL树是如何让树达到平衡的呢?就是每插入了一个节点后,进行了一些调整,如果插入节点后不平衡,那么会将其调整成平衡

    插入后对插入节点祖先的平衡因子进行调整,当调整过程中,有平衡因子出现异常时,此时通过旋转的方式,让树继续保持平衡

    当平衡因子出现异常即是 平衡因子的值更新为 2 或者 -2 时,说明树现在已经不平衡,需要进行旋转

    分情况讨论:

    a6f7bbde65044588ad1a8e0c6d46229b.png

    现在平衡因子已经出现了不平衡,为什么旋转之后,树就可以继续平衡呢?

    具体看到旋转 (这里以左单旋为例):

    定义节点指针 parent(图中的节点值为30), cur(图中的60)

    左单旋是将 cur 的左孩子给给 parent 的右, 再把 parent 赋值给 cur 的左,旋转完成

    再进行平衡因子的更新:parent 和 cur 的平衡因子 _bf 都变成 0

    32e08c9f357a4f2db020b7bdfb4e58a1.png

    左单旋具体代码如下:

    1. void RotateL(Node* parent)
    2. {
    3. assert(parent);
    4. Node* cur = parent->_right;
    5. Node* cur_left = cur->_left;
    6. // 改变节点之间的关系
    7. parent->_right = cur_left;
    8. cur->_left = parent;
    9. // 改变_parent的指向
    10. //原本 parent 的 _parent
    11. Node* ppNode = parent->_parent;
    12. //若原本 ppNode(原本 parent 的 _parent)为空,说明parent原本不是根,现需把 ppNode 给到 cur 的 _parent,并且把 ppNode 的子更新为 cur
    13. if (ppNode)
    14. {
    15. if (ppNode->_left == parent)
    16. {
    17. ppNode->_left = cur;
    18. }
    19. else
    20. {
    21. ppNode->_right = cur;
    22. }
    23. cur->_parent = ppNode;
    24. }
    25. //若原本 parent->_parent 为空,说明parent原本是根,现需把_root更新为根
    26. else
    27. {
    28. _root = cur;
    29. cur->_parent = nullptr;
    30. }
    31. if (cur_left)
    32. {
    33. cur_left->_parent = parent;
    34. }
    35. parent->_parent = cur;
    36. // 更新平衡因子
    37. cur->_bf = parent->_bf = 0;
    38. }

    对左单旋的总结是:当不平衡的树进行左单旋之后,树又被调整为平衡,然后再进行平衡因子的更新

    那么右单旋的思路是一样的,自己可以进行推理

    而要进行双旋时候,可以再进行讨论(这里以右左旋进行讨论):

    8cd424f049604210a6c94074d65f57a3.png

    右左旋:定义 parent(下图节点值为30), cur(下图节点值为90), cur_left(下图节点值为60)

    双旋都是两大步,这里右左旋就是先进行右旋,再进行左旋,旋转结束;对,这里对刚刚实现的单旋代码进行了复用,复用yyds

    具体是对 cur 先进行右旋,再对 parent 进行左旋,如下

    dcb5820617d4473c95c273a54add59f1.png

    最后进行平衡因子的调整,但是这里特别容易忘记第三种情况的讨论,AVL树的这个细节得注意:

    188fbf8bb0974858b161474841cdfb82.png

    右左旋的代码如下:

    1. void RotateRL(Node* parent)
    2. {
    3. Node* cur = parent->_right;
    4. Node* cur_left = cur->_left;
    5. int bf = cur_left->_bf;
    6. RotateR(parent->_right);
    7. RotateL(parent);
    8. parent->_bf = 0;
    9. cur->_bf = 0;
    10. cur_left->_bf = 0;
    11. if (bf == -1)
    12. {
    13. cur->_bf = 1;
    14. }
    15. if (bf == 1)
    16. {
    17. parent->_bf = -1;
    18. }
    19. }

    那么左右旋的思路是一样的,自己可以进行推理

    4. 总结

    而进行何种旋转本质是取决于 parent cur 和 cur_left (或cur_right)之间的关系,若他们三个所连成的是直线,那么进行单旋操作,如果为折线,那就进行双旋操作;而这里的平衡因子刚好可以体现他们之间的关系,所以上图中根据平衡因子来决定单双旋和左右旋转

    AVL树构造和插入函数,测试函数:

    这里的节点值类型简化为了int类型,原为 pair

    1. #pragma once
    2. #include
    3. using namespace std;
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. #include
    16. #include
    17. #include
    18. #include
    19. namespace zhuandrong
    20. {
    21. class AVLTreeNode
    22. {
    23. typedef AVLTreeNode Node;
    24. public:
    25. int _val;
    26. Node* _left;
    27. Node* _right;
    28. Node* _parent;
    29. int _bf;
    30. public:
    31. AVLTreeNode(const int val = 0)
    32. : _val(val)
    33. , _left(nullptr)
    34. , _right(nullptr)
    35. , _parent(nullptr)
    36. , _bf(0)
    37. {}
    38. };
    39. class AVLTree
    40. {
    41. typedef AVLTreeNode Node;
    42. protected:
    43. void RotateL(Node* parent)
    44. {
    45. assert(parent);
    46. Node* cur = parent->_right;
    47. Node* cur_left = cur->_left;
    48. // 改变节点之间的关系
    49. parent->_right = cur_left;
    50. cur->_left = parent;
    51. // 改变_parent的指向
    52. //原本 parent 的 _parent
    53. Node* ppNode = parent->_parent;
    54. //若原本 ppNode(原本 parent 的 _parent)为空,说明parent原本不是根,现需把 ppNode 给到 cur 的 _parent,并且把 ppNode 的子更新为 cur
    55. if (ppNode)
    56. {
    57. if (ppNode->_left == parent)
    58. {
    59. ppNode->_left = cur;
    60. }
    61. else
    62. {
    63. ppNode->_right = cur;
    64. }
    65. cur->_parent = ppNode;
    66. }
    67. //若原本 parent->_parent 为空,说明parent原本是根,现需把_root更新为根
    68. else
    69. {
    70. _root = cur;
    71. cur->_parent = nullptr;
    72. }
    73. if (cur_left)
    74. {
    75. cur_left->_parent = parent;
    76. }
    77. parent->_parent = cur;
    78. // 更新平衡因子
    79. cur->_bf = parent->_bf = 0;
    80. }
    81. //void RotateL(Node* parent)
    82. //{
    83. // Node* cur = parent->_right;
    84. // Node* cur_left = cur->_left;
    85. // parent->_right = cur_left;
    86. // cur->_left = parent;
    87. // Node* ppNode = parent->_parent;
    88. // if (cur_left)//右孩子可能存在,也可能不存在,所以需要判断,需要在parent改变前判断
    89. // {
    90. // cur_left->_parent = parent;
    91. // }
    92. // parent->_parent = cur;
    93. // if (parent == _root)//parent可能是根节点,也可能不是根节点
    94. // {
    95. // _root = cur;
    96. // cur->_parent = nullptr;
    97. // }
    98. // else
    99. // {
    100. // if (ppNode->_left == parent)
    101. // {
    102. // ppNode->_left = cur;
    103. // }
    104. // else
    105. // {
    106. // ppNode->_right = cur;
    107. // }
    108. // cur->_parent = ppNode;
    109. // }
    110. // cur->_bf = parent->_bf = 0;//将平衡因子调整
    111. //}
    112. void RotateR(Node* parent)
    113. {
    114. assert(parent);
    115. Node* cur = parent->_left;
    116. Node* cur_right = cur->_right;
    117. // 改变节点之间的关系
    118. parent->_left = cur_right;
    119. cur->_right = parent;
    120. // 改变_parent的指向
    121. //原本 parent 的 _parent
    122. Node* ppNode = parent->_parent;
    123. //若原本 ppNode(原本 parent 的 _parent)为空,说明parent原本不是根,现需把 ppNode 给到 cur 的 _parent,并且把 ppNode 的子更新为 cur
    124. if (ppNode)
    125. {
    126. if (ppNode->_left == parent)
    127. {
    128. ppNode->_left = cur;
    129. }
    130. else
    131. {
    132. ppNode->_right = cur;
    133. }
    134. cur->_parent = ppNode;
    135. }
    136. //若原本 parent->_parent 为空,说明parent原本是根,现需把_root更新为根
    137. else
    138. {
    139. _root = cur;
    140. cur->_parent = nullptr;
    141. }
    142. if (cur_right)
    143. {
    144. cur_right->_parent = parent;
    145. }
    146. parent->_parent = cur;
    147. // 更新平衡因子
    148. cur->_bf = parent->_bf = 0;
    149. }
    150. //void RotateR(Node* parent)
    151. //{
    152. // Node* cur = parent->_left;
    153. // Node* curRight = cur->_right;
    154. // parent->_left = curRight;
    155. // cur->_right = parent;
    156. // Node* ppNode = parent->_parent;
    157. // if (curRight)//右孩子可能存在,也可能不存在,所以需要判断,需要在parent改变前判断
    158. // {
    159. // curRight->_parent = parent;
    160. // }
    161. // parent->_parent = cur;
    162. // if (parent == _root)//parent可能是根节点,也可能不是根节点
    163. // {
    164. // _root = cur;
    165. // cur->_parent = nullptr;
    166. // }
    167. // else
    168. // {
    169. // if (ppNode->_left == parent)
    170. // {
    171. // ppNode->_left = cur;
    172. // }
    173. // else
    174. // {
    175. // ppNode->_right = cur;
    176. // }
    177. // cur->_parent = ppNode;
    178. // }
    179. // cur->_bf = parent->_bf = 0;//将平衡因子调整
    180. //}
    181. void RotateRL(Node* parent)
    182. {
    183. Node* cur = parent->_right;
    184. Node* cur_left = cur->_left;
    185. int bf = cur_left->_bf;
    186. RotateR(parent->_right);
    187. RotateL(parent);
    188. /*parent->_bf = cur_left->_bf = 0;
    189. cur->_bf = flag;*/
    190. parent->_bf = 0;
    191. cur->_bf = 0;
    192. cur_left->_bf = 0;
    193. if (bf == -1)
    194. {
    195. cur->_bf = 1;
    196. }
    197. if (bf == 1)
    198. {
    199. parent->_bf = -1;
    200. }
    201. }
    202. void RotateLR(Node* parent)
    203. {
    204. Node* cur = parent->_left;
    205. Node* cur_right = cur->_right;
    206. int bf = cur_right->_bf;
    207. RotateL(parent->_left);
    208. RotateR(parent);
    209. /*parent->_bf = parent->_parent->_bf = 0;
    210. parent->_parent->_left->_bf = -1;*/
    211. cur->_bf = 0;
    212. parent->_bf = 0;
    213. cur_right->_bf = 0;
    214. if (bf == 1)
    215. {
    216. cur->_bf = -1;
    217. }
    218. if (bf == -1)
    219. {
    220. parent->_bf = 1;
    221. }
    222. }
    223. protected:
    224. Node* _root;
    225. public:
    226. AVLTree()
    227. : _root(nullptr)
    228. {}
    229. AVLTree(vector<int> v)
    230. {
    231. for (auto& e : v)
    232. {
    233. if (e == 8)
    234. {
    235. int i = 0;
    236. }
    237. insert(e);
    238. assert(IsBalance());
    239. }
    240. }
    241. bool insert(int val)
    242. {
    243. // 判断是否有根节点
    244. if (_root)
    245. {
    246. //先找到合适的插入位置
    247. Node* cur = _root;
    248. Node* parent = nullptr;
    249. while (cur)
    250. {
    251. if (val < cur->_val)
    252. {
    253. parent = cur;
    254. cur = cur->_left;
    255. }
    256. else if (val > cur->_val)
    257. {
    258. parent = cur;
    259. cur = cur->_right;
    260. }
    261. else
    262. {
    263. cout << "插入的元素值已重复" << endl;
    264. return false;
    265. }
    266. }
    267. cur = new Node(val);
    268. cur->_parent = parent;
    269. if (val < parent->_val)
    270. {
    271. parent->_left = cur;
    272. }
    273. else
    274. {
    275. parent->_right = cur;
    276. }
    277. //对平衡因子进行更新
    278. while (parent)
    279. {
    280. if (cur == parent->_left)
    281. {
    282. --parent->_bf;
    283. }
    284. else if (cur == parent->_right)
    285. {
    286. ++parent->_bf;
    287. }
    288. //若 parent->_bf == 0,表明平衡因子调整结束
    289. if (!parent->_bf)
    290. {
    291. break;
    292. }
    293. else if (parent->_bf == 1 || parent->_bf == -1)
    294. {
    295. cur = parent;
    296. parent = parent->_parent;
    297. }
    298. //若parent->_bf == 2 && cur->_bf == 1,将parent进行左单旋
    299. else if (parent->_bf == 2 && cur->_bf == 1)
    300. {
    301. RotateL(parent);
    302. break;
    303. }
    304. //若parent->_bf == 2 && cur->_bf == -1,将parent进行右左单旋
    305. else if (parent->_bf == 2 && cur->_bf == -1)
    306. {
    307. RotateRL(parent);
    308. break;
    309. }
    310. //若parent->_bf == -2 && cur->_bf == -1,将parent进行右单旋
    311. else if (parent->_bf == -2 && cur->_bf == -1)
    312. {
    313. RotateR(parent);
    314. break;
    315. }
    316. //若parent->_bf == -2 && cur->_bf == 1,将parent进行左右单旋
    317. else if (parent->_bf == -2 && cur->_bf == 1)
    318. {
    319. RotateLR(parent);
    320. break;
    321. }
    322. else
    323. {
    324. assert(false);
    325. }
    326. }
    327. }
    328. else
    329. {
    330. _root = new Node(val);
    331. }
    332. return true;
    333. }
    334. int TreeHight(Node* root)
    335. {
    336. if (root == nullptr)
    337. return 0;
    338. int leftHight = TreeHight(root->_left);
    339. int rightHight = TreeHight(root->_right);
    340. return leftHight > rightHight ? leftHight + 1 : rightHight + 1;
    341. }
    342. void Inorder()
    343. {
    344. _Inorder(_root);
    345. }
    346. bool IsBalance()
    347. {
    348. return _IsBalance(_root);
    349. }
    350. private:
    351. void _Inorder(Node* root)
    352. {
    353. if (root == nullptr)
    354. return;
    355. _Inorder(root->_left);
    356. cout << root->_val << endl;
    357. _Inorder(root->_right);
    358. }
    359. bool _IsBalance(Node* root)
    360. {
    361. if (root == nullptr)
    362. return true;
    363. int leftHight = TreeHight(root->_left);
    364. int rightHight = TreeHight(root->_right);
    365. //检查平衡因子对不对
    366. if (rightHight - leftHight != root->_bf)
    367. {
    368. cout << "平衡因子出现异常" << endl;
    369. cout << rightHight - leftHight << endl;
    370. return false;
    371. }
    372. //需要递归检查是否平衡
    373. return (leftHight - rightHight <= 1 && leftHight - rightHight >= -1)
    374. && _IsBalance(root->_left) && _IsBalance(root->_right);
    375. }
    376. };
    377. void test_AVLTree()
    378. {
    379. /*vector v = { 6, 4, 32, 2, 7, 8 };
    380. AVLTree avl_tree(v);
    381. assert(avl_tree.IsBalance());*/
    382. AVLTree avl_tree;
    383. srand((unsigned int)time(NULL));
    384. for (int i = 1000; i >= 0; --i)
    385. {
    386. avl_tree.insert(rand());
    387. //avl_tree.insert(i);
    388. assert(avl_tree.IsBalance());
    389. }
    390. //srand((unsigned int)time(0));
    391. //const size_t N = 10000;
    392. //for (size_t i = 0; i < N; ++i)
    393. //{
    394. // size_t x = rand();
    395. // avl_tree.insert(x);
    396. // //cout << t.IsBalance() << endl;
    397. //}
    398. //avl_tree.Inorder();
    399. //cout << avl_tree.IsBalance() << endl;
    400. }
    401. }

    红黑树

    1. 红黑树的概念和性质(什么是红黑树,并且作为一颗红黑树的要求)

    8f14b4f1c0434c04abce9efca47479a1.png

    以上是红黑树的概念和性质,在红黑树里不仅仅要考虑 cur 、curleft 、 parent 还要引入 grandfather,具体为什么看到后面就知道了

    2. 红黑树类的属性

    是使用枚举枚举出 红 黑 两种情况

    58533f47adb74e74bda140814c9b16bd.png

    3. 红黑树的插入函数

    还是分情况讨论:

    4. 总结

    根据性质可以分为以下情况:

    可以看出第一种情况(uncle存在且为黑)只需要变色即可,在看是否继续向上调整

    第二种情况就要旋转了,而如何旋转本质图中也详细说了,取决于 grandfather、parent、cur 之间的关系,其实AVL树的旋转的决定因素也在此,只是转换成平衡因子进行描述

    关于红黑,具体的思想关键体现在插入函数中,复习请自行分析出两种大情况,和情况二的细分,然后写出插入函数,才算过关

    总体代码:

    1. #pragma once
    2. #include
    3. using namespace std;
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. #include
    16. #include
    17. #include
    18. #include
    19. namespace zhuandrong
    20. {
    21. enum Color
    22. {
    23. RED,
    24. BLACK
    25. };
    26. template<typename K, typename T>
    27. class RBTreeNode
    28. {
    29. typedef RBTreeNode Node;
    30. public:
    31. pair _t;
    32. Node* _left;
    33. Node* _right;
    34. Node* _parent;
    35. Color color;
    36. public:
    37. RBTreeNode(pair t)
    38. : _t(t)
    39. , _left(nullptr)
    40. , _right(nullptr)
    41. , _parent(nullptr)
    42. , color(RED)
    43. {}
    44. };
    45. template<typename K, typename T>
    46. class RBTree
    47. {
    48. typedef RBTreeNode Node;
    49. protected:
    50. Node* _root;
    51. protected:
    52. void RotateL(Node* parent)
    53. {
    54. assert(parent);
    55. Node* cur = parent->_right;
    56. Node* cur_left = cur->_left;
    57. // 改变节点之间的关系
    58. parent->_right = cur_left;
    59. cur->_left = parent;
    60. // 改变_parent的指向
    61. //原本 parent 的 _parent
    62. Node* ppNode = parent->_parent;
    63. //若原本 ppNode(原本 parent 的 _parent)为空,说明parent原本不是根,现需把 ppNode 给到 cur 的 _parent,并且把 ppNode 的子更新为 cur
    64. if (ppNode)
    65. {
    66. if (ppNode->_left == parent)
    67. {
    68. ppNode->_left = cur;
    69. }
    70. else
    71. {
    72. ppNode->_right = cur;
    73. }
    74. cur->_parent = ppNode;
    75. }
    76. //若原本 parent->_parent 为空,说明parent原本是根,现需把_root更新为根
    77. else
    78. {
    79. _root = cur;
    80. cur->_parent = nullptr;
    81. }
    82. if (cur_left)
    83. {
    84. cur_left->_parent = parent;
    85. }
    86. parent->_parent = cur;
    87. }
    88. void RotateR(Node* parent)
    89. {
    90. assert(parent);
    91. Node* cur = parent->_left;
    92. Node* cur_right = cur->_right;
    93. // 改变节点之间的关系
    94. parent->_left = cur_right;
    95. cur->_right = parent;
    96. // 改变_parent的指向
    97. //原本 parent 的 _parent
    98. Node* ppNode = parent->_parent;
    99. //若原本 ppNode(原本 parent 的 _parent)为空,说明parent原本不是根,现需把 ppNode 给到 cur 的 _parent,并且把 ppNode 的子更新为 cur
    100. if (ppNode)
    101. {
    102. if (ppNode->_left == parent)
    103. {
    104. ppNode->_left = cur;
    105. }
    106. else
    107. {
    108. ppNode->_right = cur;
    109. }
    110. cur->_parent = ppNode;
    111. }
    112. //若原本 parent->_parent 为空,说明parent原本是根,现需把_root更新为根
    113. else
    114. {
    115. _root = cur;
    116. cur->_parent = nullptr;
    117. }
    118. if (cur_right)
    119. {
    120. cur_right->_parent = parent;
    121. }
    122. parent->_parent = cur;
    123. }
    124. void RotateRL(Node* parent)
    125. {
    126. RotateR(parent->_right);
    127. RotateL(parent);
    128. }
    129. void RotateLR(Node* parent)
    130. {
    131. RotateL(parent->_left);
    132. RotateR(parent);
    133. }
    134. public:
    135. RBTree()
    136. : _root(nullptr)
    137. {}
    138. RBTree(vector > v)
    139. {
    140. for (auto& e : v)
    141. {
    142. if (e.second == 5)
    143. {
    144. int i = 0;
    145. }
    146. insert(e);
    147. }
    148. }
    149. bool insert(const pair t)
    150. {
    151. // 先判断根节点是否为空
    152. if (_root)
    153. {
    154. // 若不为空,先找到合适的插入位置
    155. Node* cur = _root;
    156. Node* parent = nullptr;
    157. while (cur)
    158. {
    159. if (t.second < cur->_t.second)
    160. {
    161. parent = cur;
    162. cur = cur->_left;
    163. }
    164. else if (t.second > cur->_t.second)
    165. {
    166. parent = cur;
    167. cur = cur->_right;
    168. }
    169. else
    170. {
    171. //cout << "该元素已经插入,请重试" << endl;
    172. return false;
    173. }
    174. }
    175. //找到该位置后进行插入并且链接关系
    176. cur = new Node(t);
    177. cur->_parent = parent;
    178. if (t.second < parent->_t.second)
    179. {
    180. parent->_left = cur;
    181. }
    182. else
    183. {
    184. parent->_right = cur;
    185. }
    186. // 进行调整
    187. while (parent && parent->color == RED)
    188. {
    189. Node* grandfather = parent->_parent;
    190. Node* uncle = nullptr;
    191. if (parent == grandfather->_left)
    192. {
    193. uncle = grandfather->_right;
    194. }
    195. else
    196. {
    197. uncle = grandfather->_left;
    198. }
    199. // 第一种情况:如果uncle存在且为红
    200. if (uncle && uncle->color == RED)
    201. {
    202. //将p和u变黑,g变红
    203. parent->color = uncle->color = BLACK;
    204. grandfather->color = RED;
    205. //更新,并且判断更新后的parent是否为根,不为根就继续调整;为根表明调整结束
    206. cur = grandfather;
    207. parent = cur->_parent;
    208. if (parent == _root)
    209. {
    210. break;
    211. }
    212. }
    213. // 第二种情况:如果uncle存在且为黑色或者uncle不存在
    214. else
    215. {
    216. // 当 cur 为 parent 的左孩子时
    217. if (parent->_left == cur)
    218. {
    219. if (grandfather->_left == parent)
    220. {
    221. // g
    222. // p u
    223. // c
    224. //
    225. Node* uncle = grandfather->_right;
    226. RotateR(grandfather);
    227. grandfather->color = cur->color = RED;
    228. parent->color = BLACK;
    229. }
    230. else
    231. {
    232. // g g c
    233. // u p --> u c --> g p
    234. // c p u
    235. //
    236. Node* uncle = grandfather->_left;
    237. RotateRL(grandfather);
    238. grandfather->color = parent->color = RED;
    239. cur->color = BLACK;
    240. }
    241. }
    242. // 当 cur 为 parent 的右孩子时
    243. else
    244. {
    245. if (grandfather->_right == parent)
    246. {
    247. // g
    248. // u p
    249. // c
    250. //
    251. Node* uncle = grandfather->_right;
    252. RotateL(grandfather);
    253. grandfather->color = cur->color = RED;
    254. parent->color = BLACK;
    255. }
    256. else
    257. {
    258. // g g c
    259. // p u --> c u --> p g
    260. // c p u
    261. //
    262. Node* uncle = grandfather->_left;
    263. RotateLR(grandfather);
    264. grandfather->color = parent->color = RED;
    265. cur->color = BLACK;
    266. }
    267. }
    268. break;
    269. }
    270. }
    271. }
    272. // 若为空,则该元素作为根节点
    273. else
    274. {
    275. _root = new Node(t);
    276. }
    277. _root->color = BLACK;
    278. return true;
    279. }
    280. bool judge_color(Node* root, int blacksum, int blacknum)
    281. {
    282. if (!root)
    283. {
    284. if (blacknum != blacksum)
    285. {
    286. return false;
    287. }
    288. return true;
    289. }
    290. if (root->color == BLACK)
    291. {
    292. ++blacknum;
    293. }
    294. if (root->color == RED && root->_parent && root->_parent->color == RED)
    295. {
    296. return false;
    297. }
    298. return judge_color(root->_left, blacksum, blacknum)
    299. && judge_color(root->_right, blacksum, blacknum);
    300. }
    301. bool isBalance()
    302. {
    303. if (!_root)
    304. {
    305. cout << "根为空" << endl;
    306. return false;
    307. }
    308. if (_root->color == RED)
    309. {
    310. cout << "根的颜色为红色,非法" << endl;
    311. return false;
    312. }
    313. Node* cur = _root;
    314. int blacksum = 0;
    315. while (cur)
    316. {
    317. if (cur->color == BLACK)
    318. {
    319. ++blacksum;
    320. }
    321. cur = cur->_right;
    322. }
    323. return judge_color(_root, blacksum, 0);
    324. }
    325. };
    326. void test_RBTree()
    327. {
    328. /*vector> v;
    329. v.push_back(make_pair(1, 13));
    330. v.push_back(make_pair(2, 8));
    331. v.push_back(make_pair(3, 17));
    332. v.push_back(make_pair(4, 1));
    333. v.push_back(make_pair(5, 11));
    334. v.push_back(make_pair(6, 15));
    335. v.push_back(make_pair(7, 25));
    336. v.push_back(make_pair(8, 6));
    337. v.push_back(make_pair(9, 22));
    338. v.push_back(make_pair(10, 27));
    339. v.push_back(make_pair(11, 5));
    340. RBTree rb_tree(v);
    341. cout << rb_tree.isBalance() << endl;*/
    342. RBTree<int, int> rb_tree;
    343. srand((unsigned int)time(NULL));
    344. for (int i = 0; i < 1000; ++i)
    345. {
    346. rb_tree.insert(make_pair(i, rand()));
    347. }
    348. if (rb_tree.isBalance())
    349. {
    350. cout << "本次测试成功" << endl;
    351. }
    352. else
    353. {
    354. cout << "本次测试失败" << endl;
    355. }
    356. }
    357. }

  • 相关阅读:
    当你学会这项python数据提取神器时,请做好升职准备!
    淘宝/天猫API:item_review-获取商品评论
    机器学习的初学术语掌握
    科技型中小企业认定条件
    HTML <tt> 标签
    CSS 属性计算
    为什么阿里Java开发手册不推荐使用Timestamp
    mysql的判断语句
    2023年8大在线渗透测试工具介绍与分析
    (四)激光线扫描-光平面标定
  • 原文地址:https://blog.csdn.net/qq_73575817/article/details/132893578