性質2. 根是黑色。node
性質3. 全部葉子都是黑色(葉子是NIL節點)。ios
性質4. 每一個紅色節點的兩個子節點都是黑色。(從每一個葉子到根的全部路徑上不能有兩個連續的紅色節點)算法
1 插入新節點老是紅色節點數據結構
2 若是插入節點的父節點是黑色, 能維持性質this
3 若是插入節點的父節點是紅色, 破壞了性質. 故須要經過從新着色或旋轉, 來維持性質spa
插入關鍵部分指針
解決相鄰的兩個節點爲紅色的結點,同時維持任意路徑黑高度(黑色結點個數)相同code
刪除須要須要注意的點blog
1 若是刪除的是紅色節點, 不破壞性質遞歸
2 若是刪除的是黑色節點, 那麼這個路徑上就會少一個黑色節點, 破壞了性質. 故須要經過從新着色或旋轉, 來維持性質
刪除關鍵部分
若是刪除的是左子樹黑色結點,維持的最終目的是左右黑高度相同,即維持右子樹黑高度的同時,增長左子樹的黑高度
代碼主要根據上圖實現
1 #include <iostream> 2 #include <crtdbg.h> 3 #include <string> 4 using namespace std; 5 /*紅黑樹*/ 6 /*實現中假設關鍵元素互不相同*/ 7 typedef int DataType; 8 9 class BST 10 { 11 private: 12 enum {BLACK = 0, RED = 1}; 13 /*結點的數據結構*/ 14 struct node 15 { 16 DataType data; 17 bool color; 18 node *left; 19 node *right; 20 node *parent; 21 22 node() 23 { 24 color = RED; 25 left = NULL; 26 right = NULL; 27 parent = NULL; 28 data = 0; 29 } 30 node *Grandfather() 31 { 32 if (parent == NULL) 33 { 34 return NULL; 35 } 36 return parent->parent; 37 } 38 node *Uncle() 39 { 40 if(Grandfather() == NULL) 41 return NULL; 42 if (parent == Grandfather()->left) 43 { 44 return Grandfather()->right; 45 } 46 else 47 { 48 return Grandfather()->left; 49 } 50 } 51 node *Sibling() 52 { 53 if (parent->left == this) 54 { 55 return parent->right; 56 } 57 else 58 { 59 return parent->left; 60 } 61 } 62 }; 63 void Left_rotate(node *p ) 64 { 65 //把y的左子樹鏈接到p的右子樹下面,並更新父節點 66 node *y = p->right; 67 p->right = y->left; 68 if (y->left != NIL) 69 { 70 y->left->parent = p; 71 } 72 //更新y的父節點 73 y->parent = p->parent; 74 if (p->parent == NIL) //判斷根結點 75 { 76 root = y; 77 } 78 //更新原x父節點的子節點 79 else if (p == p->parent->left) 80 { 81 p->parent->left = y; 82 } 83 else 84 { 85 p->parent->right = y; 86 } 87 //更新x 與 y 的關係 88 y->left = p; 89 p->parent = y; 90 } 91 void Right_rotate(node *p) 92 { 93 node *y = p->left; 94 p->left = y->right; 95 if (y->right != NIL) 96 { 97 y->right->parent = p; 98 } 99 y->parent = p->parent; 100 if (p->parent == NIL) //判斷根結點 101 { 102 root = y; 103 } 104 else if (p == p->parent->left) 105 { 106 p->parent->left = y; 107 } 108 else 109 { 110 p->parent->right = y; 111 } 112 y->right = p; 113 p->parent = y; 114 } 115 string OutputColor(bool color) 116 { 117 return color ? "RED":"BLACK"; 118 } 119 /*糾正因插入而破壞的性質*/ 120 void Insert_Fixup(node *p) 121 { 122 /*因爲p結點爲紅色(新插入默認賦值爲紅色), 123 判斷p的父節點是否爲紅色,若是爲紅色則破壞了紅黑樹的性質,須要維護*/ 124 while(p->parent->color == RED) 125 { 126 if (p->parent == p->Grandfather()->left) 127 { 128 node *y = p->Grandfather()->right; 129 if (y->color == RED) /*case 3*/ 130 { 131 p->parent->color = BLACK; 132 y->color = BLACK; 133 p->Grandfather()->color = RED; 134 p = p->Grandfather();/*p結點向上移*/ 135 } 136 else if (p == p->parent->right) /*case 2*/ 137 { 138 p = p->parent;/*p結點向上移*/ 139 Left_rotate(p); 140 } 141 else 142 { 143 p->parent->color = BLACK; /*case 3*/ 144 p->Grandfather()->color = RED; 145 Right_rotate(p->Grandfather());/*注意是祖父結點*/ 146 } 147 } 148 else 149 { 150 node *y = p->Grandfather()->left; 151 if (y->color == RED) /*case 3*/ 152 { 153 p->parent->color = BLACK; 154 y->color = BLACK; 155 p->Grandfather()->color = RED; 156 p = p->Grandfather(); 157 } 158 else if (p == p->parent->left) /*case 2*/ 159 { 160 p = p->parent; 161 Right_rotate(p); 162 } 163 else 164 { 165 p->parent->color = BLACK; /*case 3*/ 166 p->Grandfather()->color = RED; 167 Left_rotate(p->Grandfather()); 168 } 169 } 170 } 171 root->color = BLACK;/*確保插入根結點時,知足紅黑樹的性質*/ 172 } 173 /*糾正因刪除而破壞的性質*/ 174 void Delete_Fixup(node *p) 175 { 176 /*判斷p結點是否爲黑色 177 若是是紅色不破壞紅黑樹性質 178 緣由1.刪除紅色樹黑高度不變2.不存在兩個相鄰紅色結點 179 3. 若是y是紅色的,就不多是根,即根仍然是黑色的 180 爲保證性質任何路徑上黑結點個數相同,假設p結點爲多重顏色(雙黑或紅黑)*/ 181 while (p != root && p->color == BLACK) 182 { 183 if(p == p->parent->left) 184 { 185 node *pSibling = p->parent->right; 186 if (pSibling->color == RED)/*case1*/ 187 { 188 pSibling->color = BLACK; 189 Left_rotate(p->parent); 190 pSibling = p->parent->right; 191 } 192 else if (pSibling->left->color == BLACK && pSibling->right->color == BLACK)/*case2*/ 193 { 194 pSibling->color = RED; 195 p = p->parent; 196 } 197 else 198 { 199 if (pSibling->right->color == BLACK)/*case3*/ 200 { 201 pSibling->left->color = BLACK; 202 pSibling->color = RED; 203 Right_rotate(pSibling); 204 pSibling = p->parent->right; 205 } 206 pSibling->color = p->parent->color;/*case4*/ 207 p->parent->color = BLACK; 208 pSibling->right->color = BLACK; 209 Left_rotate(p->parent); 210 p = root; 211 } 212 } 213 else 214 { 215 node *pSibling = p->parent->left; 216 if (pSibling->color == RED)/*case1*/ 217 { 218 pSibling->color = BLACK; 219 Left_rotate(p->parent); 220 pSibling = p->parent->left; 221 } 222 else if (pSibling->left->color == BLACK && pSibling->right->color == BLACK)/*case2*/ 223 { 224 pSibling->color = RED; 225 p = p->parent; 226 } 227 else 228 { 229 if (pSibling->left->color == BLACK)/*case3*/ 230 { 231 pSibling->right->color = BLACK; 232 pSibling->color = RED; 233 Left_rotate(pSibling); 234 pSibling = p->parent->left; 235 } 236 pSibling->color = p->parent->color;/*case4*/ 237 p->parent->color = BLACK; 238 pSibling->right->color = BLACK; 239 Right_rotate(p->parent); 240 p = root; 241 } 242 } 243 } 244 p->color = BLACK; 245 } 246 /*中序遍歷*/ 247 void InOrderTree(node *p) 248 { 249 if (p == NULL || p == NIL) 250 { 251 return; 252 } 253 InOrderTree(p->left); 254 cout << p->data << "\t" << OutputColor(p->color) << endl; 255 InOrderTree(p->right); 256 } 257 /*獲取結點的後繼*/ 258 node *TreeAfter(node *p) 259 { 260 if (p->right != NIL) 261 { 262 node *pTemp = p->right; 263 while(pTemp != NIL) 264 { 265 p = pTemp; 266 pTemp = p->left; 267 } 268 } 269 return p; 270 } 271 private: 272 node *root; 273 node *NIL; 274 public: 275 BST() 276 { 277 NIL = new node(); 278 NIL->color = BLACK; 279 root = NULL; 280 } 281 ~BST() 282 { 283 if (root != NULL) 284 { 285 Destory(root); 286 root = NULL; 287 } 288 delete NIL; 289 NIL = NULL; 290 } 291 void Destory(node *p) 292 { 293 if (p == NULL || p == NIL) 294 return; 295 Destory(p->left); 296 Destory(p->right); 297 delete p; 298 } 299 void Insert(DataType data) 300 { 301 node *p = root; 302 node *pTemp = NIL; 303 while( p != NIL && p != NULL) 304 { 305 pTemp = p; 306 if (data < p->data) 307 { 308 p = p->left; 309 } 310 else 311 { 312 p = p->right; 313 } 314 } 315 node *pNew = new node(); 316 pNew->parent = pTemp; 317 pNew->data = data; 318 if (pTemp == NIL) 319 { 320 root = pNew; 321 } 322 else 323 { 324 if (pNew->data < pTemp->data) 325 { 326 pTemp->left = pNew; 327 } 328 else 329 { 330 pTemp->right = pNew; 331 } 332 } 333 pNew->left = NIL; 334 pNew->right = NIL; 335 Insert_Fixup(pNew); 336 } 337 /*非遞歸版本*/ 338 node* Find(DataType key) 339 { 340 node *p = root; 341 while(p != NULL && p->data != key) 342 { 343 if (key < p->data) 344 { 345 p = p->left; 346 } 347 else 348 { 349 p = p->right; 350 } 351 } 352 return p; 353 } 354 void Delete(DataType data) 355 { 356 /*獲取data的指針*/ 357 node *p = Find(data); 358 node *pDelete= NIL; 359 node *pNode = NIL;/*要刪除節點的子節點*/ 360 if (p->left == NIL || p->right == NIL) 361 { 362 pDelete = p; 363 } 364 else 365 { 366 pDelete = TreeAfter(p); 367 } 368 /*獲取子結點*/ 369 if(pDelete->left != NIL) 370 { 371 pNode = pDelete->left; 372 } 373 else 374 { 375 pNode = pDelete->right; 376 } 377 /*更新父結點*/ 378 pNode->parent = pDelete->parent; 379 /*更新子結點*/ 380 if (pDelete->parent == NIL) 381 { 382 root = pNode; 383 } 384 else if(pDelete->parent->left == pDelete) 385 { 386 pDelete->parent->left = pNode; 387 } 388 else 389 { 390 pDelete->parent->right = pNode; 391 } 392 if (pDelete != p) 393 { 394 p->data = pDelete->data; 395 } 396 /*若是要刪除的結點pDelete是紅色的, 397 不影響黑高度,即不會破壞紅黑樹的性質*/ 398 if (pDelete->color == BLACK) 399 { 400 Delete_Fixup(pNode); 401 } 402 delete pDelete; 403 pDelete = NULL; 404 } 405 void InOrder() 406 { 407 if (root == NULL) 408 { 409 return; 410 } 411 InOrderTree(root); 412 cout << endl; 413 } 414 }; 415 416 void main() 417 { 418 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 419 420 BST bst; 421 422 bst.Insert(11); 423 bst.Insert(2); 424 bst.Insert(14); 425 bst.Insert(15); 426 bst.Insert(1); 427 bst.Insert(7); 428 bst.Insert(5); 429 bst.Insert(8); 430 bst.Insert(4); 431 432 bst.InOrder(); 433 434 //bst.Delete(4); 435 //bst.Delete(14); 436 bst.Delete(7); 437 bst.InOrder(); 438 439 system("pause"); 440 }
(轉載請註明做者和出處 :) Seven++ http://www.cnblogs.com/sevenPP/ )