RedBlack-Tree(红黑树)原理及C++代码实现
众所周知,红黑树是用途很广的平衡二叉搜索树,用过的都说好。所以我们来看看红黑树的是怎么实现的吧。
红黑树顾名思义,通过红与黑两种颜色来给每个节点上色。其中根结点和叶子结点一定是黑色的,并且红色结点的两个孩子一定是黑色的,每个结点到所有后代叶子的简单路径上,均包含相同数目的黑色结点(黑高bh)。
这里和其他树有些区别的是,红黑树的叶子结点并不包含关键字,它只是用来维持红黑树的性质。所以包含关键字的结点都是内部结点。
这样的性质也带来了很多有意思的现象。下面我们忽略所谓的叶子结点来看看。
1.红色结点的孩子要么没有,要么是两个黑色结点,不会有单个孩子结点的时候。
2.如果某个结点只有一个孩子结点,那么那个孩子结点一定是红色的。
3.用吸收的角度去看,即黑色结点可以吸收它的红色孩子结点,红黑树就像一个2-3-4树。
下面我们来看看代码吧,代码用了一个小技巧,即所有的叶子结点都用一个nil结点来表示,指向nullptr的指针现在全部指向nil。
代码如下:(仅供参考)
1 #include <iostream> 2 using namespace std; 3 4 class RBT { 5 private : 6 enum {RED = 0, BLACK}; 7 struct Node { 8 int key; 9 bool color; 10 Node * left; 11 Node * right; 12 Node * parent; 13 Node(int k = 0, bool c = BLACK, Node *l = nullptr, Node *r = nullptr, Node *p = nullptr) 14 : key(k), color(c), left(l), right(r), parent(p) {} 15 }; 16 private : 17 Node * nil; 18 Node * root; 19 private : 20 void leftRotate(Node * x); 21 void rightRotate(Node * x); 22 void fixup_insert(Node * p); 23 void fixup_remove(Node * p); 24 void transplant(Node * old_t, Node * new_t); 25 void insert(Node * p); 26 void remove(Node * p); 27 Node * search(Node * p, const int k); 28 Node * minimum(Node * p); 29 Node * maximum(Node * p); 30 void inorderWalk(Node * p) const; 31 public : 32 RBT() : nil(new Node), root(nil) {} 33 ~RBT() {delete nil;} 34 void insert(const int key) {insert(new Node(key, RED, nil, nil, nil));} 35 void remove(const int key) {remove(search(root, key));} 36 bool search(const int key) {return (search(root, key) == nil ? false : true);} 37 int minimum() {return minimum(root)->key;} 38 int maximum() {return maximum(root)->key;} 39 int predecessor(const int key); 40 int successor(const int key); 41 42 friend ostream &operator<<(ostream &os, const RBT &t); 43 }; 44 45 void RBT::inorderWalk(Node * p) const { 46 if (p != nil) { 47 inorderWalk(p->left); 48 cout << p->key << ' '; 49 inorderWalk(p->right); 50 } 51 } 52 53 RBT::Node * RBT::search(Node * p, const int k) { 54 if (p == nil || k == p->key) 55 return p; 56 if (k < p->key) 57 return search(p->left, k); 58 else 59 return search(p->right, k); 60 } 61 62 RBT::Node * RBT::minimum(Node * p) { 63 if (p == nil) 64 return p; 65 while (p->left != nil) 66 p = p->left; 67 return p; 68 } 69 70 RBT::Node * RBT::maximum(Node * p) { 71 if (p == nil) 72 return p; 73 while (p->right != nil) 74 p = p->right; 75 return p; 76 } 77 78 int RBT::predecessor(const int k) { 79 Node * p = search(root, k); 80 if (p == nil) 81 return 0; 82 if (p->left != nil) 83 return maximum(p->left)->key; 84 Node * y = p->parent; 85 while (y != nil && y->left == p) { 86 p = y; 87 y = y->parent; 88 } 89 return y->key; 90 } 91 92 int RBT::successor(const int k) { 93 Node * p = search(root, k); 94 if (p == nil) 95 return 0; 96 if (p->right != nil) 97 return minimum(p->right)->key; 98 Node * y = p->parent; 99 while (y != nil && y->right == p) { 100 p = y; 101 y = y->parent; 102 } 103 return y->key; 104 } 105 106 void RBT::leftRotate(Node * x) { //assume:x->right != nil 107 Node * y = x->right; 108 x->right = y->left; 109 if (y->left != nil) 110 y->left->parent = x; 111 y->parent = x->parent; 112 if (x->parent == nil) 113 root = y; 114 else if (x == x->parent->left) 115 x->parent->left = y; 116 else 117 x->parent->right = y; 118 y->left = x; 119 x->parent = y; 120 } 121 122 void RBT::rightRotate(Node * x) { //assume:x->left != nil 123 Node * y = x->left; 124 x->left = y->right; 125 if (y->right != nil) 126 y->right->parent = x; 127 y->parent = x->parent; 128 if (x->parent == nil) 129 root = y; 130 else if (x == x->parent->right) 131 x->parent->right = y; 132 else 133 x->parent->left = y; 134 y->right = x; 135 x->parent = y; 136 } 137 138 void RBT::insert(Node * p) { 139 if (p == nullptr) 140 return ; 141 Node * x = root; 142 Node * y = nil; 143 while (x != nil) { 144 y = x; 145 if (x->key < p->key) 146 x = x->right; 147 else 148 x = x->left; 149 } 150 p->parent = y; 151 if (y == nil) 152 root = p; 153 else if (y->key < p->key) 154 y->right = p; 155 else 156 y->left = p; 157 fixup_insert(p); 158 } 159 160 void RBT::fixup_insert(Node * p) { 161 while (p->parent->color == RED) { 162 if (p->parent == p->parent->parent->left) { 163 Node * y = p->parent->parent->right; 164 if (y->color == RED) { //case 1 165 p->parent->color = BLACK; 166 y->color = BLACK; 167 p->parent->parent->color = RED; 168 p = p->parent->parent; 169 } 170 else { 171 if (p == p->parent->right) { //case 2 172 p = p->parent; 173 leftRotate(p); 174 } 175 p->parent->color = BLACK; //case 3 176 p->parent->parent->color = RED; 177 rightRotate(p->parent->parent); 178 } 179 } 180 else { //with "right" and "left" exchanged 181 Node * y = p->parent->parent->left; 182 if (y->color == RED) { //case 1 183 p->parent->color = BLACK; 184 y->color = BLACK; 185 p->parent->parent->color = RED; 186 p = p->parent->parent; 187 } 188 else { 189 if (p == p->parent->left) { //case 2 190 p = p->parent; 191 rightRotate(p); 192 } 193 p->parent->color = BLACK; //case 3 194 p->parent->parent->color = RED; 195 leftRotate(p->parent->parent); 196 } 197 } 198 } 199 root->color = BLACK; 200 } 201 202 void RBT::transplant(Node * old_t, Node * new_t) { 203 if (old_t->parent == nil) 204 root = new_t; 205 else if (old_t == old_t->parent->left) 206 old_t->parent->left = new_t; 207 else 208 old_t->parent->right = new_t; 209 new_t->parent = old_t->parent; 210 } 211 212 void RBT::fixup_remove(Node * x) { 213 Node * z = nil; 214 while (x != root && x->color == BLACK) { 215 if (x == x->parent->left) { 216 z = x->parent->right; 217 /*case 1*/ if (z->color == RED) { 218 z->color = BLACK; 219 x->parent->color = RED; 220 leftRotate(x->parent); 221 z = x->parent->right; //new z 222 } 223 /*case 2*/ if (z->left->color == BLACK && z->right->color == BLACK) { 224 z->color = RED; 225 x = x->parent; 226 } 227 else { 228 /*case 3*/ if (z->right->color == BLACK) { 229 z->left->color = BLACK; 230 z->color = RED; 231 rightRotate(z); 232 z = x->parent->right; 233 } 234 /*case 4*/ z->color = x->parent->color; 235 x->parent->color = BLACK; 236 z->right->color = BLACK; 237 leftRotate(x->parent); 238 x = root; //exit while 239 } 240 } 241 else { 242 z = x->parent->left; 243 /*case 1*/ if (z->color == RED) { 244 z->color = BLACK; 245 x->parent->color = RED; 246 rightRotate(x->parent); 247 z = x->parent->left; //new z 248 } 249 /*case 2*/ if (z->right->color == BLACK && z->left->color == BLACK) { 250 z->color = RED; 251 x = x->parent; 252 } 253 else { 254 /*case 3*/ if (z->left->color == BLACK) { 255 z->right->color = BLACK; 256 z->color = RED; 257 leftRotate(z); 258 z = x->parent->left; 259 } 260 /*case 4*/ z->color = x->parent->color; 261 x->parent->color = BLACK; 262 z->left->color = BLACK; 263 rightRotate(x->parent); 264 x = root; //exit while 265 } 266 } 267 } 268 x->color = BLACK; 269 } 270 271 void RBT::remove(Node * p) { 272 if (p == nil) 273 return ; 274 Node * y = p; 275 Node * x = nil; 276 bool y_originalColor = y->color; 277 if (p->left == nil) { 278 x = p->right; 279 transplant(p, p->right); 280 } 281 else if (p->right == nil) { 282 x = p->left; 283 transplant(p, p->left); 284 } 285 else { 286 y = minimum(p->right); 287 y_originalColor = y->color; 288 x = y->right; 289 if (y->parent == p) 290 x->parent = y; //maybe x == nil 291 else { 292 transplant(y, y->right); 293 y->right = p->right; 294 y->right->parent = y; 295 } 296 transplant(p, y); 297 y->left = p->left; 298 y->left->parent = y; 299 y->color = p->color; 300 } 301 delete p; 302 if (y_originalColor == BLACK) 303 fixup_remove(x); 304 } 305 306 ostream &operator<<(ostream &os, const RBT &t) { 307 t.inorderWalk(t.root); 308 return os; 309 }