• 数据结构 红黄树 学习笔记


    首先我们了解一下红黑树的性质:

     

    在我们编写红黑树添加函数ADDRBT()之前   我们先编写几个工具函数 

    RBT* GetFather(RBT* pRoot, int id)       获得当前节点的父亲

    1. RBT* GetFather(RBT* pRoot, int id)
    2. {
    3. if (pRoot == NULL)
    4. {
    5. return nullptr;
    6. }
    7. while (pRoot != NULL)
    8. {
    9. if (pRoot->id > id)
    10. {
    11. if (pRoot->pLeft == NULL)
    12. {
    13. return pRoot;
    14. }
    15. pRoot = pRoot->pLeft;
    16. }
    17. else if (pRoot->id < id)
    18. {
    19. if (pRoot->pRight == NULL)
    20. {
    21. return pRoot;
    22. }
    23. pRoot = pRoot->pRight;
    24. }
    25. else
    26. {
    27. break;
    28. }
    29. }
    30. return nullptr;
    31. }

    RBT* GetUncle(RBT* pRoot)                   获得当前节点的叔叔

    1. RBT* GetUncle(RBT* pRoot)
    2. {
    3. if (pRoot == NULL || pRoot->pFather == NULL || pRoot->pFather->pFather == NULL)
    4. {
    5. return nullptr;
    6. }
    7. else
    8. {
    9. if (pRoot->pFather->pFather->pLeft == pRoot->pFather)
    10. {
    11. return pRoot->pFather->pFather->pRight;
    12. }
    13. else
    14. {
    15. return pRoot->pFather->pFather->pLeft;
    16. }
    17. }
    18. }

    void RightRotate(RBT* pRBT,RBT*& pBoot)     右旋当前节点

    1. void RightRotate(RBT* pRBT, RBT*& pBoot)
    2. {
    3. if (pRBT == nullptr || pRBT->pLeft == nullptr)
    4. {
    5. return;
    6. }
    7. //标记不平衡节点 A
    8. RBT* pMark = pRBT;
    9. //标记不平衡节点的左 B
    10. RBT* pTemp = pRBT->pLeft;
    11. //x pMark->pFather E pTemp->pRight
    12. //三个孩子
    13. //不平衡节点的左->不平衡节点的 左的右 A->左=E
    14. pMark->pLeft = pTemp->pRight;
    15. //不平衡节点左的右->不平衡节点 B->右=A
    16. pTemp->pRight = pMark;
    17. //不平衡节点是不是根
    18. //是 不平衡的节点变为根
    19. if (pMark->pFather == nullptr)
    20. {
    21. pBoot = pTemp;
    22. }
    23. //不是 判断不平衡节点是父亲的左还是右 (A是父亲的左还是右)
    24. else
    25. {
    26. //左:
    27. //不平衡节点的父亲的左孩子->不平衡节点 X->左=B
    28. if (pMark->pFather->pLeft == pMark)
    29. {
    30. pMark->pFather->pLeft = pTemp;
    31. }
    32. //右:
    33. //不平衡节点的父亲的右孩子->不平衡节点 X->右=B
    34. else
    35. {
    36. pMark->pFather->pRight = pTemp;
    37. }
    38. }
    39. if (pMark->pLeft != nullptr)
    40. {
    41. pMark->pLeft->pFather = pMark;
    42. }
    43. pTemp->pFather = pMark->pFather;
    44. pMark->pFather = pTemp;
    45. }

    void LeftRotate(RBT* pRBT, RBT*& pBoot)       左旋当前节点

    1. void LeftRotate(RBT* pRBT, RBT*& pBoot)
    2. {
    3. if (pRBT == nullptr || pRBT->pRight == nullptr)
    4. {
    5. return;
    6. }
    7. RBT* pMark = pRBT;
    8. RBT* pTemp = pRBT->pRight;
    9. pMark->pRight = pTemp->pLeft;
    10. pTemp->pLeft = pMark;
    11. if (pMark->pFather == nullptr)
    12. {
    13. pBoot = pTemp;
    14. }
    15. else
    16. {
    17. if (pMark->pFather->pLeft == pMark)
    18. {
    19. pMark->pFather->pLeft = pTemp;
    20. }
    21. else
    22. {
    23. pMark->pFather->pRight = pTemp;
    24. }
    25. }
    26. if (pMark->pRight != nullptr)
    27. {
    28. pMark->pRight->pFather = pMark;
    29. }
    30. pTemp->pFather = pMark->pFather;
    31. pMark->pFather = pTemp;
    32. }

    然后我们开始定义  void AddRBT(RBT*& rpBoot, int id)函数

    思想:

     

    首先  我们把思路列出来 如下列代码注释

    1. void AddRBT(RBT*& rpBoot, int id)
    2. {
    3. RBT* pFather = GetFather(rpBoot, id);
    4. RBT* pMark = new RBT;
    5. pMark->color = RED;
    6. pMark->id = id;
    7. pMark->pFather = pFather;
    8. pMark->pLeft = NULL;
    9. pMark->pRight = NULL;
    10. //判断根是否为空
    11. //空 pMark赋给根
    12. if (rpBoot == NULL)
    13. {
    14. pMark->color = BLACK;
    15. rpBoot = pMark;
    16. return;
    17. }
    18. //非空 添加
    19. if (pFather->id > pMark->id)
    20. {
    21. pFather->pLeft = pMark;
    22. }
    23. else
    24. {
    25. pFather->pRight = pMark;
    26. }
    27. //分析
    28. while (1)
    29. {
    30. //先给pFather和pUncle重新赋值
    31. pFather = pMark->pFather;
    32. //判断父亲的颜色
    33. //黑 直接加
    34. if (pFather->color == BLACK)
    35. {
    36. return;
    37. }
    38. RBT* pUncle = GetUncle(pMark);
    39. //父亲为红 判断叔叔的颜色
    40. //叔叔为红
    41. //父亲和叔叔都变黑
    42. //爷爷变红
    43. //判断爷爷是否为根
    44. //为根 爷爷变黑
    45. //不为根 爷爷赋给标记 结束当前循环 重新对爷爷进行分析
    46. if (pUncle != nullptr && pUncle->color == RED)
    47. {
    48. pFather->color = BLACK;
    49. pUncle->color = BLACK;
    50. pFather->pFather->color = RED;
    51. pMark = pFather->pFather;
    52. if (pMark->pFather == NULL)
    53. {
    54. pMark->color = BLACK;
    55. return;
    56. }
    57. continue;
    58. }
    59. //叔叔为黑 (包含空)
    60. if (pUncle == NULL||pUncle->color==BLACK)
    61. {
    62. //判断父亲是爷爷的左还是右孩子
    63. //左 判断标记是父亲的左还是由节点
    64. //左 爷爷变红 父亲变黑 对爷爷节点右旋 结束
    65. //右 爷爷变红 父亲赋值给标记 对标记左旋
    66. //右 判断标记是父亲的左还是由节点
    67. //右 爷爷变红 父亲变黑 对爷爷节点左旋 结束
    68. //左 爷爷变红 父亲赋值给标记 对标记右旋
    69. if (pFather == pFather->pFather->pLeft)
    70. {
    71. if (pFather->pRight == pMark)
    72. {
    73. pMark = pFather;
    74. LeftRotate(pMark, rpBoot);
    75. }
    76. else
    77. {
    78. pMark->pFather->pFather->color = RED;
    79. pMark->pFather->color = BLACK;
    80. RightRotate(pMark->pFather->pFather, rpBoot);
    81. return;
    82. }
    83. }
    84. //右
    85. if (pFather == pFather->pFather->pRight)
    86. {
    87. if (pFather->pLeft == pMark)
    88. {
    89. pMark = pFather;
    90. RightRotate(pMark, rpBoot);
    91. }
    92. else
    93. {
    94. pMark->pFather->pFather->color = RED;
    95. pMark->pFather->color = BLACK;
    96. LeftRotate(pMark->pFather->pFather, rpBoot);
    97. return;
    98. }
    99. }
    100. }
    101. }
    102. }

    delete函数思想:

     

    代码

    1. RBT* GetDeleteNode(RBT* rpBoot, int id)
    2. {
    3. while (rpBoot)
    4. {
    5. if (id > rpBoot->id)
    6. {
    7. rpBoot = rpBoot->pRight;
    8. }
    9. else if (id < rpBoot->id)
    10. {
    11. rpBoot = rpBoot->pLeft;
    12. }
    13. else if(id == rpBoot->id)
    14. {
    15. return rpBoot;
    16. }
    17. }
    18. return NULL;
    19. }
    20. void DeteleRBT(RBT*& rpBoot, int nId)
    21. {
    22. RBT* pDel = GetDeleteNode(rpBoot, nId);
    23. if (pDel == NULL)
    24. {
    25. return;
    26. }
    27. if (pDel->pLeft != NULL && pDel->pRight != NULL)
    28. {
    29. RBT* pMark = pDel;
    30. pDel = pDel->pRight;
    31. while (pDel->pLeft!=NULL)
    32. {
    33. pDel = pDel->pLeft;
    34. }
    35. pMark->id = pDel->id;
    36. }
    37. if (pDel->pFather == NULL)
    38. //根
    39. {
    40. if (pDel->pLeft == NULL && pDel->pRight == NULL)
    41. //判断有没有一个孩子
    42. {
    43. rpBoot = NULL;
    44. //没有孩子
    45. }
    46. else
    47. {
    48. //有孩子
    49. rpBoot = pDel->pLeft != NULL ? pDel->pLeft : pDel->pRight;
    50. rpBoot->color = BLACK;
    51. rpBoot->pFather = NULL;
    52. }
    53. delete pDel;
    54. pDel = NULL;
    55. return;
    56. }
    57. RBT* pFather =pDel->pFather;
    58. //非根
    59. //分析节点颜色
    60. if (pDel->color == RED)
    61. //红 直接删
    62. {
    63. if (pDel == pFather->pLeft)
    64. {
    65. pFather->pLeft = NULL;
    66. }
    67. else
    68. {
    69. pFather->pRight = NULL;
    70. }
    71. delete pDel;
    72. pDel = NULL;
    73. return;
    74. }
    75. //黑 判断节点是否有孩子
    76. if (pDel->pLeft != NULL || pDel->pRight != NULL)
    77. //有孩子 一定是红孩子
    78. {
    79. //红孩子变黑 与爷爷相连
    80. RBT* pChild = pDel->pLeft != NULL ? pDel->pLeft : pDel->pRight;
    81. pChild->color = BLACK;
    82. pChild->pFather = pFather;
    83. if (pFather->pLeft==pDel)
    84. {
    85. pFather->pLeft = pChild;
    86. }
    87. else
    88. {
    89. pFather->pRight = pChild;
    90. }
    91. delete pDel;
    92. pDel = NULL;
    93. return;
    94. }
    95. //没孩子
    96. //先获得兄弟 删除节点
    97. RBT* pBrother = GetBrother(pDel);
    98. if (pFather->pLeft == pDel)
    99. {
    100. pFather->pLeft = NULL;
    101. }
    102. else
    103. {
    104. pFather->pRight = NULL;
    105. }
    106. //分析兄弟颜色 loop
    107. while (1)
    108. {
    109. if (pBrother->color == RED)
    110. //兄弟为红
    111. {
    112. //父亲变红 兄弟变黑 分析兄弟方向
    113. pFather->color = RED;
    114. pBrother->color = BLACK;
    115. if (pFather->pLeft == pBrother)//兄弟为父亲的左
    116. {
    117. //以父亲为支点 右旋
    118. RightRotate(pFather, rpBoot);
    119. pBrother = pFather->pLeft;
    120. }
    121. else //兄弟为父亲的右
    122. {
    123. //以父亲为支点 左旋
    124. LeftRotate(pFather, rpBoot);
    125. pBrother = pFather->pRight;
    126. }
    127. continue;
    128. }
    129. if (pBrother->color == BLACK)
    130. //兄弟为黑
    131. // 分析两个侄子的颜色
    132. {
    133. if ((pBrother->pLeft == NULL && pBrother->pRight == NULL) ||
    134. ((pBrother->pLeft != NULL && pBrother->pLeft->color == BLACK) &&
    135. (pBrother->pRight != NULL && pBrother->pRight->color == BLACK)))
    136. {
    137. //两个侄子全黑(包括全为空) 分析父亲颜色
    138. if (pFather->color == RED)
    139. {
    140. //父亲为红 :父亲变黑 兄弟变红 结束
    141. pFather->color = BLACK;
    142. pBrother->color = RED;
    143. return;
    144. }
    145. else
    146. {
    147. //父亲为黑 : 兄弟变红 父亲为新的标记 更换兄弟 标记为根的时候结束 不为根继续分析
    148. pBrother->color = RED;
    149. pDel = pFather;
    150. if (pDel->pFather == NULL)
    151. {
    152. return;
    153. }
    154. continue;
    155. }
    156. }
    157. //左侄子红右侄子黑(空) 分析兄弟方向
    158. if ((pBrother->pLeft != NULL && pBrother->pLeft->color == RED) &&
    159. (pBrother->pRight == NULL || pBrother->pRight->color == BLACK))
    160. {
    161. //兄弟是父亲的右 兄弟变红 左侄子变黑 一兄弟为支点右旋 继续分析
    162. if (pBrother == pFather->pRight)
    163. {
    164. pBrother->color = RED;
    165. pBrother->pLeft->color = BLACK;
    166. RightRotate(pBrother, rpBoot);
    167. pBrother = pFather->pRight;
    168. continue;
    169. }
    170. //兄弟是父亲的左 父亲的颜色给兄弟 父亲变黑 左侄子变黑 以父亲为支点右旋 结束
    171. if (pFather->pLeft == pBrother)
    172. {
    173. pBrother->color = pFather->color;
    174. pFather->color = BLACK;
    175. pBrother->pLeft->color = BLACK;
    176. RightRotate(pFather, rpBoot);
    177. return;
    178. }
    179. }
    180. //右侄子红 分析兄弟方向
    181. if (pBrother->pRight != NULL && pBrother->pRight->color == RED)
    182. //兄弟是父亲的左 兄弟变红 右侄子变黑 以兄弟为支点左旋 继续分析
    183. if (pBrother == pFather->pLeft)
    184. {
    185. pBrother->color = RED;
    186. pBrother->pRight->color = BLACK;
    187. LeftRotate(pBrother, rpBoot);
    188. pBrother = pFather->pLeft;
    189. continue;
    190. }
    191. //兄弟是父亲的右 父亲的颜色给兄弟 父亲变黑 右侄子变黑 以父亲为支点左旋 结束
    192. if (pFather->pRight == pBrother)
    193. {
    194. pBrother->color = pFather->color;
    195. pFather->color = BLACK;
    196. pBrother->pRight->color = BLACK;
    197. LeftRotate(pFather, rpBoot);
    198. return;
    199. }
    200. }
    201. }
    202. }

    主函数中我们进行测试:

    1. RBT* Boot = NULL;
    2. int arr[] = { 11,2,14,1,7,15,5 ,8};
    3. for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    4. {
    5. AddRBT(Boot, arr[i]);
    6. }
    7. inorder(Boot);
    8. cout << "----------" << endl;
    9. AddRBT(Boot, 4);
    10. /*RBT* pBrother = GetBrother(Boot->pRight);
    11. cout << pBrother->id << endl;*/
    12. inorder(Boot);
    13. cout << "----------" << endl;
    14. //DeteleRBT(Boot, 1);
    15. DeteleRBT(Boot,8);
    16. inorder(Boot);
    17. return 0;

    这里我们添加了节点4   删除了节点8

    执行结果如下:

     

     

    完整代码如下

    1. #include
    2. #include
    3. using namespace std;
    4. //1.红黑树中所有的节点但不是红的就是黑的
    5. //2.
    6. enum COLOR { RED, BLACK };
    7. struct RBT
    8. {
    9. int id;
    10. RBT* pLeft;
    11. RBT* pRight;
    12. RBT* pFather;
    13. COLOR color;
    14. };
    15. RBT* GetFather(RBT* pRoot, int id)
    16. {
    17. if (pRoot == NULL)
    18. {
    19. return nullptr;
    20. }
    21. while (pRoot != NULL)
    22. {
    23. if (pRoot->id > id)
    24. {
    25. if (pRoot->pLeft == NULL)
    26. {
    27. return pRoot;
    28. }
    29. pRoot = pRoot->pLeft;
    30. }
    31. else if (pRoot->id < id)
    32. {
    33. if (pRoot->pRight == NULL)
    34. {
    35. return pRoot;
    36. }
    37. pRoot = pRoot->pRight;
    38. }
    39. else
    40. {
    41. cout << "不允许添加值相同的节点,数据有误" << endl;
    42. break;
    43. }
    44. }
    45. return nullptr;
    46. }
    47. RBT* GetUncle(RBT* pRoot)
    48. {
    49. if (pRoot == NULL || pRoot->pFather == NULL || pRoot->pFather->pFather == NULL)
    50. {
    51. return nullptr;
    52. }
    53. if (pRoot->pFather->pFather->pLeft == pRoot->pFather)
    54. {
    55. return pRoot->pFather->pFather->pRight;
    56. }
    57. else
    58. {
    59. return pRoot->pFather->pFather->pLeft;
    60. }
    61. }
    62. void RightRotate(RBT* pRBT, RBT*& pBoot)
    63. {
    64. if (pRBT == nullptr || pRBT->pLeft == nullptr)
    65. {
    66. return;
    67. }
    68. //标记不平衡节点 A
    69. RBT* pMark = pRBT;
    70. //标记不平衡节点的左 B
    71. RBT* pTemp = pRBT->pLeft;
    72. //x pMark->pFather E pTemp->pRight
    73. //三个孩子
    74. //不平衡节点的左->不平衡节点的 左的右 A->左=E
    75. pMark->pLeft = pTemp->pRight;
    76. //不平衡节点左的右->不平衡节点 B->右=A
    77. pTemp->pRight = pMark;
    78. //不平衡节点是不是根
    79. //是 不平衡的节点变为根
    80. if (pMark->pFather == nullptr)
    81. {
    82. pBoot = pTemp;
    83. }
    84. //不是 判断不平衡节点是父亲的左还是右 (A是父亲的左还是右)
    85. else
    86. {
    87. //左:
    88. //不平衡节点的父亲的左孩子->不平衡节点 X->左=B
    89. if (pMark->pFather->pLeft == pMark)
    90. {
    91. pMark->pFather->pLeft = pTemp;
    92. }
    93. //右:
    94. //不平衡节点的父亲的右孩子->不平衡节点 X->右=B
    95. else
    96. {
    97. pMark->pFather->pRight = pTemp;
    98. }
    99. }
    100. if (pMark->pLeft != nullptr)
    101. {
    102. pMark->pLeft->pFather = pMark;
    103. }
    104. pTemp->pFather = pMark->pFather;
    105. pMark->pFather = pTemp;
    106. }
    107. void LeftRotate(RBT* pRBT, RBT*& pBoot)
    108. {
    109. if (pRBT == nullptr || pRBT->pRight == nullptr)
    110. {
    111. return;
    112. }
    113. RBT* pMark = pRBT;
    114. RBT* pTemp = pRBT->pRight;
    115. pMark->pRight = pTemp->pLeft;
    116. pTemp->pLeft = pMark;
    117. if (pMark->pFather == nullptr)
    118. {
    119. pBoot = pTemp;
    120. }
    121. else
    122. {
    123. if (pMark->pFather->pLeft == pMark)
    124. {
    125. pMark->pFather->pLeft = pTemp;
    126. }
    127. else
    128. {
    129. pMark->pFather->pRight = pTemp;
    130. }
    131. }
    132. if (pMark->pRight != nullptr)
    133. {
    134. pMark->pRight->pFather = pMark;
    135. }
    136. pTemp->pFather = pMark->pFather;
    137. pMark->pFather = pTemp;
    138. }
    139. void AddRBT(RBT*& rpBoot, int id)
    140. {
    141. RBT* pFather = GetFather(rpBoot, id);
    142. RBT* pMark = new RBT;
    143. pMark->color = RED;
    144. pMark->id = id;
    145. pMark->pFather = pFather;
    146. pMark->pLeft = NULL;
    147. pMark->pRight = NULL;
    148. //判断根是否为空
    149. //空 pMark赋给根
    150. if (rpBoot == NULL)
    151. {
    152. pMark->color = BLACK;
    153. rpBoot = pMark;
    154. return;
    155. }
    156. //非空 添加
    157. if (pFather->id > pMark->id)
    158. {
    159. pFather->pLeft = pMark;
    160. }
    161. else
    162. {
    163. pFather->pRight = pMark;
    164. }
    165. //分析
    166. while (1)
    167. {
    168. //先给pFather和pUncle重新赋值
    169. pFather = pMark->pFather;
    170. //判断父亲的颜色
    171. //黑 直接加
    172. if (pFather->color == BLACK)
    173. {
    174. return;
    175. }
    176. RBT* pUncle = GetUncle(pMark);
    177. //父亲为红 判断叔叔的颜色
    178. //叔叔为红
    179. //父亲和叔叔都变黑
    180. //爷爷变红
    181. //判断爷爷是否为根
    182. //为根 爷爷变黑
    183. //不为根 爷爷赋给标记 结束当前循环 重新对爷爷进行分析
    184. if (pUncle != nullptr && pUncle->color == RED)
    185. {
    186. pFather->color = BLACK;
    187. pUncle->color = BLACK;
    188. pFather->pFather->color = RED;
    189. pMark = pFather->pFather;
    190. if (pMark->pFather == NULL)
    191. {
    192. pMark->color = BLACK;
    193. return;
    194. }
    195. continue;
    196. }
    197. //叔叔为黑 (包含空)
    198. if (pUncle == NULL||pUncle->color==BLACK)
    199. {
    200. //判断父亲是爷爷的左还是右孩子
    201. //左 判断标记是父亲的左还是由节点
    202. //左 爷爷变红 父亲变黑 对爷爷节点右旋 结束
    203. //右 爷爷变红 父亲赋值给标记 对标记左旋
    204. //右 判断标记是父亲的左还是由节点
    205. //右 爷爷变红 父亲变黑 对爷爷节点左旋 结束
    206. //左 爷爷变红 父亲赋值给标记 对标记右旋
    207. if (pFather == pFather->pFather->pLeft)
    208. {
    209. if (pFather->pRight == pMark)
    210. {
    211. pMark = pFather;
    212. LeftRotate(pMark, rpBoot);
    213. }
    214. else
    215. {
    216. pMark->pFather->pFather->color = RED;
    217. pMark->pFather->color = BLACK;
    218. RightRotate(pMark->pFather->pFather, rpBoot);
    219. return;
    220. }
    221. }
    222. //右
    223. if (pFather == pFather->pFather->pRight)
    224. {
    225. if (pFather->pLeft == pMark)
    226. {
    227. pMark = pFather;
    228. RightRotate(pMark, rpBoot);
    229. }
    230. else
    231. {
    232. pMark->pFather->pFather->color = RED;
    233. pMark->pFather->color = BLACK;
    234. LeftRotate(pMark->pFather->pFather, rpBoot);
    235. return;
    236. }
    237. }
    238. }
    239. }
    240. }
    241. RBT* GetBrother(RBT* rpBoot)
    242. {
    243. if (rpBoot == NULL || rpBoot->pFather == NULL)
    244. {
    245. return NULL;
    246. }
    247. return rpBoot == rpBoot->pFather->pLeft ? rpBoot->pFather->pRight : rpBoot->pFather->pLeft;
    248. }
    249. RBT* GetDeleteNode(RBT* rpBoot, int id)
    250. {
    251. while (rpBoot)
    252. {
    253. if (id > rpBoot->id)
    254. {
    255. rpBoot = rpBoot->pRight;
    256. }
    257. else if (id < rpBoot->id)
    258. {
    259. rpBoot = rpBoot->pLeft;
    260. }
    261. else if(id == rpBoot->id)
    262. {
    263. return rpBoot;
    264. }
    265. }
    266. return NULL;
    267. }
    268. void DeteleRBT(RBT*& rpBoot, int nId)
    269. {
    270. RBT* pDel = GetDeleteNode(rpBoot, nId);
    271. if (pDel == NULL)
    272. {
    273. return;
    274. }
    275. if (pDel->pLeft != NULL && pDel->pRight != NULL)
    276. {
    277. RBT* pMark = pDel;
    278. pDel = pDel->pRight;
    279. while (pDel->pLeft!=NULL)
    280. {
    281. pDel = pDel->pLeft;
    282. }
    283. pMark->id = pDel->id;
    284. }
    285. if (pDel->pFather == NULL)
    286. //根
    287. {
    288. if (pDel->pLeft == NULL && pDel->pRight == NULL)
    289. //判断有没有一个孩子
    290. {
    291. rpBoot = NULL;
    292. //没有孩子
    293. }
    294. else
    295. {
    296. //有孩子
    297. rpBoot = pDel->pLeft != NULL ? pDel->pLeft : pDel->pRight;
    298. rpBoot->color = BLACK;
    299. rpBoot->pFather = NULL;
    300. }
    301. delete pDel;
    302. pDel = NULL;
    303. return;
    304. }
    305. RBT* pFather =pDel->pFather;
    306. //非根
    307. //分析节点颜色
    308. if (pDel->color == RED)
    309. //红 直接删
    310. {
    311. if (pDel == pFather->pLeft)
    312. {
    313. pFather->pLeft = NULL;
    314. }
    315. else
    316. {
    317. pFather->pRight = NULL;
    318. }
    319. delete pDel;
    320. pDel = NULL;
    321. return;
    322. }
    323. //黑 判断节点是否有孩子
    324. if (pDel->pLeft != NULL || pDel->pRight != NULL)
    325. //有孩子 一定是红孩子
    326. {
    327. //红孩子变黑 与爷爷相连
    328. RBT* pChild = pDel->pLeft != NULL ? pDel->pLeft : pDel->pRight;
    329. pChild->color = BLACK;
    330. pChild->pFather = pFather;
    331. if (pFather->pLeft==pDel)
    332. {
    333. pFather->pLeft = pChild;
    334. }
    335. else
    336. {
    337. pFather->pRight = pChild;
    338. }
    339. delete pDel;
    340. pDel = NULL;
    341. return;
    342. }
    343. //没孩子
    344. //先获得兄弟 删除节点
    345. RBT* pBrother = GetBrother(pDel);
    346. if (pFather->pLeft == pDel)
    347. {
    348. pFather->pLeft = NULL;
    349. }
    350. else
    351. {
    352. pFather->pRight = NULL;
    353. }
    354. //分析兄弟颜色 loop
    355. while (1)
    356. {
    357. if (pBrother->color == RED)
    358. //兄弟为红
    359. {
    360. //父亲变红 兄弟变黑 分析兄弟方向
    361. pFather->color = RED;
    362. pBrother->color = BLACK;
    363. if (pFather->pLeft == pBrother)//兄弟为父亲的左
    364. {
    365. //以父亲为支点 右旋
    366. RightRotate(pFather, rpBoot);
    367. pBrother = pFather->pLeft;
    368. }
    369. else //兄弟为父亲的右
    370. {
    371. //以父亲为支点 左旋
    372. LeftRotate(pFather, rpBoot);
    373. pBrother = pFather->pRight;
    374. }
    375. continue;
    376. }
    377. if (pBrother->color == BLACK)
    378. //兄弟为黑
    379. // 分析两个侄子的颜色
    380. {
    381. if ((pBrother->pLeft == NULL && pBrother->pRight == NULL) ||
    382. ((pBrother->pLeft != NULL && pBrother->pLeft->color == BLACK) &&
    383. (pBrother->pRight != NULL && pBrother->pRight->color == BLACK)))
    384. {
    385. //两个侄子全黑(包括全为空) 分析父亲颜色
    386. if (pFather->color == RED)
    387. {
    388. //父亲为红 :父亲变黑 兄弟变红 结束
    389. pFather->color = BLACK;
    390. pBrother->color = RED;
    391. return;
    392. }
    393. else
    394. {
    395. //父亲为黑 : 兄弟变红 父亲为新的标记 更换兄弟 标记为根的时候结束 不为根继续分析
    396. pBrother->color = RED;
    397. pDel = pFather;
    398. if (pDel->pFather == NULL)
    399. {
    400. return;
    401. }
    402. continue;
    403. }
    404. }
    405. //左侄子红右侄子黑(空) 分析兄弟方向
    406. if ((pBrother->pLeft != NULL && pBrother->pLeft->color == RED) &&
    407. (pBrother->pRight == NULL || pBrother->pRight->color == BLACK))
    408. {
    409. //兄弟是父亲的右 兄弟变红 左侄子变黑 一兄弟为支点右旋 继续分析
    410. if (pBrother == pFather->pRight)
    411. {
    412. pBrother->color = RED;
    413. pBrother->pLeft->color = BLACK;
    414. RightRotate(pBrother, rpBoot);
    415. pBrother = pFather->pRight;
    416. continue;
    417. }
    418. //兄弟是父亲的左 父亲的颜色给兄弟 父亲变黑 左侄子变黑 以父亲为支点右旋 结束
    419. if (pFather->pLeft == pBrother)
    420. {
    421. pBrother->color = pFather->color;
    422. pFather->color = BLACK;
    423. pBrother->pLeft->color = BLACK;
    424. RightRotate(pFather, rpBoot);
    425. return;
    426. }
    427. }
    428. //右侄子红 分析兄弟方向
    429. if (pBrother->pRight != NULL && pBrother->pRight->color == RED)
    430. //兄弟是父亲的左 兄弟变红 右侄子变黑 以兄弟为支点左旋 继续分析
    431. if (pBrother == pFather->pLeft)
    432. {
    433. pBrother->color = RED;
    434. pBrother->pRight->color = BLACK;
    435. LeftRotate(pBrother, rpBoot);
    436. pBrother = pFather->pLeft;
    437. continue;
    438. }
    439. //兄弟是父亲的右 父亲的颜色给兄弟 父亲变黑 右侄子变黑 以父亲为支点左旋 结束
    440. if (pFather->pRight == pBrother)
    441. {
    442. pBrother->color = pFather->color;
    443. pFather->color = BLACK;
    444. pBrother->pRight->color = BLACK;
    445. LeftRotate(pFather, rpBoot);
    446. return;
    447. }
    448. }
    449. }
    450. }
    451. ostream& operator <<(ostream& os, COLOR color)
    452. {
    453. if (color == RED)
    454. {
    455. os << "红";
    456. }
    457. if (color == BLACK)
    458. {
    459. os << "黑";
    460. }
    461. return os;
    462. }
    463. void inorder(RBT*& Boot)
    464. {
    465. if (Boot == NULL)
    466. {
    467. return;
    468. }
    469. inorder(Boot->pLeft);
    470. cout << Boot->id << " " << Boot->color << endl;
    471. inorder(Boot->pRight);
    472. }
    473. int main()
    474. {
    475. RBT* Boot = NULL;
    476. int arr[] = { 11,2,14,1,7,15,5 ,8};
    477. for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    478. {
    479. AddRBT(Boot, arr[i]);
    480. }
    481. inorder(Boot);
    482. cout << "----------" << endl;
    483. AddRBT(Boot, 4);
    484. /*RBT* pBrother = GetBrother(Boot->pRight);
    485. cout << pBrother->id << endl;*/
    486. inorder(Boot);
    487. cout << "----------" << endl;
    488. //存疑 :
    489. // Add节点4 之后 8的节点的父亲应该是11 代码中的8 的父亲是7 未能找到原因 ??
    490. // 解决这个问题 代码就差不多没问题了
    491. //DeteleRBT(Boot, 1);
    492. DeteleRBT(Boot,7);
    493. inorder(Boot);
    494. return 0;
    495. }

  • 相关阅读:
    【leetcode】206. 反转链表 (简单)
    Element的MessageBox自定义图标
    win安装vue并运行 vue-admin-template
    Fiddler入门:下载、安装、配置、抓包、customize rules
    sap业务伙伴分组后台配置的问题
    Chrome iframe 跨域失败
    [c/c++进阶必刷题(一)]
    Java毕业设计-快递物流管理系统
    云原生:使用HPA和VPA实现集群扩缩容
    LeetCode 901. 股票价格跨度【单调栈】1708
  • 原文地址:https://blog.csdn.net/van9527/article/details/125819553