• C++实现红黑树


    1.红黑树的基本概念

     2.节点的定义

    1. // 基本定义
    2. enum RBTColor{RED, BLACK};
    3. template<class T>
    4. class RBTNode{
    5. public:
    6. RBTColor color; // 颜色
    7. T key; // 键值
    8. RBTNode* left; // 左孩子
    9. RBTNode* right; // 右孩子
    10. RBTNode* parent; // 父节点
    11. RBTNode(T value, RBTColor c, RBTNode* p, RBTNode* l, RBTNode* r):
    12. key(value),color(c),parent(p),left(l),right(r){
    13. }
    14. };

    3.红黑树类的定义

    1. template<class T>
    2. class RBTree{
    3. private:
    4. RBTNode<T>* mRoot;
    5. public:
    6. RBTree();
    7. ~RBTree();
    8. // 前序遍历
    9. void preOrder();
    10. // 中序遍历
    11. void inOrder();
    12. // 后序遍历
    13. void postOrder();
    14. RBTNode<T>* iterativeSearch(T key);
    15. // (递归实现)查找”红黑树“中键值为key的节点
    16. RBTNode<T>* search(T key);
    17. // 查找最小节点:返回最小节点的键值
    18. T minimum();
    19. // 查找最大节点:返回最大节点的键值
    20. T maximum();
    21. // 将节点(key为节点键值)插入到红黑树中
    22. void insert(T key);
    23. // 删除节点(key为节点键值)
    24. void remove(T key);
    25. // 销毁红黑树
    26. void destroy();
    27. // 打印红黑树
    28. void print();
    29. private:
    30. // 前序遍历”红黑树“
    31. void preOrder(RBTNode<T>* tree) const;
    32. // 中序遍历”红黑树“
    33. void inOrder(RBTNode<T>* tree) const;
    34. // 后续遍历“红黑树”
    35. void postOrder(RBTNode<T>* tree) const;
    36. // (递归实现)查找”红黑树“中键值为key的节点
    37. RBTNode<T>* search(RBTNode<T>* x ,T key) const;
    38. // (非递归实现)查找”红黑树“中键值为key的节点
    39. RBTNode<T>* iterativeSearch(RBTNode<T>* x ,T key) const;
    40. // 查找最小节点:返回最小节点的键值
    41. RBTNode<T>* minimum(RBTNode<T>* tree);
    42. // 查找最大节点:返回最大节点的键值
    43. RBTNode<T>* maximum(RBTNode<T>* tree);
    44. // 查找节点(X)的后继节点,即查找在红黑树中大于该节点值的最小节点
    45. RBTNode<T>* successor(RBTNode<T>* x);
    46. // 查找节点(X)的前驱节点,即查找在红黑树中小于该节点值的最大节点
    47. RBTNode<T>* predecessor(RBTNode<T>* x);
    48. // 左旋
    49. void leftRotate(RBTNode<T>* &root, RBTNode<T>* x);
    50. // 右旋
    51. void rightRotate(RBTNode<T>* &root, RBTNode<T>* y);
    52. // 插入函数
    53. void insert(RBTNode<T>*&root, RBTNode<T>* node);
    54. // 插入修正函数
    55. // void insertFixUp(RBTNode<T>*&root, RBTNode<T>* node, RBTNode<T>* parent);
    56. void insertFixUp(RBTNode<T>*&root, RBTNode<T>* node);
    57. // 删除的修正函数
    58. void removeFixUp(RBTNode<T>*&root, RBTNode<T>* node, RBTNode<T>* parent);
    59. // 查找需要替代删除的节点
    60. RBTNode<T>* findReplaceNode(RBTNode<T>* node);
    61. // 销毁红黑树
    62. void destroy(RBTNode<T>* &tree);
    63. // 打印红黑树
    64. void print(RBTNode<T>* &tree, T key, int direction);
    65. #define rb_parent(r) ((r)->parent)
    66. #define rb_color(r) ((r)->color)
    67. #define rb_is_red(r) ((r)->color == RED)
    68. #define rb_is_black(r) ((r)->color == BLACK)
    69. #define rb_set_black(r) do{(r)->color = BLACK;}while(0)
    70. #define rb_set_red(r) do{(r)->color = RED;}while(0)
    71. #define rb_set_parent(r, p) do{(r)->parent=(p);}while(0)
    72. #define rb_set_color(r,c) do{(r)->color = (c);}while(0)
    73. };

    4.红黑树中几个主要的算法解析

    4.1前驱算法思路

    查找节点(X)的前驱节点,即查找在红黑树中小于该节点值的最大节点 。

    如上图所示,节点值为10的前驱应该是以其左孩子为根节点的子树中的最大值节点,即节点值为8。查找思路:若查找节点X的前驱,则先移动到X的左孩子(X->left),再一直查找右孩子直到右孩子为空。

    4.2后继算法思路

    查找节点(X)的后继节点,即查找在红黑树中大于该节点值的最小节点 

    如上图所示,节点值为10的后继节点应该是以其右孩子为根节点的子树中的最小值节点,即节点值为11。查找思路:若查找节点X的后继,则先移动到X的右孩子(X->right),再一直查找左孩子直到左孩子为空。

    4.3插入算法思路

    (1)插入的节点若是根节点,则直接染黑

     (2)插入的节点X不管是左孩子还是右孩子)的父节点P为黑色,则不用操作

    (3)LP的左孩子,若新插入的节点X的父节点L和叔叔节点R都是红色,则将LR染黑,P染红,再将P作为新插入的节点继续向上判断 

     (4)LP的左孩子,若插入的节点X的父节点L为红色且XL的左孩子,叔叔节点R为黑色,则根据P右旋,将L染黑,P染红

    (5)若插入节点X为父节点L的右孩子,且L为红色,叔叔节点R为黑色,则先根据L左转,再根据P右转,将X染黑,P染红

    (6)RP的右孩子,若插入的节点X的父节点R为红色且XL孩子,叔叔节点L为黑色,则根据P左旋,将R染黑,P染红

    (7)RP的右节点,若插入节点X为父节点R孩子,且R为红色,叔叔节点L为黑色,则先根据R转,再根据P转,将X染黑,P染红

    4.4删除算法思路

    删除节点方案:

    1.找到前驱节点,复制前驱节点值覆盖预备删除的节点的值,然后删除前驱节点

    2.找到后继节点,复制后继节点值覆盖预备删除的节点的值,然后删除后继节点

    通过前驱节点与后继节点的替换,可以将删除的节点转移到叶子节点上,方便操作

    蓝色节点表示红或者黑,下面删除的节点都是以删除节点x为例

    (1)删除节点x为红色,不管是父节点的左孩子还是右孩子,则直接删除

    (2)删除的节点x为黑色,且其兄弟节点Y为叶节点且为黑色,则将x删除,p变为黑色,Y变为红色 

     (3)节点XY为黑色,且节点X的兄弟节点Y,只包含左孩子L且为红色,则删除节点X后,需要先根据Y右旋,再据P左旋,L变为P的颜色,再将P

     (4)节点XY为黑色,节点X的兄弟节点Y,只包含右孩子R且为红色,则删除节点X后,据P左旋,再将Y变为P的颜色,将PR染黑。

     (5)节点X和其兄弟节点Y都为黑色,Y的左孩子与右孩子都为红色,将节点X删除,再根据P进行左旋,再将Y变为P的颜色,PR变黑

    ​​​​

    (6)被删除的节点X为黑色,其兄弟节点Y为红色,则Y的左孩子与右孩子比为黑色。删除节点X,在根据P进行左旋,Y染黑,L染红

    4.5红黑树代码

    有点大800行左右

    1. #include<iostream>
    2. #include <iomanip>
    3. using namespace std;
    4. /**
    5. 1.节点红或者黑
    6. 2. 根节点为黑色
    7. 3.空叶节点为黑色
    8. 4.红色节点的孩子是黑色
    9. 5.从根节点出发到所以空叶节点的简单路径中黑色节点数量相等
    10. 初始插入节点是红色
    11. 1.插入位置为根,直接染黑
    12. 2.父亲节点如果是黑色,则不需要染色或者旋转
    13. 3.父亲节点是红色,叔叔节点也是红色。父亲和叔叔节点染成黑色,爷爷染成红色,
    14. 把爷爷看成新插入的节点,循环向上插入
    15. 4.父亲节点是红色,叔叔节点是黑色。
    16. (1)当前节点是其父节点的左节点且父节点是祖父节点的左孩子,
    17. 则父节点右旋转,父节点变黑,祖父节点变红,父节点的右子树变为祖父节点的左子树。
    18. (2)当前节点是其父节点的右孩子且父节点是祖父节点的右孩子,
    19. 则父节点左旋,父节点变黑,祖父节点变红,父节点的左孩子变为祖父节点的右孩子。
    20. 5. 父亲节点是红色,叔叔节点是黑色
    21. (1) 当前节点是其父节点的右节点且父节点是祖父节点的左节点,
    22. 则先以父节点进行左旋转,再以祖父节点右旋转【4.1】
    23. (2) 当前节点是父节点的左节点且父节点是祖父节点的右节点,
    24. 则先以父节点右旋转,再以祖父节点左旋转【4.2】
    25. */
    26. // 基本定义
    27. enum RBTColor{RED, BLACK};
    28. template<class T>
    29. class RBTNode{
    30. public:
    31. RBTColor color; // 颜色
    32. T key; // 键值
    33. RBTNode* left; // 左孩子
    34. RBTNode* right; // 右孩子
    35. RBTNode* parent; // 父节点
    36. RBTNode(T value, RBTColor c, RBTNode* p, RBTNode* l, RBTNode* r):
    37. key(value),color(c),parent(p),left(l),right(r){
    38. }
    39. };
    40. template<class T>
    41. class RBTree{
    42. private:
    43. RBTNode<T>* mRoot;
    44. public:
    45. RBTree();
    46. ~RBTree();
    47. // 前序遍历
    48. void preOrder();
    49. // 中序遍历
    50. void inOrder();
    51. // 后序遍历
    52. void postOrder();
    53. RBTNode<T>* iterativeSearch(T key);
    54. // (递归实现)查找”红黑树“中键值为key的节点
    55. RBTNode<T>* search(T key);
    56. // 查找最小节点:返回最小节点的键值
    57. T minimum();
    58. // 查找最大节点:返回最大节点的键值
    59. T maximum();
    60. // 将节点(key为节点键值)插入到红黑树中
    61. void insert(T key);
    62. // 删除节点(key为节点键值)
    63. void remove(T key);
    64. // 销毁红黑树
    65. void destroy();
    66. // 打印红黑树
    67. void print();
    68. private:
    69. // 前序遍历”红黑树“
    70. void preOrder(RBTNode<T>* tree) const;
    71. // 中序遍历”红黑树“
    72. void inOrder(RBTNode<T>* tree) const;
    73. // 后续遍历“红黑树”
    74. void postOrder(RBTNode<T>* tree) const;
    75. // (递归实现)查找”红黑树“中键值为key的节点
    76. RBTNode<T>* search(RBTNode<T>* x ,T key) const;
    77. // (非递归实现)查找”红黑树“中键值为key的节点
    78. RBTNode<T>* iterativeSearch(RBTNode<T>* x ,T key) const;
    79. // 查找最小节点:返回最小节点的键值
    80. RBTNode<T>* minimum(RBTNode<T>* tree);
    81. // 查找最大节点:返回最大节点的键值
    82. RBTNode<T>* maximum(RBTNode<T>* tree);
    83. // 查找节点(X)的后继节点,即查找在红黑树中大于该节点值的最小节点
    84. RBTNode<T>* successor(RBTNode<T>* x);
    85. // 查找节点(X)的前驱节点,即查找在红黑树中小于该节点值的最大节点
    86. RBTNode<T>* predecessor(RBTNode<T>* x);
    87. // 左旋
    88. void leftRotate(RBTNode<T>* &root, RBTNode<T>* x);
    89. // 右旋
    90. void rightRotate(RBTNode<T>* &root, RBTNode<T>* y);
    91. // 插入函数
    92. void insert(RBTNode<T>*&root, RBTNode<T>* node);
    93. // 插入修正函数
    94. // void insertFixUp(RBTNode<T>*&root, RBTNode<T>* node, RBTNode<T>* parent);
    95. void insertFixUp(RBTNode<T>*&root, RBTNode<T>* node);
    96. // 删除的修正函数
    97. void removeFixUp(RBTNode<T>*&root, RBTNode<T>* node, RBTNode<T>* parent);
    98. // 查找需要替代删除的节点
    99. RBTNode<T>* findReplaceNode(RBTNode<T>* node);
    100. // 销毁红黑树
    101. void destroy(RBTNode<T>* &tree);
    102. // 打印红黑树
    103. void print(RBTNode<T>* &tree, T key, int direction);
    104. #define rb_parent(r) ((r)->parent)
    105. #define rb_color(r) ((r)->color)
    106. #define rb_is_red(r) ((r)->color == RED)
    107. #define rb_is_black(r) ((r)->color == BLACK)
    108. #define rb_set_black(r) do{(r)->color = BLACK;}while(0)
    109. #define rb_set_red(r) do{(r)->color = RED;}while(0)
    110. #define rb_set_parent(r, p) do{(r)->parent=(p);}while(0)
    111. #define rb_set_color(r,c) do{(r)->color = (c);}while(0)
    112. };
    113. /**
    114. *构造函数
    115. */
    116. template<class T>
    117. RBTree<T>::RBTree():mRoot(NULL){
    118. //mRoot = NULL;
    119. }
    120. /**
    121. * 析构函数
    122. */
    123. template<class T>
    124. RBTree<T>::~RBTree(){
    125. destroy();
    126. }
    127. /**
    128. * 前序遍历”红黑树“
    129. */
    130. template<class T>
    131. void RBTree<T>::preOrder(RBTNode<T>* tree) const{
    132. if(tree != NULL){
    133. cout << tree->key << " ";
    134. preOrder(tree->left);
    135. preOrder(tree->right);
    136. }
    137. }
    138. template<class T>
    139. void RBTree<T>::preOrder(){
    140. this->preOrder(mRoot);
    141. }
    142. /**
    143. * 中序遍历”红黑树“
    144. */
    145. template<class T>
    146. void RBTree<T>::inOrder(RBTNode<T>* tree) const{
    147. if(tree != NULL){
    148. inOrder(tree->left);
    149. cout << tree->key << " ";
    150. inOrder(tree->right);
    151. }
    152. }
    153. template<class T>
    154. void RBTree<T>::inOrder(){
    155. this->inOrder(mRoot);
    156. }
    157. /**
    158. * 后序遍历”红黑树“
    159. */
    160. template<class T>
    161. void RBTree<T>::postOrder(RBTNode<T>* tree) const{
    162. if(tree != NULL){
    163. postOrder(tree->left);
    164. postOrder(tree->right);
    165. cout << tree->key << " ";
    166. }
    167. }
    168. template<class T>
    169. void RBTree<T>::postOrder(){
    170. this->postOrder(mRoot);
    171. }
    172. /**
    173. * (递归实现)查找”红黑树“中键值为key的节点
    174. */
    175. template<class T>
    176. RBTNode<T>* RBTree<T>::search(RBTNode<T>* x, T key) const{
    177. if(x == NULL || x->key == key){
    178. return x;
    179. }
    180. if(key < x->key){
    181. return search(x->left, key);
    182. }else{
    183. return search(x->right, key);
    184. }
    185. }
    186. template<class T>
    187. RBTNode<T>* RBTree<T>::search(T key){
    188. return search(mRoot, key);
    189. }
    190. // (非递归实现)查找”红黑树“中键值为key的节点
    191. template<class T>
    192. RBTNode<T>* RBTree<T>::iterativeSearch(RBTNode<T>* x ,T key) const{
    193. while(x != NULL && x->key != key){
    194. if(key < x->key){
    195. return iterativeSearch(x->left, key);
    196. }else{
    197. return iterativeSearch(x->right, key);
    198. }
    199. }
    200. return x;
    201. }
    202. template<class T>
    203. RBTNode<T>* RBTree<T>::iterativeSearch(T key){
    204. return iterativeSearch(mRoot, key);
    205. }
    206. /**
    207. * 查找最小节点:返回最小节点的键值
    208. */
    209. template<class T>
    210. RBTNode<T>* RBTree<T>::minimum(RBTNode<T>* tree){
    211. if(tree == NULL){
    212. return NULL;
    213. }
    214. while(tree->left != NULL){
    215. tree = tree->left;
    216. }
    217. return tree;
    218. }
    219. template<class T>
    220. T RBTree<T>::minimum(){
    221. RBTNode<T>* p = minimum(mRoot);
    222. if(p != NULL){
    223. return p->key;
    224. }
    225. return 0;
    226. }
    227. /**
    228. * 查找最大节点:返回最大节点的键值
    229. */
    230. template<class T>
    231. RBTNode<T>* RBTree<T>::maximum(RBTNode<T>* tree){
    232. if(tree == NULL){
    233. return NULL;
    234. }
    235. while(tree->right != NULL){
    236. tree = tree->right;
    237. }
    238. return tree;
    239. }
    240. template<class T>
    241. T RBTree<T>::maximum(){
    242. RBTNode<T>* p = maximum(mRoot);
    243. if(p != NULL){
    244. return p->key;
    245. }
    246. return 0;
    247. }
    248. /**
    249. * 查找节点(X)的后继节点,即查找在红黑树中大于该节点值的最小节点
    250. */
    251. template<class T>
    252. RBTNode<T>* RBTree<T>::successor(RBTNode<T>* x){
    253. // 如果x存在右孩子,则x的后继节点为其右孩子作为根节点子树的最小节点
    254. if(x->right != NULL){
    255. return minimum(x->right);
    256. }
    257. // 如果x没有右孩子,则x有一下两种可能
    258. // 1.x是父节点的左孩子,则x的后继节点为父节点
    259. // 2.x是父节点的右孩子,则需要循环查找x的最低父节点,并且该父节点具有左孩子
    260. RBTNode<T>* y = x->parent;
    261. while(y != NULL && x != y->left){
    262. x = y;
    263. y = y->parent;
    264. }
    265. return y;
    266. }
    267. /**
    268. * 查找节点(X)的前驱节点,即查找在红黑树中小于该节点值的最大节点
    269. */
    270. template<class T>
    271. RBTNode<T>* RBTree<T>::predecessor(RBTNode<T>* x){
    272. // 如果x存在左孩子,则x的后继节点为其右孩子作为根节点子树的最大节点
    273. if(x->left != NULL){
    274. return maximum(x->left);
    275. }
    276. // 如果x没有左孩子,则x有一下两种可能
    277. // 1.x是父节点的右孩子,则x的后继节点为父节点
    278. // 2.x是父节点的左孩子,则需要循环查找x的最低父节点,并且该父节点具有右孩子
    279. RBTNode<T>* y = x->parent;
    280. while(y != NULL && x != y->right){
    281. x = y;
    282. y = y->parent;
    283. }
    284. return y;
    285. }
    286. /**
    287. 左旋
    288. px px
    289. / 对x进行左旋转 /
    290. x ------------> y
    291. / \ / \
    292. lx y x ry
    293. / \ / \
    294. ly ry lx ly
    295. */
    296. template<class T>
    297. void RBTree<T>::leftRotate(RBTNode<T>* &root, RBTNode<T>* x){
    298. // 设置x的右孩子y
    299. RBTNode<T>* y = x->right;
    300. // 将y的左孩子设为x的右孩子
    301. // 如果y的左孩子非空,将x设为y的左孩子的父亲
    302. x->right = y->left;
    303. if(y->left != NULL){
    304. y->left->parent = x;
    305. }
    306. // 将x的父节点设置为y的父节点
    307. y->parent = x->parent;
    308. if(x->parent == NULL){
    309. root = y; // 如果x的父节点为空,则将y设为根节点
    310. } else{
    311. if(x->parent->left == x){
    312. x->parent->left = y; // 如果x是他父节点的左孩子,则将y设为x的父节点的左孩子
    313. }else{
    314. x->parent->right = y;// 如果x是他父节点的右孩子,则将y设为x的父节点的右孩子
    315. }
    316. }
    317. // 将x设为y的左孩子
    318. y->left = x;
    319. // 将x的父节点设为y
    320. x->parent = y;
    321. }
    322. /**
    323. 右旋转
    324. py py
    325. / /
    326. y x
    327. / \ 对y进行右旋转 / \
    328. x ry ------------> lx y
    329. / \ / \
    330. lx rx rx ry
    331. */
    332. template<class T>
    333. void RBTree<T>::rightRotate(RBTNode<T>* &root, RBTNode<T>* y){
    334. // 获取节点x
    335. RBTNode<T>* x = y->left;
    336. // 如果x的右孩子非空,则将x的右孩子设置为y的左孩子
    337. y->left = x->right;
    338. if(x->right != NULL){
    339. x->right->parent = y;
    340. }
    341. // 将x的父节点指向y的父节点
    342. x->parent = y->parent;
    343. if(y->parent == NULL){
    344. root = x; // 如果y为根节点,则将x变为新的根节点
    345. }else{
    346. if(y->parent->left == y){
    347. y->parent->left = x; // 如果y为父节点的左孩子,则将x设置为父节点的左孩子
    348. }else{
    349. y->parent->right = x; // 如果y为父节点的右孩子,则将x设置为父节点的右孩子
    350. }
    351. }
    352. y->parent = x; // 将y的父节点设置为x
    353. x->right = y; // 将x的右孩子设置为y
    354. }
    355. /**
    356. 红黑树插入修正函数
    357. 在向红黑树中插入节点之后(失去平衡),再调用该函数 ;
    358. 目的是将它重新塑造成一颗红黑树
    359. 参数说明:
    360. root 红黑树的根
    361. node 插入的节点
    362. */
    363. //#define rb_parent(r) ((r)->parent)
    364. //#define rb_color(r) ((r)->color)
    365. //#define rb_is_red(r) ((r)->color == RED)
    366. //#define rb_is_black(r) ((r)->color == BLACK)
    367. //#define rb_set_black(r) do{(r)->color = BLACK;}while(0)
    368. //#define rb_set_red(r) do{(r)->color = RED;}while(0)
    369. //#define rb_set_parent(r, p) do{(r)->parent=(p);}while(0)
    370. //#define rb_set_color(r,c) do{(r)->color = (c);}while(0)
    371. /**
    372. 初始插入节点是红色
    373. 1.插入位置为根,直接染黑
    374. 2.父亲节点如果是黑色,则不需要染色或者旋转
    375. 3.父亲节点是红色,叔叔节点也是红色。父亲和叔叔节点染成黑色,爷爷染成红色,
    376. 把爷爷看成新插入的节点,循环向上插入
    377. 4.父亲节点是红色,叔叔节点是黑色。
    378. (1)当前节点是其父节点的左节点且父节点是祖父节点的左孩子,
    379. 则父节点右旋转,父节点变黑,祖父节点变红,父节点的右子树变为祖父节点的左子树。
    380. (2)当前节点是其父节点的右孩子且父节点是祖父节点的右孩子,
    381. 则父节点左旋,父节点变黑,祖父节点变红,父节点的左孩子变为祖父节点的右孩子。
    382. 5. 父亲节点是红色,叔叔节点是黑色
    383. (1) 当前节点是其父节点的右节点且父节点是祖父节点的左节点,
    384. 则先以父节点进行左旋转,再以祖父节点右旋转【4.1】
    385. (2) 当前节点是父节点的左节点且父节点是祖父节点的右节点,
    386. 则先以父节点右旋转,再以祖父节点左旋转【4.2】
    387. */
    388. template<class T>
    389. void RBTree<T>::insertFixUp(RBTNode<T>*&root, RBTNode<T>* node){
    390. // 定义父节点和祖父节点
    391. RBTNode<T>* parent;
    392. RBTNode<T>* gparent;
    393. RBTNode<T>* uncle;
    394. parent = rb_parent(node);
    395. // 1.插入位置为根,直接染黑
    396. if(parent == NULL){
    397. rb_set_black(node);
    398. root = node;
    399. return;
    400. }
    401. // 2.父亲节点如果是黑色,则不需要染色或者旋转
    402. if(rb_is_black(parent)){
    403. return;
    404. }
    405. RBTNode<T>* curNode = node;
    406. parent = rb_parent(curNode);
    407. while(parent != NULL && rb_is_red(parent)){
    408. gparent = rb_parent(parent);
    409. // 先讨论父节点是祖父节点左孩子的情况
    410. if(parent == gparent->left){
    411. uncle = gparent->right;
    412. if(uncle == NULL || rb_is_black(uncle)){
    413. if(curNode == parent->right){
    414. // 5.若插入节点为父节点的右孩子,且父节点为红色,叔叔节点为黑色,
    415. // 则先根据父节点左转,(再根据祖父右转,将当前染黑,祖父染红)跳转到4
    416. leftRotate(root, parent);
    417. curNode = parent;
    418. parent = rb_parent(curNode);
    419. }
    420. if(curNode == parent->left){
    421. // 4.父节点为祖父节点的左孩子,若插入的节点的父节点为红色且为父节点的左孩子,叔叔节点为黑色,
    422. // 则根据祖父节点右旋,将父节点染黑,祖父染红
    423. rightRotate(root, gparent);
    424. rb_set_black(parent); // 将父节点染黑
    425. rb_set_red(gparent); // 将祖父节点染红
    426. break;
    427. }
    428. }
    429. }// 父节点是祖父节点右孩子的情况
    430. else{
    431. uncle = gparent->left;
    432. if(uncle == NULL || rb_is_black(uncle)){
    433. if(curNode == parent->left){
    434. // 7.父节点为祖父节点的右孩子,若插入节点为父节点的左孩子,且父节点为红色,叔叔节点为黑色,
    435. // 则先根据父节点右转,(再根据祖父左转,将当前染黑,祖父染红)跳转到6
    436. rightRotate(root, parent);
    437. curNode = parent;
    438. parent = rb_parent(curNode);
    439. }
    440. if(curNode == parent->right){
    441. // 6.父节点为祖父节点的右孩子,若父节点为红色且插入节点为父节点的右孩子,叔叔节点为黑色,
    442. //则根据祖父左旋,将父节点染黑,祖父染红
    443. leftRotate(root, gparent);
    444. rb_set_black(parent); // 将父节点染黑
    445. rb_set_red(gparent); // 将祖父节点染红
    446. break;
    447. }
    448. }
    449. }
    450. //3.父亲节点是红色,叔叔节点也是红色。父亲和叔叔节点染成黑色,
    451. // 爷爷染成红色,把爷爷看成新插入的节点,循环向上插入
    452. if(uncle != NULL && rb_is_red(uncle)){
    453. rb_set_black(parent); // 将父节点染黑
    454. rb_set_black(uncle); // 将叔叔节点染黑
    455. rb_set_red(gparent); // 将祖父节点染红
    456. curNode = gparent;
    457. parent = rb_parent(curNode);
    458. }
    459. }
    460. // 将根节点设为黑色
    461. rb_set_black(root);
    462. }
    463. // 插入函数
    464. /**
    465. * 将节点插入到红黑树中
    466. * root : 红黑树的根节点
    467. * node : 插入的节点
    468. */
    469. template<class T>
    470. void RBTree<T>::insert(RBTNode<T>*&root, RBTNode<T>* node){
    471. RBTNode<T>* y = NULL;
    472. RBTNode<T>* x = root;
    473. // 1. 将红黑树当作一颗二叉查找树,将节点添加到二叉树中
    474. while(x != NULL){
    475. y = x;
    476. if(node->key < x->key){
    477. x = x->left;
    478. }else{
    479. x = x->right;
    480. }
    481. }
    482. node->parent = y;
    483. if(y != NULL){
    484. if(node->key < y->key){
    485. y->left = node;
    486. }else{
    487. y->right = node;
    488. }
    489. }else{
    490. root = node;
    491. }
    492. // 2.设置节点的颜色为红色
    493. node->color = RED;
    494. // 3.将它重新修正为一颗红黑树
    495. insertFixUp(root, node);
    496. }
    497. /**
    498. * 将节点(key为节点键值)插入到红黑树中
    499. * 参数说明
    500. * key :插入点的键值
    501. */
    502. template<class T>
    503. void RBTree<T>::insert(T key){
    504. RBTNode<T>* z = NULL;
    505. // 如果新建节点失败,则返回
    506. if((z = new RBTNode<T>(key, RED, NULL, NULL, NULL)) == NULL){
    507. return;
    508. }
    509. insert(mRoot, z);
    510. }
    511. /**
    512. 红黑树删除修正函数
    513. 在从红黑树中删除插入节点之后(红黑树失去平衡),再调用该函数,目的是将它重新塑造成一颗红黑树
    514. 参数说明:
    515. root : 红黑树的根
    516. node : 待修正的节点
    517. 删除操作:
    518. 主题思想是:若删除的节点不是叶子节点,则可以查找该节点的后继节点的值将其代替,再删除替代它的节点,因为后继节点一般是叶节点,
    519. 则删除操作可以简化为对叶节点进行操作。
    520. 1.叶节点是红色,直接删除
    521. 2.
    522. */
    523. // 查找需要替代删除的节点 ,叶子节点即可
    524. template<class T>
    525. RBTNode<T>* RBTree<T>::findReplaceNode(RBTNode<T>* node){
    526. // 1.node本身就是叶子节点
    527. // 2.node存在左孩子或者右孩子
    528. RBTNode<T>* curNode = node;
    529. RBTNode<T>* preNode = node;
    530. while(curNode->left != NULL || curNode->right != NULL){
    531. // 先找后继节点
    532. if(curNode->right != NULL){
    533. curNode = this->successor(curNode);
    534. }
    535. preNode->key = curNode->key;
    536. preNode = curNode;
    537. // 查找前驱节点
    538. if(curNode->left != NULL){
    539. curNode = this->predecessor(curNode);
    540. }
    541. preNode->key = curNode->key;
    542. preNode = curNode;
    543. }
    544. return curNode;
    545. }
    546. //#define rb_parent(r) ((r)->parent)
    547. //#define rb_color(r) ((r)->color)
    548. //#define rb_is_red(r) ((r)->color == RED)
    549. //#define rb_is_black(r) ((r)->color == BLACK)
    550. //#define rb_set_black(r) do{(r)->color = BLACK;}while(0)
    551. //#define rb_set_red(r) do{(r)->color = RED;}while(0)
    552. //#define rb_set_parent(r, p) do{(r)->parent=(p);}while(0)
    553. //#define rb_set_color(r,c) do{(r)->color = (c);}while(0)
    554. template<class T>
    555. void RBTree<T>::removeFixUp(RBTNode<T>*&root, RBTNode<T>* node, RBTNode<T>* parent){
    556. RBTNode<T>* x = this->findReplaceNode(node); // 将删除的节点转移到叶子节点
    557. RBTNode<T>* p = rb_parent(x);
    558. RBTNode<T>* y = NULL;
    559. RBTNode<T>* l = NULL;
    560. RBTNode<T>* r = NULL;
    561. // 先判断删除的叶子节点为父节点的左孩子情况
    562. if(x == p->left){
    563. y = p->right; // x的兄弟节点
    564. if(y != NULL){
    565. l = y->left;
    566. r = y->right;
    567. }
    568. // 1. 删除节点为红色,不管是父节点的左孩子还是右孩子,则直接删除
    569. if(rb_is_red(x)){
    570. p->left = NULL;
    571. delete x;
    572. }// 2.删除的节点x为黑色,且其兄弟节点Y为叶节点且为黑色,则将x删除,p变为黑色,Y变为红色
    573. else if(y == NULL || (rb_is_black(x) && rb_is_black(y) && l == NULL && r == NULL)){
    574. p->left = NULL;
    575. delete x;
    576. rb_set_black(p);
    577. if(y != NULL){
    578. rb_set_red(y);
    579. }
    580. }// 3.节点x与Y为黑色,节点X的兄弟节点Y,只包含左孩子L且为红色,则删除节点X后,需要先根据Y右旋,再据P左旋,将L变为P的颜色,
    581. //再将P染黑
    582. else if(y != NULL && l != NULL && r == NULL && rb_is_red(l) && rb_is_black(x) && rb_is_black(y)){
    583. p->left = NULL;
    584. delete x;
    585. rightRotate(root, y); // 根据y右旋
    586. leftRotate(root, p); // 根据p左旋
    587. l->color = p->color;
    588. rb_set_black(p);
    589. }// 4.节点X与Y为黑色,节点X的兄弟节点Y,只包含右孩子R且为红色,则删除节点X后,据P左旋,再将Y变为P的颜色,
    590. // 将P和R染黑。
    591. else if(y != NULL && l == NULL && r != NULL && rb_is_red(r) && rb_is_black(x) && rb_is_black(y)){
    592. p->left = NULL;
    593. delete x;
    594. leftRotate(root, p); // 根据p左旋
    595. y->color = p->color;
    596. rb_set_black(p);
    597. rb_set_black(r);
    598. }// 5.节点X和其兄弟节点Y都为黑色,Y的左孩子与右孩子都为红色,将节点X删除,再根据P进行左旋,再将Y变为P的颜色,
    599. // P和R变黑
    600. else if(y != NULL && l != NULL && r != NULL && rb_is_red(l) && rb_is_red(r) && rb_is_black(x) && rb_is_black(y)){
    601. p->left = NULL;
    602. delete x;
    603. leftRotate(root, p); // 根据p左旋
    604. y->color = p->color;
    605. rb_set_black(p);
    606. rb_set_black(r);
    607. }// 6. 被删除的节点X为黑色,其兄弟节点Y为红色,则Y的左孩子与右孩子比黑色。删除节点X,在根据P进行左旋,
    608. // 再将Y染黑,L染红
    609. else if(y != NULL && rb_is_red(y) && l != NULL && r != NULL && rb_is_black(l) && rb_is_black(r) && rb_is_black(x)){
    610. p->left = NULL;
    611. delete x;
    612. leftRotate(root, p); // 根据p左旋
    613. rb_set_black(y);
    614. rb_set_red(l);
    615. }
    616. }// 再判断删除的叶子节点为父节点的右孩子情况
    617. else{
    618. y = p->left; // x的兄弟节点
    619. if(y != NULL){
    620. l = y->left;
    621. r = y->right;
    622. }
    623. // 1. 删除节点为红色,不管是父节点的左孩子还是右孩子,则直接删除
    624. if(rb_is_red(x)){
    625. p->right = NULL;
    626. delete x;
    627. }// 2.删除的节点x为黑色,且其兄弟节点Y为叶节点且为黑色,则将x删除,p变为黑色,Y变为红色
    628. else if(y == NULL || (rb_is_black(x) && rb_is_black(y) && l == NULL && r == NULL)){
    629. p->right = NULL;
    630. delete x;
    631. rb_set_black(p);
    632. if(y != NULL){
    633. rb_set_red(y);
    634. }
    635. }// 3.节点X为父节点的右节点,节点X与Y为黑色,且节点X的兄弟节点Y只包含右孩子R且为红色,则删除节点X后,
    636. // 需要先根据Y左旋,再据P右旋,将R变为P的颜色,再将P染黑
    637. else if(y != NULL && rb_is_black(x) && rb_is_black(y) && r != NULL && l == NULL && rb_is_red(r)){
    638. p->right = NULL;
    639. delete x;
    640. leftRotate(root, y); // 根据y左旋
    641. rightRotate(root, p); // 根据p右旋
    642. r->color = p->color; // 将R变为P的颜色
    643. rb_set_black(p); // 将P染黑
    644. }// 4.节点X为父节点的右节点,节点X与Y为黑色,且节点X的兄弟节点Y,只包含左孩子L且为红色,则删除节点X后,
    645. // 根据P右旋,将Y变为P的颜色,再将P和L染黑
    646. else if(y != NULL && rb_is_black(x) && rb_is_black(y) && r == NULL && l != NULL && rb_is_red(l)){
    647. p->right = NULL;
    648. delete x;
    649. rightRotate(root, p); // 根据p右旋
    650. y->color = p->color;
    651. rb_set_black(p); // 将P染黑
    652. rb_set_black(l); // 将P染黑
    653. }// 5.节点X为父节点的右节点,节点X和其兄弟节点Y都为黑色,Y的左孩子与右孩子都为红色,将节点X删除,
    654. // 再根据P进行右旋,再将Y变为P的颜色,P和L变黑
    655. else if(y != NULL && rb_is_black(x) && rb_is_black(y) && r != NULL && l != NULL && rb_is_red(l) && rb_is_red(r)){
    656. p->right = NULL;
    657. delete x;
    658. rightRotate(root, p); // 根据p右旋
    659. y->color = p->color;
    660. rb_set_black(p); // 将P染黑
    661. rb_set_black(l); // 将P染黑
    662. }// 6.节点X为父节点的右孩子,被删除的节点X为黑色,其兄弟节点Y为红色,则Y的左孩子与右孩子比为黑色。
    663. // 删除节点X,在根据P进行右旋,再将Y染黑,R染红
    664. else if(y != NULL && rb_is_black(x) && rb_is_red(y) && r != NULL && l != NULL && rb_is_black(l) && rb_is_black(r)){
    665. p->right = NULL;
    666. delete x;
    667. rightRotate(root, p); // 根据p右旋
    668. rb_set_black(y); // 将y染黑
    669. rb_set_red(r); // 将r染红
    670. }
    671. }
    672. }
    673. // 删除节点(key为节点键值)
    674. template<class T>
    675. void RBTree<T>::remove(T key){
    676. RBTNode<T>* node;
    677. // 查找key对应的节点node,找到的话就删除该节点
    678. if((node = search(mRoot, key)) != NULL){
    679. removeFixUp(mRoot, node, NULL);
    680. }
    681. }
    682. /**
    683. * 销毁红黑树
    684. */
    685. template<class T>
    686. void RBTree<T>::destroy(RBTNode<T>* &tree){
    687. if(tree == NULL){
    688. return;
    689. }
    690. destroy(tree->left);
    691. destroy(tree->right);
    692. delete tree;
    693. tree = NULL;
    694. }
    695. template<class T>
    696. void RBTree<T>::destroy(){
    697. destroy(mRoot);
    698. }
    699. /**
    700. * 打印二叉查找树
    701. key 节点的键值
    702. direction 0 表示该节点是根节点
    703. -1 表示该节点是它的父节点的左孩子
    704. 1 表示该节点是它父节点的右孩子
    705. */
    706. template<class T>
    707. void RBTree<T>::print(RBTNode<T>* &tree, T key, int direction){
    708. if(tree != NULL){
    709. if(direction == 0){ // tree是根节点
    710. cout << setw(2) << tree->key << "(B) is root" << endl;
    711. }else{
    712. cout << setw(2) << tree->key << (rb_is_red(tree) ? "(R)":"(B)") << " is " << setw(2) << key
    713. << " 's " << setw(12) << (direction == 1 ? "right child":"left child") << endl;
    714. }
    715. print(tree->left, tree->key, -1);
    716. print(tree->right, tree->key, 1);
    717. }
    718. }
    719. template<class T>
    720. void RBTree<T>::print(){
    721. if(mRoot != NULL){
    722. print(mRoot, mRoot->key, 0);
    723. }
    724. }
    725. int main(){
    726. cout << "hello1111" << endl;
    727. int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80};
    728. int check_insert = 0; // “插入”动作的检测开关(0,关闭;1,打开)
    729. int check_remove = 0; // “删除”动作的检测开关(0,关闭;1,打开)
    730. int i;
    731. int len = (sizeof(a))/sizeof(a[0]);
    732. RBTree<int>* tree = new RBTree<int>();
    733. cout << "====原始数据:";
    734. for(i = 0; i < len; i++){
    735. cout << a[i] << " ";
    736. }
    737. cout << endl;
    738. for(i = 0; i < len; i++){
    739. tree->insert(a[i]);
    740. // 设置check_insert=1,测试“添加函数”
    741. if(check_insert){
    742. cout << "==添加节点:" << a[i] << endl;
    743. cout << "==树的详细信息:" << endl;
    744. tree->print();
    745. cout << endl;
    746. }
    747. }
    748. cout << "==前序遍历:";
    749. tree->preOrder();
    750. cout << endl;
    751. cout << "==中序遍历:";
    752. tree->inOrder();
    753. cout << endl;
    754. cout << "==后序遍历:";
    755. tree->postOrder();
    756. cout << endl;
    757. cout << "==最小值:" << tree->minimum() << endl;
    758. cout << "==最大值:" << tree->maximum() << endl;
    759. cout << "==树的详细信息:" << endl;
    760. tree->print();
    761. cout << endl;
    762. // 设置check_remove = 1,测试“删除函数”
    763. check_remove = 1;
    764. if(check_remove){
    765. for(i = 0; i < len; i++){
    766. tree->remove(a[i]);
    767. cout << "==删除节点:" << a[i] << endl;
    768. cout << "==树的详细信息:" << endl;
    769. tree->print();
    770. cout << endl;
    771. }
    772. }
    773. // 销毁红黑树
    774. tree->destroy();
    775. return 0;
    776. }

    在删除操作那儿,后续还要再改动下

  • 相关阅读:
    io_uring 之 liburing 的简单使用
    【PG】PostgreSQL高可用方案repmgr管理之配置文件
    城市-上市公司数字经济数据(2011-2019年)
    amazon账号注册用什么软件?
    Vue中如何进行滚动加载与无限滚动
    深度学习——BRNN和DRNN
    Stream Collectors.groupingBy的四种用法 解决分组统计(计数、求和、平均数等)、范围统计、分组合并、分组结果自定义映射等问题
    HCE OS------操作系统基础操作
    Thymeleaf常见属性
    pip安装Cartopy小白版
  • 原文地址:https://blog.csdn.net/hdsHDS6/article/details/125494544