▶ 书中第三章部分程序,加上自己补充的代码,红黑树
● 红黑树,大部分方法与注释与二叉树相同
1 package package01; 2 3 import java.util.NoSuchElementException; 4 import edu.princeton.cs.algs4.Queue; 5 import edu.princeton.cs.algs4.StdIn; 6 import edu.princeton.cs.algs4.StdOut; 7 8 public class class01<Key extends Comparable<Key>, Value> 9 { 10 private static final boolean RED = true; 11 private static final boolean BLACK = false; 12 13 private class Node 14 { 15 private Key key; 16 private Value val; 17 private Node left, right; 18 private boolean color; // 指向该节点的连接的颜色 19 private int size; 20 21 public Node(Key key, Value val, boolean color, int size) 22 { 23 this.key = key; 24 this.val = val; 25 this.color = color; 26 this.size = size; 27 } 28 } 29 30 private Node root; 31 32 public class01() {} 33 34 private boolean isRed(Node x) 35 { 36 if (x == null) 37 return false; 38 return x.color == RED; 39 } 40 41 public int size() 42 { 43 return size(root); 44 } 45 46 private int size(Node x) 47 { 48 if (x == null) 49 return 0; 50 return x.size; 51 } 52 53 public boolean isEmpty() 54 { 55 return size() == 0; //return root == null; 56 } 57 58 public Value get(Key key) // 查找 59 { 60 if (key == null) 61 throw new IllegalArgumentException("\n<get> key == null.\n"); 62 return getKernel(root, key); 63 } 64 65 private Value getKernel(Node x, Key key)// 查找内核,使用了非递归实现 66 { 67 for (int cmp = key.compareTo(x.key); x != null; cmp = key.compareTo(x.key)) 68 { 69 if (cmp < 0) 70 x = x.left; 71 else if (cmp > 0) 72 x = x.right; 73 else 74 return x.val; 75 } 76 return null; 77 } 78 79 public boolean contains(Key key) // 判断 key 是否在树中 80 { 81 if (key == null) 82 throw new IllegalArgumentException("\n<contains> key == null.\n"); 83 return get(key) != null; 84 } 85 86 public void put(Key key, Value val) // 插入 87 { 88 if (key == null) 89 throw new IllegalArgumentException("\n<put> key == null.\n"); 90 if (val == null) 91 delete(key); 92 else 93 { 94 root = putKernel(root, key, val); 95 root.color = BLACK; 96 } 97 // assert check(); 98 } 99 100 private Node putKernel(Node x, Key key, Value val) 101 { 102 if (x == null) 103 return new Node(key, val, RED, 1); 104 int cmp = key.compareTo(x.key); 105 if (cmp < 0) 106 x.left = putKernel(x.left, key, val); 107 else if (cmp > 0) 108 x.right = putKernel(x.right, key, val); 109 else 110 x.val = val; 111 if (isRed(x.right) && !isRed(x.left)) 112 x = rotateLeft(x); 113 if (isRed(x.left) && isRed(x.left.left)) 114 x = rotateRight(x); 115 if (isRed(x.left) && isRed(x.right)) 116 flipColors(x); 117 x.size = 1 + size(x.left) + size(x.right); 118 return x; 119 } 120 121 public void deleteMin() 122 { 123 if (isEmpty()) 124 throw new NoSuchElementException("\n<deleteMin> underflow.\n"); 125 if (!isRed(root.left) && !isRed(root.right)) 126 root.color = RED; 127 root = deleteMinKernel(root); 128 if (!isEmpty()) 129 root.color = BLACK; 130 // assert check(); 131 } 132 133 private Node deleteMinKernel(Node x) 134 { 135 if (x.left == null) 136 return null; 137 if (!isRed(x.left) && !isRed(x.left.left)) 138 x = moveRedLeft(x); 139 x.left = deleteMinKernel(x.left); 140 return balance(x); 141 } 142 143 public void deleteMax() 144 { 145 if (isEmpty()) 146 throw new NoSuchElementException("\n<deleteMax> underflow.\n"); 147 if (!isRed(root.left) && !isRed(root.right)) 148 root.color = RED; 149 root = deleteMaxKernel(root); 150 if (!isEmpty()) 151 root.color = BLACK; 152 // assert check(); 153 } 154 155 private Node deleteMaxKernel(Node x) 156 { 157 if (isRed(x.left)) 158 x = rotateRight(x); 159 if (x.right == null) 160 return null; 161 if (!isRed(x.right) && !isRed(x.right.left)) 162 x = moveRedRight(x); 163 x.right = deleteMaxKernel(x.right); 164 return balance(x); 165 } 166 167 public void delete(Key key) 168 { 169 if (key == null) 170 throw new IllegalArgumentException("\n<delete> key == null.\n"); 171 if (!contains(key)) 172 return; 173 if (!isRed(root.left) && !isRed(root.right)) 174 root.color = RED; 175 root = deleteKernel(root, key); 176 if (!isEmpty()) 177 root.color = BLACK; 178 // assert check(); 179 } 180 181 private Node deleteKernel(Node x, Key key) 182 { 183 if (key.compareTo(x.key) < 0) 184 { 185 if (!isRed(x.left) && !isRed(x.left.left)) 186 x = moveRedLeft(x); 187 x.left = deleteKernel(x.left, key); 188 } 189 else 190 { 191 if (isRed(x.left)) 192 x = rotateRight(x); 193 if (key.compareTo(x.key) == 0 && (x.right == null)) 194 return null; 195 if (!isRed(x.right) && !isRed(x.right.left)) 196 x = moveRedRight(x); 197 if (key.compareTo(x.key) == 0) 198 { 199 Node t = minKernel(x.right); 200 x.key = t.key; 201 x.val = t.val; 202 // x.val = get(x.right, min(x.right).key); 203 // x.key = min(x.right).key; 204 x.right = deleteMinKernel(x.right); 205 } 206 else x.right = deleteKernel(x.right, key); 207 } 208 return balance(x); 209 } 210 211 private Node rotateRight(Node x) // 右旋转 212 { 213 Node t = x.left; 214 x.left = t.right; 215 t.right = x; 216 t.color = t.right.color; 217 t.right.color = RED; 218 t.size = x.size; 219 x.size = 1 + size(x.left) + size(x.right); 220 return t; 221 } 222 223 private Node rotateLeft(Node x) // 左旋转 224 { 225 Node t = x.right; 226 x.right = t.left; 227 t.left = x; 228 t.color = t.left.color; 229 t.left.color = RED; 230 t.size = x.size; 231 x.size = 1 + size(x.left) + size(x.right); 232 return t; 233 } 234 235 private void flipColors(Node x) // 改变节点及其子节点的颜色 236 { 237 // assert (x != null) && (x.left != null) && (x.right != null); 238 // assert (!isRed(x) && isRed(x.left) && isRed(x.right)) || (isRed(x) && !isRed(x.left) && !isRed(x.right)); 239 x.color = !x.color; 240 x.left.color = !x.left.color; 241 x.right.color = !x.right.color; 242 } 243 244 private Node moveRedLeft(Node x) // x 红而 x.left 和 x.left.left 都是黑的,调整使得两个黑链接之一变红 245 { 246 // assert (x != null); 247 // assert isRed(x) && !isRed(x.left) && !isRed(x.left.left); 248 flipColors(x); 249 if (isRed(x.right.left)) 250 { 251 x.right = rotateRight(x.right); 252 x = rotateLeft(x); 253 flipColors(x); 254 } 255 return x; 256 } 257 258 private Node moveRedRight(Node x) // x 红而 x.right 和 x.right.left 都是黑的,调整使得两黑链接之一变红 259 { 260 // assert (x != null); 261 // assert isRed(x) && !isRed(x.right) && !isRed(x.right.left); 262 flipColors(x); 263 if (isRed(x.left.left)) 264 { 265 x = rotateRight(x); 266 flipColors(x); 267 } 268 return x; 269 } 270 271 private Node balance(Node x) // 右链接红色、连续两层左链接红色以及左右链接都是红色的状况,分别调整 272 { 273 // assert (x != null); 274 if (isRed(x.right)) 275 x = rotateLeft(x); 276 if (isRed(x.left) && isRed(x.left.left)) 277 x = rotateRight(x); 278 if (isRed(x.left) && isRed(x.right)) 279 flipColors(x); 280 x.size = 1 + size(x.left) + size(x.right); 281 return x; 282 } 283 284 public Key min() 285 { 286 if (isEmpty()) 287 throw new NoSuchElementException("\n<delete> empty.\n"); 288 return minKernel(root).key; 289 } 290 291 private Node minKernel(Node x) 292 { 293 if (x.left == null) 294 return x; 295 return minKernel(x.left); 296 } 297 298 public Key max() 299 { 300 if (isEmpty()) 301 throw new NoSuchElementException("\n<max> empty.\n"); 302 return maxKernel(root).key; 303 } 304 305 private Node maxKernel(Node x) 306 { 307 if (x.right == null) 308 return x; 309 return maxKernel(x.right); 310 } 311 312 public Key floor(Key key) 313 { 314 if (key == null) 315 throw new IllegalArgumentException("\n<floor> key == null.\n"); 316 if (isEmpty()) 317 throw new NoSuchElementException("\n<floor> empty.\n"); 318 Node x = floorKernel(root, key); 319 return (x == null) ? null : x.key; 320 } 321 322 private Node floorKernel(Node x, Key key) 323 { 324 if (x == null) 325 return null; 326 int cmp = key.compareTo(x.key); 327 if (cmp == 0) 328 return x; 329 if (cmp < 0) 330 return floorKernel(x.left, key); 331 Node t = floorKernel(x.right, key); 332 return (t == null) ? x : t; 333 } 334 335 public Key ceiling(Key key) 336 { 337 if (key == null) 338 throw new IllegalArgumentException("\n<ceiling> key == null.\n"); 339 if (isEmpty()) 340 throw new NoSuchElementException("\n<ceiling> empty.\n"); 341 Node x = ceilingKernel(root, key); 342 return (x == null) ? null : x.key; 343 } 344 345 private Node ceilingKernel(Node x, Key key) 346 { 347 if (x == null) 348 return null; 349 int cmp = key.compareTo(x.key); 350 if (cmp == 0) 351 return x; 352 if (cmp > 0) 353 return ceilingKernel(x.right, key); 354 Node t = ceilingKernel(x.left, key); 355 return (t == null) ? x : t; 356 } 357 358 public Key select(int k) 359 { 360 if (k < 0 || k >= size()) 361 throw new IllegalArgumentException("\n<select> k < 0 || k >= size().\n"); 362 return selectKernel(root, k).key; 363 } 364 365 private Node selectKernel(Node x, int k) 366 { 367 if (x == null) 368 return null; 369 int t = size(x.left); 370 if (k <t) 371 return selectKernel(x.left, k); 372 if (k > t) 373 return selectKernel(x.right, k - t - 1); 374 return x; 375 } 376 377 public int rank(Key key) 378 { 379 if (key == null) 380 throw new IllegalArgumentException("\n<rank> key == null.\n"); 381 return rankKernel(key, root); 382 } 383 384 private int rankKernel(Key key, Node x) 385 { 386 if (x == null) 387 return 0; 388 int cmp = key.compareTo(x.key); 389 if (cmp < 0) 390 return rankKernel(key, x.left); 391 if (cmp > 0) 392 return 1 + size(x.left) + rankKernel(key, x.right); 393 return size(x.left); 394 } 395 396 public Iterable<Key> keys() 397 { 398 if (isEmpty()) 399 return new Queue<Key>(); 400 Key lo = min(), hi = max(); 401 if (lo == null) 402 throw new IllegalArgumentException("\n<iterable> lo == null.\n"); 403 if (hi == null) 404 throw new IllegalArgumentException("\n<iterable> hi == null.\n"); 405 Queue<Key> queue = new Queue<Key>(); 406 // if (isEmpty() || lo.compareTo(hi) > 0) return queue; 407 keysKernel(root, queue, lo, hi); 408 return queue; 409 } 410 411 private void keysKernel(Node x, Queue<Key> queue, Key lo, Key hi) 412 { 413 if (x == null) 414 return; 415 int cmplo = lo.compareTo(x.key), cmphi = hi.compareTo(x.key); 416 if (cmplo < 0) 417 keysKernel(x.left, queue, lo, hi); 418 if (cmplo <= 0 && cmphi >= 0) 419 queue.enqueue(x.key); 420 if (cmphi > 0) 421 keysKernel(x.right, queue, lo, hi); 422 } 423 424 public Iterable<Key> levelOrder() 425 { 426 Queue<Key> keys = new Queue<Key>(); 427 Queue<Node> queue = new Queue<Node>(); 428 for (queue.enqueue(root); !queue.isEmpty();) 429 { 430 Node x = queue.dequeue(); 431 if (x == null) 432 continue; 433 keys.enqueue(x.key); 434 queue.enqueue(x.left); 435 queue.enqueue(x.right); 436 } 437 return keys; 438 } 439 440 public int size(Key lo, Key hi) 441 { 442 if (lo == null) 443 throw new IllegalArgumentException("\n<size> lo == null.\n"); 444 if (hi == null) 445 throw new IllegalArgumentException("\n<size> hi == null.\n"); 446 if (lo.compareTo(hi) > 0) 447 return 0; 448 if (contains(hi)) 449 return rank(hi) - rank(lo) + 1; 450 return rank(hi) - rank(lo); 451 } 452 453 public int height() 454 { 455 return heightKernel(root); 456 } 457 458 private int heightKernel(Node x) 459 { 460 if (x == null) 461 return -1; 462 return 1 + Math.max(heightKernel(x.left), heightKernel(x.right)); 463 } 464 465 private boolean check() 466 { 467 if (!isBST()) 468 StdOut.println("\n<check> Not in symmetric order.\n"); 469 if (!isSizeConsistent()) 470 StdOut.println("\n<check> Subtree counts not consistent.\n"); 471 if (!isRankConsistent()) 472 StdOut.println("\n<check> Ranks not consistent.\n"); 473 if (!is23()) 474 StdOut.println("\n<check> Not a 2 - 3 tree.\n"); 475 if (!isBalanced()) 476 StdOut.println("\n<check> Not balanced.\n"); 477 return isBST() && isSizeConsistent() && isRankConsistent() && is23() && isBalanced(); 478 } 479 480 private boolean isBST() 481 { 482 return isBSTKernel(root, null, null); 483 } 484 485 private boolean isBSTKernel(Node x, Key min, Key max) 486 { 487 if (x == null) 488 return true; 489 if (min != null && x.key.compareTo(min) <= 0) 490 return false; 491 if (max != null && x.key.compareTo(max) >= 0) 492 return false; 493 return isBSTKernel(x.left, min, x.key) && isBSTKernel(x.right, x.key, max); 494 } 495 496 private boolean isSizeConsistent() 497 { 498 return isSizeConsistentKernel(root); 499 } 500 501 private boolean isSizeConsistentKernel(Node x) 502 { 503 if (x == null) 504 return true; 505 if (x.size != 1 + size(x.left) + size(x.right)) 506 return false; 507 return isSizeConsistentKernel(x.left) && isSizeConsistentKernel(x.right); 508 } 509 510 private boolean isRankConsistent() 511 { 512 for (int i = 0; i < size(); i++) 513 { 514 if (i != rank(select(i))) 515 return false; 516 } 517 for (Key key : keys()) 518 { 519 if (key.compareTo(select(rank(key))) != 0) 520 return false; 521 } 522 return true; 523 } 524 525 private boolean is23() 526 { 527 return is23Kernel(root); 528 } 529 530 private boolean is23Kernel(Node x) 531 { 532 if (x == null) 533 return true; 534 if (isRed(x.right)) 535 return false; 536 if (x != root && isRed(x) && isRed(x.left)) 537 return false; 538 return is23Kernel(x.left) && is23Kernel(x.right); 539 } 540 541 private boolean isBalanced() 542 { 543 int black = 0; // 从 root 到 min 节点的路径长 544 for(Node x = root;x != null; x = x.left) 545 { 546 if (!isRed(x)) 547 black++; 548 } 549 return isBalancedKernel(root, black); 550 } 551 552 private boolean isBalancedKernel(Node x, int black) 553 { 554 if (x == null) 555 return black == 0; 556 if (!isRed(x)) 557 black--; 558 return isBalancedKernel(x.left, black) && isBalancedKernel(x.right, black); 559 } 560 561 public static void main(String[] args) 562 { 563 class01<String, Integer> st = new class01<String, Integer>(); 564 for (int i = 0; !StdIn.isEmpty(); i++) 565 { 566 String key = StdIn.readString(); 567 st.put(key, i); 568 } 569 570 for (String s : st.levelOrder()) 571 StdOut.println(s + " " + st.get(s)); 572 573 StdOut.println(); 574 for (String s : st.keys()) 575 StdOut.println(s + " " + st.get(s)); 576 } 577 }// 703