001// Exercise 3.2.6 3.2.32 3.2.33 (Solution published at http://algs4.cs.princeton.edu/) 002package algs32; 003import stdlib.*; 004import algs13.Queue; 005/* *********************************************************************** 006 * Compilation: javac BST.java 007 * Execution: java BST 008 * Dependencies: StdIn.java StdOut.java 009 * Data files: http://algs4.cs.princeton.edu/32bst/tinyST.txt 010 * 011 * A symbol table implemented with a binary search tree. 012 * 013 * % more tinyST.txt 014 * S E A R C H E X A M P L E 015 * 016 * % java BST < tinyST.txt 017 * A 8 018 * C 4 019 * E 12 020 * H 5 021 * L 11 022 * M 9 023 * P 10 024 * R 3 025 * S 0 026 * X 7 027 * 028 *************************************************************************/ 029public class BST<K extends Comparable<? super K>, V> { 030 private Node<K,V> root; // root of BST 031 032 private static class Node<K extends Comparable<? super K>,V> { 033 public final K key; // sorted by key 034 public V val; // associated data 035 public Node<K,V> left, right; // left and right subtrees 036 public int N; // number of nodes in subtree 037 038 public Node(K key, V val, int N) { 039 this.key = key; 040 this.val = val; 041 this.N = N; 042 } 043 } 044 045 // is the symbol table empty? 046 public boolean isEmpty() { return size() == 0; } 047 048 // return number of key-value pairs in BST 049 public int size() { return size(root); } 050 051 // return number of key-value pairs in BST rooted at x 052 private int size(Node<K,V> x) { 053 if (x == null) return 0; 054 else return x.N; 055 } 056 057 /* ********************************************************************* 058 * Search BST for given key, and return associated value if found, 059 * return null if not found 060 ***********************************************************************/ 061 // does there exist a key-value pair with given key? 062 public boolean contains(K key) { 063 return get(key) != null; 064 } 065 066 // return value associated with the given key, or null if no such key exists 067 public V get(K key) { return get(root, key); } 068 private V get(Node<K,V> x, K key) { 069 if (x == null) return null; 070 int cmp = key.compareTo(x.key); 071 if (cmp < 0) return get(x.left, key); 072 else if (cmp > 0) return get(x.right, key); 073 else return x.val; 074 } 075 076 /* ********************************************************************* 077 * Insert key-value pair into BST 078 * If key already exists, update with new value 079 ***********************************************************************/ 080 public void put(K key, V val) { 081 if (val == null) { delete(key); return; } 082 root = put(root, key, val); 083 //assert check(); 084 } 085 086 private Node<K,V> put(Node<K,V> x, K key, V val) { 087 if (x == null) return new Node<>(key, val, 1); 088 int cmp = key.compareTo(x.key); 089 if (cmp < 0) 090 x.left = put(x.left, key, val); 091 else if (cmp > 0) 092 x.right = put(x.right, key, val); 093 else 094 x.val = val; 095 x.N = 1 + size(x.left) + size(x.right); 096 return x; 097 } 098 099 /* ********************************************************************* 100 * Delete 101 ***********************************************************************/ 102 103 public void deleteMin() { 104 if (isEmpty()) throw new Error("Symbol table underflow"); 105 root = deleteMin(root); 106 //assert check(); 107 } 108 109 private Node<K,V> deleteMin(Node<K,V> x) { 110 if (x.left == null) return x.right; 111 x.left = deleteMin(x.left); 112 x.N = size(x.left) + size(x.right) + 1; 113 return x; 114 } 115 116 public void deleteMax() { 117 if (isEmpty()) throw new Error("Symbol table underflow"); 118 root = deleteMax(root); 119 //assert check(); 120 } 121 122 private Node<K,V> deleteMax(Node<K,V> x) { 123 if (x.right == null) return x.left; 124 x.right = deleteMax(x.right); 125 x.N = size(x.left) + size(x.right) + 1; 126 return x; 127 } 128 129 public void delete(K key) { 130 root = delete(root, key); 131 //assert check(); 132 } 133 134 private Node<K,V> delete(Node<K,V> x, K key) { 135 if (x == null) return null; 136 int cmp = key.compareTo(x.key); 137 if (cmp < 0) x.left = delete(x.left, key); 138 else if (cmp > 0) x.right = delete(x.right, key); 139 else { 140 if (x.right == null) return x.left; 141 if (x.left == null) return x.right; 142 Node<K,V> t = x; 143 x = min(t.right); 144 x.right = deleteMin(t.right); 145 x.left = t.left; 146 } 147 x.N = size(x.left) + size(x.right) + 1; 148 return x; 149 } 150 151 152 /* ********************************************************************* 153 * Min, max, floor, and ceiling 154 ***********************************************************************/ 155 public K min() { 156 if (isEmpty()) return null; 157 return min(root).key; 158 } 159 160 private Node<K,V> min(Node<K,V> x) { 161 if (x.left == null) return x; 162 else return min(x.left); 163 } 164 165 public K max() { 166 if (isEmpty()) return null; 167 return max(root).key; 168 } 169 170 private Node<K,V> max(Node<K,V> x) { 171 if (x.right == null) return x; 172 else return max(x.right); 173 } 174 175 public K floor(K key) { 176 Node<K,V> x = floor(root, key); 177 if (x == null) return null; 178 else return x.key; 179 } 180 181 private Node<K,V> floor(Node<K,V> x, K key) { 182 if (x == null) return null; 183 int cmp = key.compareTo(x.key); 184 if (cmp == 0) return x; 185 if (cmp < 0) return floor(x.left, key); 186 Node<K,V> t = floor(x.right, key); 187 if (t != null) return t; 188 else return x; 189 } 190 191 public K ceiling(K key) { 192 Node<K,V> x = ceiling(root, key); 193 if (x == null) return null; 194 else return x.key; 195 } 196 197 private Node<K,V> ceiling(Node<K,V> x, K key) { 198 if (x == null) return null; 199 int cmp = key.compareTo(x.key); 200 if (cmp == 0) return x; 201 if (cmp < 0) { 202 Node<K,V> t = ceiling(x.left, key); 203 if (t != null) return t; 204 else return x; 205 } 206 return ceiling(x.right, key); 207 } 208 209 /* ********************************************************************* 210 * Rank and selection 211 ***********************************************************************/ 212 public K select(int k) { 213 if (k < 0 || k >= size()) return null; 214 Node<K,V> x = select(root, k); 215 return x.key; 216 } 217 218 // Return key of rank k. 219 private Node<K,V> select(Node<K,V> x, int k) { 220 if (x == null) return null; 221 int t = size(x.left); 222 if (t > k) return select(x.left, k); 223 else if (t < k) return select(x.right, k-t-1); 224 else return x; 225 } 226 227 public int rank(K key) { 228 return rank(key, root); 229 } 230 231 // Number of keys in the subtree less than x.key. 232 private int rank(K key, Node<K,V> x) { 233 if (x == null) return 0; 234 int cmp = key.compareTo(x.key); 235 if (cmp < 0) return rank(key, x.left); 236 else if (cmp > 0) return 1 + size(x.left) + rank(key, x.right); 237 else return size(x.left); 238 } 239 240 /* ********************************************************************* 241 * Range count and range search. 242 ***********************************************************************/ 243 public Iterable<K> keys() { 244 Queue<K> q = new Queue<>(); 245 inOrder(root, q); 246 return q; 247 } 248 249 private void inOrder(Node<K,V> x, Queue<K> q) { 250 if (x == null) return; 251 inOrder(x.left, q); 252 inOrder(x.right, q); 253 q.enqueue(x.key); 254 } 255 256 public Iterable<K> keys(K lo, K hi) { 257 Queue<K> queue = new Queue<>(); 258 inOrder(root, queue, lo, hi); 259 return queue; 260 } 261 262 private void inOrder(Node<K,V> x, Queue<K> queue, K lo, K hi) { 263 if (x == null) return; 264 int cmplo = lo.compareTo(x.key); 265 int cmphi = hi.compareTo(x.key); 266 if (cmplo < 0) inOrder(x.left, queue, lo, hi); 267 if (cmplo <= 0 && cmphi >= 0) queue.enqueue(x.key); 268 if (cmphi > 0) inOrder(x.right, queue, lo, hi); 269 } 270 271 public int size(K lo, K hi) { 272 if (lo.compareTo(hi) > 0) return 0; 273 if (contains(hi)) return rank(hi) - rank(lo) + 1; 274 else return rank(hi) - rank(lo); 275 } 276 277 278 // height of this BST (one-node tree has height 0) 279 public int height() { return height(root); } 280 private int height(Node<K,V> x) { 281 if (x == null) return -1; 282 return 1 + Math.max(height(x.left), height(x.right)); 283 } 284 285 // level order traversal 286 public Iterable<K> levelOrder() { 287 Queue<K> keys = new Queue<>(); 288 Queue<Node<K,V>> queue = new Queue<>(); 289 queue.enqueue(root); 290 while (!queue.isEmpty()) { 291 Node<K,V> x = queue.dequeue(); 292 if (x == null) continue; 293 keys.enqueue(x.key); 294 queue.enqueue(x.left); 295 queue.enqueue(x.right); 296 } 297 return keys; 298 } 299 300 /* *********************************************************************** 301 * Check integrity of BST data structure 302 *************************************************************************/ 303 private boolean check() { 304 if (!isBST()) StdOut.println("Not in symmetric order"); 305 if (!isSizeConsistent()) StdOut.println("Subtree counts not consistent"); 306 if (!isRankConsistent()) StdOut.println("Ranks not consistent"); 307 return isBST() && isSizeConsistent() && isRankConsistent(); 308 } 309 310 // does this binary tree satisfy symmetric order? 311 // Note: this test also ensures that data structure is a binary tree since order is strict 312 private boolean isBST() { 313 return isBST(root, null, null); 314 } 315 316 // is the tree rooted at x a BST with all keys strictly between min and max 317 // (if min or max is null, treat as empty constraint) 318 // Credit: Bob Dondero's elegant solution 319 private boolean isBST(Node<K,V> x, K min, K max) { 320 if (x == null) return true; 321 if (min != null && x.key.compareTo(min) <= 0) return false; 322 if (max != null && x.key.compareTo(max) >= 0) return false; 323 return isBST(x.left, min, x.key) && isBST(x.right, x.key, max); 324 } 325 326 // are the size fields correct? 327 private boolean isSizeConsistent() { return isSizeConsistent(root); } 328 private boolean isSizeConsistent(Node<K,V> x) { 329 if (x == null) return true; 330 if (x.N != size(x.left) + size(x.right) + 1) return false; 331 return isSizeConsistent(x.left) && isSizeConsistent(x.right); 332 } 333 334 // check that ranks are consistent 335 private boolean isRankConsistent() { 336 for (int i = 0; i < size(); i++) 337 if (i != rank(select(i))) return false; 338 for (K key : keys()) 339 if (key.compareTo(select(rank(key))) != 0) return false; 340 return true; 341 } 342 343 /* *************************************************************************** 344 * Visualization 345 *****************************************************************************/ 346 public String toString() { 347 StringBuilder sb = new StringBuilder(); 348 for (K key: levelOrder()) 349 sb.append (key + " "); 350 return sb.toString (); 351 } 352 353 public void toGraphviz(String filename) { 354 GraphvizBuilder gb = new GraphvizBuilder (); 355 toGraphviz (gb, null, root); 356 gb.toFileUndirected (filename, "ordering=\"out\""); 357 } 358 private void toGraphviz (GraphvizBuilder gb, Node<K,V> parent, Node<K,V> n) { 359 if (n == null) { gb.addNullEdge (parent); return; } 360 gb.addLabeledNode (n, n.key.toString ()); 361 if (parent != null) gb.addEdge (parent, n); 362 toGraphviz (gb, n, n.left); 363 toGraphviz (gb, n, n.right); 364 } 365 366 // You may modify "drawTree" if you wish 367 public void drawTree() { 368 if (root != null) { 369 StdDraw.setPenColor (StdDraw.BLACK); 370 StdDraw.setCanvasSize(1200,700); 371 drawTree(root, .5, 1, .25, 0); 372 } 373 } 374 private void drawTree (Node<K,V> n, double x, double y, double range, int depth) { 375 int CUTOFF = 10; 376 StdDraw.text (x, y, n.key.toString ()); 377 StdDraw.setPenRadius (.007); 378 if (n.left != null && depth != CUTOFF) { 379 StdDraw.line (x-range, y-.08, x-.01, y-.01); 380 drawTree (n.left, x-range, y-.1, range*.5, depth+1); 381 } 382 if (n.right != null && depth != CUTOFF) { 383 StdDraw.line (x+range, y-.08, x+.01, y-.01); 384 drawTree (n.right, x+range, y-.1, range*.5, depth+1); 385 } 386 } 387 388 /* *************************************************************************** 389 * Test client 390 *****************************************************************************/ 391 public static void main(String[] args) { 392 //StdIn.fromString ("S E A R C H E X A M P L E"); 393 //StdIn.fromString ("D F B G E A C"); 394 StdIn.fromString ("C A B E D"); 395 396 BST<String, Integer> st = new BST<>(); 397 for (int i = 0; !StdIn.isEmpty(); i++) { 398 String key = StdIn.readString(); 399 st.put(key, i); 400 } 401 //GraphvizBuilder.nodesToFile (st.root); 402 st.toGraphviz ("g.png"); 403 // st.drawTree (); 404 Iterable<String> keys = st.levelOrder(); 405 for (String s : keys) 406 StdOut.println(s + " " + st.get(s)); 407 // StdOut.println(); 408 // for (String s : st.keys()) 409 // StdOut.println(s + " " + st.get(s)); 410 } 411}