github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/petar/GoLLRB/doc/Sedgewick-RedBlackBST.java (about) 1 public class RedBlackBST<Key extends Comparable<Key>, Value> 2 { 3 private static final int BST = 0; 4 private static final int TD234 = 1; 5 private static final int BU23 = 2; 6 private static final boolean RED = true; 7 private static final boolean BLACK = false; 8 9 private Node root; // root of the BST 10 private int k; // ordinal for drawing 11 private final int species; // species kind of tree for insert 12 private int heightBLACK; // black height of tree 13 14 RedBlackBST(int species) 15 { this.species = species; } 16 17 private class Node 18 { 19 Key key; // key 20 Value value; // associated data 21 Node left, right; // left and right subtrees 22 boolean color; // color of parent link 23 private int N; // number of nodes in tree rooted here 24 private int height; // height of tree rooted here 25 private double xc, yc; // for drawing 26 27 Node(Key key, Value value) 28 { 29 this.key = key; 30 this.value = value; 31 this.color = RED; 32 this.N = 1; 33 this.height = 1; 34 } 35 } 36 37 public int size() 38 { return size(root); } 39 40 private int size(Node x) 41 { 42 if (x == null) return 0; 43 else return x.N; 44 } 45 46 public int rootRank() 47 { 48 if (root == null) return 0; 49 else return size(root.left); 50 } 51 52 public int height() 53 { return height(root); } 54 55 public int heightB() 56 { return heightBLACK; } 57 58 private int height(Node x) 59 { 60 if (x == null) return 0; 61 else return x.height; 62 } 63 64 public boolean contains(Key key) 65 { return (get(key) != null); } 66 67 public Value get(Key key) 68 { return get(root, key); } 69 70 private Value get(Node x, Key key) 71 { 72 if (x == null) return null; 73 if (eq (key, x.key)) return x.value; 74 if (less(key, x.key)) return get(x.left, key); 75 else return get(x.right, key); 76 } 77 78 public Key min() 79 { 80 if (root == null) return null; 81 else return min(root); 82 } 83 84 private Key min(Node x) 85 { 86 if (x.left == null) return x.key; 87 else return min(x.left); 88 } 89 90 public Key max() 91 { 92 if (root == null) return null; 93 else return max(root); 94 } 95 96 private Key max(Node x) 97 { 98 if (x.right == null) return x.key; 99 else return max(x.right); 100 } 101 102 public void put(Key key, Value value) 103 { 104 root = insert(root, key, value); 105 if (isRed(root)) heightBLACK++; 106 root.color = BLACK; 107 } 108 109 private Node insert(Node h, Key key, Value value) 110 { 111 if (h == null) 112 return new Node(key, value); 113 114 if (species == TD234) 115 if (isRed(h.left) && isRed(h.right)) 116 colorFlip(h); 117 118 if (eq(key, h.key)) 119 h.value = value; 120 else if (less(key, h.key)) 121 h.left = insert(h.left, key, value); 122 else 123 h.right = insert(h.right, key, value); 124 125 if (species == BST) return setN(h); 126 127 if (isRed(h.right)) 128 h = rotateLeft(h); 129 130 if (isRed(h.left) && isRed(h.left.left)) 131 h = rotateRight(h); 132 133 if (species == BU23) 134 if (isRed(h.left) && isRed(h.right)) 135 colorFlip(h); 136 137 return setN(h); 138 } 139 140 public void deleteMin() 141 { 142 root = deleteMin(root); 143 root.color = BLACK; 144 } 145 146 private Node deleteMin(Node h) 147 { 148 if (h.left == null) 149 return null; 150 151 if (!isRed(h.left) && !isRed(h.left.left)) 152 h = moveRedLeft(h); 153 154 h.left = deleteMin(h.left); 155 156 return fixUp(h); 157 } 158 159 public void deleteMax() 160 { 161 root = deleteMax(root); 162 root.color = BLACK; 163 } 164 165 private Node deleteMax(Node h) 166 { 167 // if (h.right == null) 168 // { 169 // if (h.left != null) 170 // h.left.color = BLACK; 171 // return h.left; 172 // } 173 174 if (isRed(h.left)) 175 h = rotateRight(h); 176 177 if (h.right == null) 178 return null; 179 180 if (!isRed(h.right) && !isRed(h.right.left)) 181 h = moveRedRight(h); 182 183 h.right = deleteMax(h.right); 184 185 return fixUp(h); 186 } 187 188 public void delete(Key key) 189 { 190 root = delete(root, key); 191 root.color = BLACK; 192 } 193 194 private Node delete(Node h, Key key) 195 { 196 if (less(key, h.key)) 197 { 198 if (!isRed(h.left) && !isRed(h.left.left)) 199 h = moveRedLeft(h); 200 h.left = delete(h.left, key); 201 } 202 else 203 { 204 if (isRed(h.left)) 205 h = rotateRight(h); 206 if (eq(key, h.key) && (h.right == null)) 207 return null; 208 if (!isRed(h.right) && !isRed(h.right.left)) 209 h = moveRedRight(h); 210 if (eq(key, h.key)) 211 { 212 h.value = get(h.right, min(h.right)); 213 h.key = min(h.right); 214 h.right = deleteMin(h.right); 215 } 216 else h.right = delete(h.right, key); 217 } 218 219 return fixUp(h); 220 } 221 222 // Helper methods 223 224 private boolean less(Key a, Key b) { return a.compareTo(b) < 0; } 225 private boolean eq (Key a, Key b) { return a.compareTo(b) == 0; } 226 227 private boolean isRed(Node x) 228 { 229 if (x == null) return false; 230 return (x.color == RED); 231 } 232 233 private void colorFlip(Node h) 234 { 235 h.color = !h.color; 236 h.left.color = !h.left.color; 237 h.right.color = !h.right.color; 238 } 239 240 private Node rotateLeft(Node h) 241 { // Make a right-leaning 3-node lean to the left. 242 Node x = h.right; 243 h.right = x.left; 244 x.left = setN(h); 245 x.color = x.left.color; 246 x.left.color = RED; 247 return setN(x); 248 } 249 250 private Node rotateRight(Node h) 251 { // Make a left-leaning 3-node lean to the right. 252 Node x = h.left; 253 h.left = x.right; 254 x.right = setN(h); 255 x.color = x.right.color; 256 x.right.color = RED; 257 return setN(x); 258 } 259 260 private Node moveRedLeft(Node h) 261 { // Assuming that h is red and both h.left and h.left.left 262 // are black, make h.left or one of its children red. 263 colorFlip(h); 264 if (isRed(h.right.left)) 265 { 266 h.right = rotateRight(h.right); 267 h = rotateLeft(h); 268 colorFlip(h); 269 } 270 return h; 271 } 272 273 private Node moveRedRight(Node h) 274 { // Assuming that h is red and both h.right and h.right.left 275 // are black, make h.right or one of its children red. 276 colorFlip(h); 277 if (isRed(h.left.left)) 278 { 279 h = rotateRight(h); 280 colorFlip(h); 281 } 282 return h; 283 } 284 285 private Node fixUp(Node h) 286 { 287 if (isRed(h.right)) 288 h = rotateLeft(h); 289 290 if (isRed(h.left) && isRed(h.left.left)) 291 h = rotateRight(h); 292 293 if (isRed(h.left) && isRed(h.right)) 294 colorFlip(h); 295 296 return setN(h); 297 } 298 299 private Node setN(Node h) 300 { 301 h.N = size(h.left) + size(h.right) + 1; 302 if (height(h.left) > height(h.right)) h.height = height(h.left) + 1; 303 else h.height = height(h.right) + 1; 304 return h; 305 } 306 307 public String toString() 308 { 309 if (root == null) return ""; 310 else return heightB() + " " + toString(root); 311 } 312 313 public String toString(Node x) 314 { 315 String s = "("; 316 if (x.left == null) s += "("; else s += toString(x.left); 317 if (isRed(x)) s += "*"; 318 if (x.right == null) s += ")"; else s += toString(x.right); 319 return s + ")"; 320 } 321 322 // Methods for tree drawing 323 324 public void draw(double y, double lineWidth, double nodeSize) 325 { 326 k = 0; 327 setcoords(root, y); 328 StdDraw.setPenColor(StdDraw.BLACK); 329 StdDraw.setPenRadius(lineWidth); 330 drawlines(root); 331 StdDraw.setPenColor(StdDraw.WHITE); 332 drawnodes(root, nodeSize); 333 } 334 335 public void setcoords(Node x, double d) 336 { 337 if (x == null) return; 338 setcoords(x.left, d-.04); 339 x.xc = (0.5 + k++)/size(); x.yc = d - .04; 340 setcoords(x.right, d-.04); 341 } 342 343 public void drawlines(Node x) 344 { 345 if (x == null) return; 346 drawlines(x.left); 347 if (x.left != null) 348 { 349 if (x.left.color == RED) StdDraw.setPenColor(StdDraw.RED); 350 else StdDraw.setPenColor(StdDraw.BLACK); 351 StdDraw.line(x.xc, x.yc, x.left.xc, x.left.yc); 352 } 353 if (x.right != null) 354 { 355 if (x.right.color == RED) StdDraw.setPenColor(StdDraw.RED); 356 else StdDraw.setPenColor(StdDraw.BLACK); 357 StdDraw.line(x.xc, x.yc, x.right.xc, x.right.yc); 358 } 359 drawlines(x.right); 360 } 361 362 public void drawnodes(Node x, double nodeSize) 363 { 364 if (x == null) return; 365 drawnodes(x.left, nodeSize); 366 StdDraw.filledCircle(x.xc, x.yc, nodeSize); 367 drawnodes(x.right, nodeSize); 368 } 369 370 public void mark(Key key) 371 { 372 StdDraw.setPenColor(StdDraw.BLACK); 373 marknodes(key, root); 374 } 375 376 public void marknodes(Key key, Node x) 377 { 378 if (x == null) return; 379 marknodes(key, x.left); 380 if (eq(key, x.key)) 381 StdDraw.filledCircle(x.xc, x.yc, .004); 382 marknodes(key, x.right); 383 } 384 385 public int ipl() 386 { return ipl(root); } 387 388 public int ipl(Node x) 389 { 390 if (x == null) return 0; 391 return size(x) - 1 + ipl(x.left) + ipl(x.right); 392 } 393 394 public int sizeRed() 395 { return sizeRed(root); } 396 397 public int sizeRed(Node x) 398 { 399 if (x == null) return 0; 400 if (isRed(x)) return 1 + sizeRed(x.left) + sizeRed(x.right); 401 else return sizeRed(x.left) + sizeRed(x.right); 402 } 403 404 // Integrity checks 405 406 public boolean check() 407 { // Is this tree a red-black tree? 408 return isBST() && is234() && isBalanced(); 409 } 410 411 private boolean isBST() 412 { // Is this tree a BST? 413 return isBST(root, min(), max()); 414 } 415 416 private boolean isBST(Node x, Key min, Key max) 417 { // Are all the values in the BST rooted at x between min and max, 418 // and does the same property hold for both subtrees? 419 if (x == null) return true; 420 if (less(x.key, min) || less(max, x.key)) return false; 421 return isBST(x.left, min, x.key) && isBST(x.right, x.key, max); 422 } 423 424 private boolean is234() { return is234(root); } 425 private boolean is234(Node x) 426 { // Does the tree have no red right links, and at most two (left) 427 // red links in a row on any path? 428 if (x == null) return true; 429 if (isRed(x.right)) return false; 430 if (isRed(x)) 431 if (isRed(x.left)) 432 if (isRed(x.left.left)) return false; 433 return is234(x.left) && is234(x.right); 434 } 435 436 private boolean isBalanced() 437 { // Do all paths from root to leaf have same number of black edges? 438 int black = 0; // number of black links on path from root to min 439 Node x = root; 440 while (x != null) 441 { 442 if (!isRed(x)) black++; 443 x = x.left; 444 } 445 return isBalanced(root, black); 446 } 447 448 private boolean isBalanced(Node x, int black) 449 { // Does every path from the root to a leaf have the given number 450 // of black links? 451 if (x == null && black == 0) return true; 452 else if (x == null && black != 0) return false; 453 if (!isRed(x)) black--; 454 return isBalanced(x.left, black) && isBalanced(x.right, black); 455 } 456 457 458 public static void main(String[] args) 459 { 460 StdDraw.setPenRadius(.0025); 461 int species = Integer.parseInt(args[0]); 462 RedBlackBST<Integer, Integer> st; 463 st = new RedBlackBST<Integer, Integer>(species); 464 int[] a = { 3, 1, 4, 2, 5, 9, 6, 8, 7 }; 465 for (int i = 0; i < a.length; i++) 466 st.put(a[i], i); 467 StdOut.println(st); 468 StdDraw.clear(StdDraw.LIGHT_GRAY); 469 st.draw(.95, .0025, .008); 470 StdOut.println(st.min() + " " + st.max() + " " + st.check()); 471 StdOut.println(st.ipl()); 472 StdOut.println(st.heightB()); 473 } 474 475 }