1 import java.util.Random; 2 3 4 public class RBTree 5 { 6 7 private Node root; 8 9 10 public RBTree(int[] array) 11 { 12 for (int i : array) insert(i); 13 } 14 15 private Node search(int key, Node node) 16 { 17 if (node == null) return null; 18 int compare = compare(key, node.key); 19 20 if (compare == 0) return node; 21 if (compare > 0) 22 return search(key, node.right); 23 else 24 return search (key, node.left); 25 } 26 27 /* 28 * 插入节点 29 */ 30 public boolean insert(int key) 31 { 32 Node node = new Node(key); 33 node.color = 'R'; 34 35 Node parent = null, current = root; 36 int compare = 0; 37 38 /* 39 * 寻找插入节点的父节点 40 */ 41 while (current != null) { 42 parent = current; 43 compare = compare(key, current.key); 44 45 if (compare == 0) return false; 46 47 if (compare == 1) 48 current = current.right; 49 else 50 current = current.left; 51 } 52 53 // 添加新节点 54 if (parent == null) { 55 root = node; 56 } 57 else { 58 node.parent = parent; 59 if (compare == 1) { 60 parent.right = node; 61 } 62 else { 63 parent.left = node; 64 } 65 } 66 67 insertFixup(node); 68 return true; 69 } 70 71 private void insertFixup(Node node) 72 { 73 while (node != root && node.parent.color == 'R') { 74 // 父节点为祖父节点的左节点 75 if (node.parent == node.parent.parent.left) { 76 Node uncle = node.parent.parent.right; 77 /* 78 * 父节点与叔叔节点都是红色 79 * 将父节点与叔叔节点变成黑色 80 * 将祖父节点变成红色 81 * 当前节点指向组父节点 82 */ 83 if (uncle != null && uncle.color == 'R') { 84 node.parent.color = 'B'; 85 uncle.color = 'B'; 86 uncle.parent.color = 'R'; 87 node = node.parent.parent; 88 } 89 else { 90 /* 91 * 叔叔节点是黑色且node为右孩子 92 * 当前结点指向父节点 93 * 以当前结点为中心左旋 94 */ 95 if (node == node.parent.right) { 96 node = node.parent; 97 leftRotate(node); 98 } 99 100 /* 101 * 叔叔节点是黑色且node为左孩子 102 * 父节点变为黑色,组父节点变为红色 103 * 以祖父节点为中心右旋 104 */ 105 node.parent.color = 'B'; 106 node.parent.parent.color = 'R'; 107 rightRotate(node.parent.parent); 108 } 109 } 110 else { 111 // 父节点为祖父节点的右节点 112 Node uncle = node.parent.parent.left; 113 114 // 操作与上面相反 115 if (uncle != null && uncle.color == 'R') { 116 node.parent.color = 'B'; 117 uncle.color = 'B'; 118 uncle.parent.color = 'R'; 119 node = node.parent.parent; 120 } 121 else { 122 if (node == node.parent.left) { 123 node = node.parent; 124 rightRotate(node); 125 } 126 node.parent.color = 'B'; 127 node.parent.parent.color = 'R'; 128 leftRotate(node.parent.parent); 129 } 130 } 131 } 132 root.color = 'B'; 133 } 134 135 private void deleteFixup(Node node) 136 { 137 if (node == null) return; 138 139 while (node != root && node.color == 'B') { 140 // node为父节点的左子节点 141 if (node == node.parent.left) { 142 Node sibling = node.parent.right; 143 144 /* 145 * 当前结点为黑色且兄弟节点为红色 146 * 将父节点染成红色,兄弟节点染成黑色 147 * 针对父节点最一次左旋 148 */ 149 if (sibling.color == 'R') { 150 sibling.color = 'B'; 151 sibling.parent.color = 'R'; 152 leftRotate(node.parent); 153 sibling = node.parent.right; 154 } 155 156 /* 157 * 当前结点和兄弟节点为黑色,兄弟节点的子节点都为黑色 158 * 将当前节点和兄弟节点抽出一重黑色加到父节点上 159 * 把父节点当成新的节点继续计算 160 */ 161 if (sibling.left.color == 'B' 162 && sibling.right.color == 'B') 163 { 164 sibling.color = 'R'; 165 node = node.parent; 166 } 167 else { 168 /* 169 * 当前节点和兄弟节点为黑色,兄弟的左子节点为红色 170 * 把兄弟节点染红,兄弟左子节点染黑 171 * 以兄弟节点位置点右旋 172 */ 173 if (sibling.right.color == 'B') { 174 sibling.left.color = 'B'; 175 sibling.color = 'R'; 176 rightRotate(sibling); 177 sibling = node.parent.right; 178 } 179 180 /* 181 * 当前结点和兄弟节点为黑色,兄弟右子节点为红色 182 * 把兄弟节点染成当前结点的父节点的颜色 183 * 将当前节点的父节点染成黑色 184 * 兄弟节点有子节点染成黑色 185 * 以当前节点的父节点为支点左旋 186 */ 187 sibling.color = node.parent.color; 188 node.parent.color = 'B'; 189 sibling.right.color = 'B'; 190 leftRotate(node.parent); 191 node = root; 192 } 193 } 194 // node为父节点的右子节点 195 else { 196 Node sibling = node.parent.left; 197 198 /* 199 * 当前结点为黑色,兄弟节点为红色 200 * 将兄弟节点染成黑色 201 * 当前结点的父节点染成红色 202 * 以当前节点的父节点进行右旋 203 */ 204 if (sibling.color == 'R') { 205 sibling.color = 'B'; 206 sibling.parent.color = 'R'; 207 rightRotate(node.parent); 208 sibling = node.parent.left; 209 } 210 211 /* 212 * 当前结点和兄弟节点为黑色 213 * 把当前结点和兄弟节点抽取一重黑色到父节点上 214 * 把当前节点当作新的节点重新计算 215 */ 216 if (sibling.left.color == 'B' && sibling.right.color == 'B') { 217 sibling.color = 'R'; 218 sibling.parent.color = 'B'; 219 node = node.parent; 220 } 221 else { 222 /* 223 * 当前结点和兄弟节点为黑色,兄弟的右子节点为红色 224 * 把兄弟节点染红,兄弟的左子节点染黑 225 * 以兄弟节点为支点左旋 226 */ 227 if (sibling.left.color == 'B') { 228 sibling.color = 'R'; 229 sibling.right.color = 'B'; 230 leftRotate(sibling); 231 sibling = node.parent.left; 232 } 233 234 /* 235 * 当前结点和兄弟节点为黑色,兄弟的右子节点为黑色 236 * 将兄弟节点染成当前结点的父节点的颜色 237 * 当前节点的父节点染黑 238 * 以当前结点的父节点为支点进行右旋 239 */ 240 sibling.color = node.parent.color; 241 node.parent.color = 'B'; 242 sibling.left.color = 'B'; 243 rightRotate(node.parent); 244 node = root; 245 } 246 } 247 } 248 node.color = 'B'; 249 } 250 251 /* 252 * 删除节点 253 * 只会在只有一个子节点的节点上进行 254 */ 255 public void delete(int key) 256 { 257 Node node = search(key, root); 258 if (node == null) return; 259 260 Node delete, child = null; 261 262 // 如果有两个子节点则删除是其节点后继节点 263 if (node.left == null || node.right == null) { 264 delete = node; 265 } 266 else { 267 delete = interval(node); 268 } 269 270 // 如国有子节点则判断是那个子节点 271 if (delete.left != null || delete.right != null) { 272 if (delete.left != null) 273 child = delete.left; 274 else 275 child = delete.right; 276 277 child.parent = delete.parent; 278 } 279 280 // 清除删除节点的引用 281 if (delete.parent == null) { 282 root = child; 283 } 284 else { 285 if (delete == delete.parent.left) 286 delete.parent.left = child; 287 else 288 delete.parent.right = child; 289 } 290 291 // 如果删除的是后继节点则将当前其值赋给当前结点 292 if (delete != node) { 293 node.key = delete.key; 294 } 295 296 // 调整红黑树平衡 297 if (delete.color == 'B') 298 deleteFixup(child); 299 } 300 301 private void leftRotate(Node node) 302 { 303 /* 304 * 左旋 305 * P P 306 * / \ / \ 307 * @ d y d 308 * / \ --> / \ 309 * a y @ c 310 * / \ / \ 311 * b c a b 312 */ 313 314 Node right = node.right; 315 node.right = right.left; 316 317 if (node.right != null) { 318 node.right.parent = node; 319 } 320 321 right.parent = node.parent; 322 if (right.parent == null) { 323 root = right; 324 } 325 else { 326 if (node == node.parent.left) 327 node.parent.left = right; 328 else 329 node.parent.right = right; 330 } 331 332 right.left = node; 333 node.parent = right; 334 } 335 336 private void rightRotate(Node node) 337 { 338 /* 339 * 右旋 340 * P P 341 * / \ / \ 342 * d @ d y 343 * / \ --> / \ 344 * y a b @ 345 * / \ / \ 346 * b c c a 347 */ 348 349 Node left = node.left; 350 node.left = left.right; 351 352 if (node.left != null) { 353 node.left.parent = node; 354 } 355 356 left.parent = node.parent; 357 if (left.parent == null) { 358 root = left; 359 } 360 else { 361 if (node == node.parent.left) 362 node.parent.left = left; 363 else 364 node.parent.right = left; 365 } 366 367 left.right = node; 368 node.parent = left; 369 } 370 371 /* 372 * 最小值想做遍历寻找 373 */ 374 private Node min(Node node) 375 { 376 while (node.left != null) { 377 node = node.left; 378 } 379 return node; 380 } 381 382 /* 383 * 最大值向右遍历寻找 384 */ 385 private Node max(Node node) 386 { 387 while (node.right != null) { 388 node = node.right; 389 } 390 return node; 391 } 392 393 /* 394 * 查找直接后继节点 395 */ 396 private Node interval(Node node) 397 { 398 /* 399 * 如果有右子节点则在右子节点中寻找 400 * 否则查找父节点为左子节点的节点作为后继节点 401 */ 402 if (node.right != null) 403 return min(node.right); 404 else { 405 Node parent = node.parent; 406 while (parent != null && node == parent.right) { 407 node = parent; 408 parent = node.parent; 409 } 410 return parent; 411 } 412 } 413 414 /* 415 * 比较大小 416 */ 417 private int compare(int a, int b) 418 { 419 return a > b ? 1 : a < b ? -1 : 0; 420 } 421 422 /* 423 * 前序遍历 424 */ 425 public void preOrder() 426 { 427 preOrder(root); 428 } 429 430 private void preOrder(Node node) 431 { 432 if (node == null) return; 433 434 System.out.println(node.key + " " + node.color); 435 preOrder(node.left); 436 preOrder(node.right); 437 } 438 439 /* 440 * 后续遍历 441 */ 442 public void postOrder() 443 { 444 postOrder(root); 445 } 446 447 private void postOrder(Node node) 448 { 449 if (node == null) return; 450 451 postOrder(node.left); 452 postOrder(node.right); 453 System.out.println(node.key + " " + node.color); 454 } 455 456 /* 457 * 中序遍历 458 */ 459 public void inOrder() 460 { 461 inOrder(root); 462 } 463 464 private void inOrder(Node node) 465 { 466 if (node == null) return; 467 468 inOrder(node.left); 469 System.out.println(node.key + " " + node.color); 470 inOrder(node.right); 471 } 472 473 static class Node 474 { 475 Node parent; 476 Node left; 477 Node right; 478 char color = 'B'; 479 int key; 480 481 public Node(int key) 482 { 483 this.key = key; 484 } 485 486 public Node(char color) 487 { 488 this.color = color; 489 this.key = -Integer.MIN_VALUE; 490 } 491 } 492 493 public static void main(String[] args) 494 { 495 int[] array = new int[20]; 496 497 Random rond = new Random(); 498 for (int i = 0; i < array.length; i++) { 499 array[i] = Math.abs(rond.nextInt()) % 40; 500 } 501 502 RBTree tree = new RBTree(array); 503 //tree.preOrder(); 504 tree.inOrder(); 505 506 System.out.println(); 507 System.out.println("delete " + array[6]); 508 System.out.println(); 509 510 tree.delete(array[6]); 511 //tree.preOrder(); 512 tree.inOrder(); 513 } 514 }