当前位置:   article > 正文

C++实现红黑树_c遍历红黑树

c遍历红黑树

红黑树的基本概念:

红黑树是一个平衡二叉树(左子节点比当前节点小,右子节点比当前节点大)。

一棵红黑树需要满足以下条件:

1.根节点的颜色是黑色的。

2.一个节点要么是黑色,要么是红色。

3.红色节点的子节点必须是黑色节点。(红色节点被黑色节点隔开)

4.叶子节点的颜色是黑色的。

5.从根节点出发到叶子节点,每一条路径的黑色节点数量是相同的。(黑高)。

红黑树的类声明:

  1. #include"iostream"
  2. #include"math.h"
  3. using namespace std;
  4. #define RED 0
  5. #define BLACK 1
  6. class RBtree{
  7. private:
  8. // 红黑树的属性
  9. public:
  10. RBtree();
  11. // 根节点
  12. RBtree *root;
  13. // 数据
  14. int data;
  15. // 颜色
  16. bool color;
  17. // 父亲节点
  18. RBtree *parent;
  19. // 左子节点
  20. RBtree *left;
  21. // 右子节点
  22. RBtree *right;
  23. // 节点插入函数,传入一个数据和一个根节点
  24. RBtree *rbinsert(int data,RBtree *root);
  25. // 节点删除传入一个要删除的数据和一个节点
  26. RBtree *rbdelete(int data,RBtree *root);
  27. // 节点的查找
  28. RBtree *rbsearch(int data,RBtree *root);
  29. // 最大值
  30. RBtree *rbmax(RBtree *root);
  31. // 最小值
  32. RBtree *rbmin(RBtree *root);
  33. // 右旋转
  34. RBtree *rrotate(RBtree *root,RBtree *x);
  35. // 左旋转
  36. RBtree *lrotate(RBtree *root,RBtree *x);
  37. // 插入修复
  38. RBtree *rbinsertfixup(RBtree *x);
  39. // 树的遍历
  40. void rbprint(RBtree *x);
  41. ~RBtree();
  42. };

红黑树的插入:

  1. #include"RBtree.h"
  2. // 插入修复
  3. RBtree *insert_fixup(RBtree *root,RBtree *x)
  4. {
  5. // 如果x的父节点的color是red,并且x节点不是root节点
  6. while (x->parent && x->parent->color==RED)
  7. {
  8. // 如果x的父是在祖父节点的左边
  9. if(x->parent == x->parent->parent->left)
  10. {
  11. // 确定叔叔节点
  12. RBtree *y = x->parent->parent->right;
  13. // 情况1:y节点的颜色是red,并且y不是空节点
  14. if(y && y->color==RED)
  15. {
  16. x->parent->color=BLACK;
  17. y->color=BLACK;
  18. x= y->parent;
  19. x->color=RED;
  20. }
  21. // 情况2:y节点是黑色的,并且x的位置是三角型
  22. else
  23. if(x==x->parent->right)
  24. {
  25. x=x->parent;
  26. root=root->lrotate(root,x);
  27. }
  28. // 情况3:y的节点是黑色,并且x的位置是直线
  29. else
  30. {
  31. x->parent->color=BLACK;
  32. x->parent->parent->color=RED;
  33. root=root->rrotate(root,x->parent->parent);
  34. }
  35. }
  36. else
  37. // x的父节点在祖父节点的右边
  38. {
  39. // 确定叔叔节点
  40. RBtree *y = x->parent->parent->left;
  41. // 情况1:y节点的颜色是red,并且y不是空节点
  42. if(y && y->color==RED)
  43. {
  44. x->parent->color=BLACK;
  45. y->color=BLACK;
  46. x= y->parent;
  47. x->color=RED;
  48. }
  49. // 情况2:y节点是黑色的,并且x的位置是三角型
  50. else
  51. if(x==x->parent->left)
  52. {
  53. x=x->parent;
  54. root=root->rrotate(root,x);
  55. }
  56. // 情况3:y的节点是黑色,并且x的位置是直线
  57. else
  58. {
  59. x->parent->color=BLACK;
  60. x->parent->parent->color=RED;
  61. root=root->lrotate(root,x->parent->parent);
  62. }
  63. }
  64. }
  65. // 根节点的颜色始终是黑色
  66. root->color=BLACK;
  67. return root;
  68. }
  69. RBtree * RBtree::rbinsert(int data,RBtree *root)
  70. {
  71. // 实现将data插入rbtree
  72. // 创建一个节点得到数据
  73. RBtree *newnode = new RBtree;
  74. newnode->data = data;
  75. // 如果root为空,第一个节点
  76. if(root== nullptr)
  77. {
  78. // 直接就是根节点
  79. root=newnode;
  80. }
  81. // 如果root不为空
  82. // 开始插入
  83. else
  84. {
  85. //辅助指针
  86. RBtree *x = root;
  87. RBtree *y;
  88. // 如果x不为空
  89. while(x)
  90. {
  91. // y的位置始终在x的后面
  92. y=x;
  93. // 如果newnode的data比x的data
  94. if(newnode->data<x->data)
  95. {
  96. // 从左边走
  97. x=x->left;
  98. }
  99. else
  100. {
  101. // 从右边走
  102. x=x->right;
  103. }
  104. }
  105. // 开始连接
  106. // 确定newnode的父节点
  107. newnode->parent=y;
  108. if(newnode->data<y->data)
  109. {
  110. // 连接左边
  111. y->left=newnode;
  112. }
  113. else
  114. {
  115. y->right=newnode;
  116. }
  117. }
  118. // 对newnode节点进行修复
  119. root=insert_fixup(root,newnode);
  120. return root;
  121. }

红黑树的删除:

  1. #include"RBtree.h"
  2. RBtree *delete_fixup(RBtree *root,RBtree *x)
  3. {
  4. while(x!=root && x->color==BLACK)
  5. {
  6. // 判断x的位置
  7. if(x==x->parent->left)
  8. {
  9. // 确定w节点
  10. RBtree *w=x->parent->right;
  11. // 情况1:w是红色节点
  12. if(w->color==RED)
  13. {
  14. // 将w的颜色染成黑色
  15. w->color=BLACK;
  16. // x的父节点的颜色染成红色
  17. x->parent->color=RED;
  18. // 对x的父节点左旋
  19. root=root->lrotate(root,x->parent);
  20. // 使得w成为新的兄弟节点
  21. w=x->parent->right;
  22. }
  23. // 情况2:w的左右子节点都是黑色,或者w左右都是空节点,因为空节点的颜色本来就是黑色的
  24. if((w->left==nullptr && w->right==nullptr)
  25. // 或者w的left是一个黑节点或者w的right节点是一个空节点
  26. || (w->left && w->left->color==BLACK && w->right==nullptr)
  27. // 或者w的right是一个黑色节点或者w的left节点是一个空节点
  28. || ((w->right && w->right->color==BLACK && w->left==nullptr))
  29. || (
  30. // 确保w的左边和右边不是空节点
  31. (w->left && w->right)
  32. &&
  33. // 确保w的左边和右边都是黑色节点
  34. (w->left->color==BLACK && w->right->color==BLACK)
  35. )
  36. )
  37. {
  38. // w的颜色直接染成红色
  39. w->color=RED;
  40. // x直接上移一个
  41. x=x->parent;
  42. }
  43. // 情况3:w右孩子是黑色,或者w的右孩子是空的
  44. else
  45. if(w->right==nullptr || w->right->color==BLACK)
  46. {
  47. w->left->color=BLACK;
  48. w->color=RED;
  49. root=root->rrotate(root,w);
  50. w=x->parent->right;
  51. }
  52. // 情况4:结束
  53. else
  54. {
  55. w->color=x->parent->color;
  56. x->parent->color=BLACK;
  57. // 判断w的right是否是节点
  58. if(w->right)
  59. {
  60. w->right->color=BLACK;
  61. }
  62. root=root->lrotate(root,x->parent);
  63. x=root;
  64. }
  65. }
  66. else
  67. {
  68. // 确定w节点
  69. RBtree *w=x->parent->left;
  70. // 情况1:w是红色节点
  71. if(w->color==RED)
  72. {
  73. // 将w的颜色染成黑色
  74. w->color=BLACK;
  75. // x的父节点的颜色染成红色
  76. x->parent->color=RED;
  77. // 对x的父节点右旋
  78. root=root->rrotate(root,x->parent);
  79. w=x->parent->left;
  80. }
  81. // 情况2:w的左右子节点都是黑色,或者w左右都是空节点,因为空节点的颜色本来就是黑色的
  82. if((w->left==nullptr && w->right==nullptr)
  83. // 或者w的left是一个黑节点或者w的right节点是一个空节点
  84. || (w->left && w->left->color==BLACK && w->right==nullptr)
  85. // 或者w的right是一个黑色节点或者w的left节点是一个黑色节点
  86. || ((w->right && w->right->color==BLACK && w->left==nullptr))
  87. || (
  88. // 确保w的左边和右边不是空节点
  89. (w->left && w->right)
  90. &&
  91. // 确保w的左边和右边都是黑色节点
  92. (w->left->color==BLACK && w->right->color==BLACK)
  93. )
  94. )
  95. {
  96. // w的颜色直接染成红色
  97. w->color=RED;
  98. // x直接上移一个
  99. x=x->parent;
  100. }
  101. // 情况3:w右孩子是黑色,或者w的右孩子是空的
  102. else
  103. if(w->left==nullptr || w->left->color==BLACK)
  104. {
  105. w->right->color=BLACK;
  106. w->color=RED;
  107. root=root->lrotate(root,w);
  108. w=x->parent->left;
  109. }
  110. // 情况4:结束
  111. else
  112. {
  113. w->color=x->parent->color;
  114. x->parent->color=BLACK;
  115. // 判断w的left是否是节点
  116. if(w->left)
  117. {
  118. w->left->color=BLACK;
  119. }
  120. root=root->rrotate(root,x->parent);
  121. x=root;
  122. }
  123. }
  124. }
  125. x->color=BLACK;
  126. return root;
  127. }
  128. RBtree *RBtree::rbdelete(int data,RBtree *root)
  129. {
  130. // 搜索节点要删除的节点
  131. RBtree *delenode = root->rbsearch(data,root);
  132. // 直到delenode被释放
  133. while(delenode!=nullptr)
  134. {
  135. // 如果删除的是根节点
  136. if(delenode == root)
  137. {
  138. // 如果根节点有两个子节点
  139. if(delenode->right && delenode->left)
  140. {
  141. // 首先找到delenode的right的最小值
  142. RBtree *rmin = delenode->rbmin(delenode->right);
  143. // 把rmin的data给到delenode的data
  144. delenode->data=rmin->data;
  145. // 直接去删除rmin
  146. delenode = rmin;
  147. // // 就直接把delenode的data改成,deletnode的right的最小值
  148. // delenode->data=delenode->right->rbmin(delenode->right)->data;
  149. // // 去删除delenode
  150. // delenode=delenode->right->rbmin(delenode->right);
  151. }
  152. else
  153. // 如果根节点只有一个右节点
  154. if(delenode->right)
  155. {
  156. // 对delenode 修复
  157. root=delete_fixup(root,delenode);
  158. // 新的根
  159. root=delenode->right;
  160. root->parent = nullptr;
  161. //删除根
  162. delete delenode;
  163. delenode =nullptr;
  164. }
  165. else
  166. // 根节点只有一个左节点
  167. if(delenode->left)
  168. {
  169. // 对delenode 修复
  170. root=delete_fixup(root,delenode);
  171. root=delenode->left;
  172. root->parent=nullptr;
  173. delete delenode;
  174. delenode = nullptr;
  175. }
  176. else
  177. // 删除根节点
  178. {
  179. root =nullptr;
  180. delete delenode;
  181. delenode = nullptr;
  182. }
  183. }
  184. // 删除的是除了根节点以外的节点
  185. else
  186. {
  187. // 判断要删除节点的方向
  188. if(delenode->parent->left==delenode)
  189. {
  190. // 要删除的节点在delenod的父节点的左边
  191. //
  192. if(delenode->right && delenode->left)
  193. {
  194. // 情况1:delenode有两个子节点
  195. RBtree *rmin = root->rbmin(delenode->right);
  196. // 替换内容
  197. delenode->data=rmin->data;
  198. // 直接删除rmin
  199. delenode = rmin;
  200. // 将第四种情况转换成第一种情况
  201. }
  202. else
  203. if(delenode->left)
  204. {
  205. // 对delenode 修复
  206. root=delete_fixup(root,delenode);
  207. // 情况2:deletnode有一个left节点
  208. // delenode父节点的左边连接denode的左边
  209. delenode->parent->left=delenode->left;
  210. // delenode的的左孩子的父节点连接delenode的父节点
  211. delenode->left->parent=delenode->parent;
  212. // 删除节点
  213. delete delenode;
  214. delenode = nullptr;
  215. }
  216. else
  217. if(delenode->right)
  218. {
  219. // 对delenode 修复
  220. root=delete_fixup(root,delenode);
  221. // 情况3:deletnode有一个right节点
  222. // delenode父节点的左边连接denode的左边
  223. delenode->parent->left=delenode->right;
  224. // delenode的的左孩子的父节点连接delenode的父节点
  225. delenode->right->parent=delenode->parent;
  226. // 删除节点
  227. delete delenode;
  228. delenode = nullptr;
  229. }
  230. else
  231. {
  232. // 对delenode 修复
  233. root=delete_fixup(root,delenode);
  234. // 情况4:delenode没有子节点
  235. delenode->parent->left =nullptr;
  236. delete delenode;
  237. delenode=nullptr;
  238. }
  239. }
  240. else
  241. {
  242. // 要删除的节点在delenod的父节点的右边
  243. //
  244. if(delenode->right && delenode->left)
  245. {
  246. // 情况1:delenode有两个子节点
  247. RBtree *rmin = root->rbmin(delenode->right);
  248. // 替换内容
  249. delenode->data=rmin->data;
  250. // 直接删除rmin
  251. delenode = rmin;
  252. // 将第四种情况转换成第一种情况
  253. }
  254. else
  255. if(delenode->left)
  256. {
  257. // 对delenode 修复
  258. root=delete_fixup(root,delenode);
  259. // 情况2:deletnode有一个left节点
  260. // delenode父节点的左边连接denode的左边
  261. delenode->parent->right=delenode->left;
  262. // delenode的的左孩子的父节点连接delenode的父节点
  263. delenode->left->parent=delenode->parent;
  264. // 删除节点
  265. delete delenode;
  266. delenode = nullptr;
  267. }
  268. else
  269. if(delenode->right)
  270. {
  271. // 对delenode 修复
  272. root=delete_fixup(root,delenode);
  273. // 情况3:deletnode有一个right节点
  274. // delenode父节点的左边连接denode的左边
  275. delenode->parent->right=delenode->right;
  276. // delenode的的左孩子的父节点连接delenode的父节点
  277. delenode->right->parent=delenode->parent;
  278. // 删除节点
  279. delete delenode;
  280. delenode = nullptr;
  281. }
  282. else
  283. {
  284. // 对delenode 修复
  285. root=delete_fixup(root,delenode);
  286. // 情况4:delenode没有子节点
  287. delenode->parent->right =nullptr;
  288. delete delenode;
  289. delenode=nullptr;
  290. }
  291. }
  292. }
  293. }
  294. return root;
  295. }

寻找节点的最大值

  1. // 查找最大值
  2. #include"RBtree.h"
  3. RBtree *RBtree::rbmax(RBtree *root)
  4. {
  5. RBtree *x =root;
  6. RBtree *y;
  7. while (x)
  8. {
  9. y=x;
  10. x=x->right;
  11. }
  12. return y;
  13. }

寻找最小值:

  1. // 查找最小值
  2. #include"RBtree.h"
  3. RBtree *RBtree::rbmin(RBtree *root)
  4. {
  5. RBtree *x =root;
  6. RBtree *y;
  7. while (x)
  8. {
  9. y=x;
  10. x=x->left;
  11. }
  12. return y;
  13. }

红黑树的遍历输出:

  1. #include"RBtree.h"
  2. // 树的遍历
  3. void RBtree::rbprint(RBtree *x)
  4. {
  5. if(x)
  6. {
  7. rbprint(x->left);
  8. cout<<x->data<<endl;
  9. rbprint(x->right);
  10. }
  11. }

红黑树的查找:

  1. #include"RBtree.h"
  2. // rb树的查找
  3. RBtree* RBtree::rbsearch(int data,RBtree *root)
  4. {
  5. RBtree *snode =root;
  6. while (snode!=nullptr)
  7. {
  8. // 如果snode的datadata要小
  9. if(snode->data<data)
  10. {
  11. // 右边走
  12. snode=snode->right;
  13. }
  14. // 如果snode的datadata要大
  15. else if(snode->data>data)
  16. {
  17. // 左边边走
  18. snode = snode->left;
  19. }
  20. else
  21. {
  22. // 找到了
  23. // 返回这个节点的地址
  24. return snode;
  25. }
  26. }
  27. return nullptr;
  28. }

红黑树的左旋:

  1. #include"RBtree.h"
  2. // 左旋转
  3. RBtree *RBtree::lrotate(RBtree *root,RBtree *x)
  4. {
  5. // 根节点的旋转
  6. RBtree *y;
  7. // y在x的右边
  8. y=x->right;
  9. // 开始旋转
  10. if(x == root)
  11. {
  12. // 如果x的right不是空节点
  13. if(x->right)
  14. {
  15. // x的右边
  16. x->right=y->left;
  17. // 判断y的left是否有节点
  18. if(y->left)
  19. {
  20. y->left->parent=x;
  21. }
  22. // y的左边
  23. y->left=x;
  24. x->parent=y;
  25. // 连接root
  26. root=y;
  27. y->parent=nullptr;
  28. }
  29. }
  30. else
  31. {
  32. // 判断x是左孩子还是右孩子
  33. if(x->parent->left==x)
  34. {
  35. // x在父节点的左边
  36. // 改变x父节点到y
  37. x->parent->left=y;
  38. }
  39. else
  40. {
  41. // x在父节点的右边
  42. // 改变x父节点到y
  43. x->parent->right=y;
  44. }
  45. y->parent=x->parent;
  46. // x的右边
  47. x->right=y->left;
  48. // 判断y是否有left节点
  49. if(y->left)
  50. {
  51. y->left->parent=x;
  52. }
  53. // y的左边
  54. y->left=x;
  55. x->parent=y;
  56. }
  57. return root;
  58. }

红黑树的右旋:

  1. #include"RBtree.h"
  2. // 右旋转
  3. RBtree *RBtree::rrotate(RBtree *root,RBtree *x)
  4. {
  5. // 根节点的旋转
  6. RBtree *y;
  7. // y在x的左边
  8. y=x->left;
  9. // 开始旋转
  10. if(x == root)
  11. {
  12. // 如果x的left不是空节点
  13. if(x->left)
  14. {
  15. // x的左边
  16. x->left=y->right;
  17. // 判断y的left是否有节点
  18. if(y->right)
  19. {
  20. y->right->parent=x;
  21. }
  22. // y的右边
  23. y->right=x;
  24. x->parent=y;
  25. // 连接root
  26. root=y;
  27. y->parent=nullptr;
  28. }
  29. }
  30. else
  31. {
  32. // 判断x是左孩子还是右孩子
  33. if(x->parent->right==x)
  34. {
  35. // x在父节点的右边
  36. // 改变x父节点到y
  37. x->parent->right=y;
  38. }
  39. else
  40. {
  41. // x在父节点的右边
  42. // 改变x父节点到y
  43. x->parent->left=y;
  44. }
  45. y->parent=x->parent;
  46. // x的左边
  47. x->left=y->right;
  48. // 判断y是否有left节点
  49. if(y->right)
  50. {
  51. y->right->parent=x;
  52. }
  53. // y的右边
  54. y->right=x;
  55. x->parent=y;
  56. }
  57. return root;
  58. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/246254
推荐阅读
相关标签
  

闽ICP备14008679号