1. 程式人生 > >查詢演算法之——二叉查詢樹(圖文分析)

查詢演算法之——二叉查詢樹(圖文分析)

  1 package Unit3;
  2 
  3 import java.util.Stack;
  4 
  5 import edu.princeton.cs.algs4.Queue;
  6 
  7 public class BST<Key extends Comparable<Key>, Value> {// 二叉查詢樹
  8     private Node root;// 查詢二叉樹的根節點
  9 
 10     private class Node {
 11         private Key key;//
 12         private
Value val;// 13 private Node left, right;// 指向子樹的連結 14 private int N;// 以該節點為根節點的子樹中的總節點數 15 16 public Node(Key key, Value val, int N) { 17 this.key = key; 18 this.val = val; 19 this.N = N; 20 } 21 } 22 23 public
int size() { 24 return size(root); 25 } 26 27 private int size(Node x) { 28 if (x != null) { 29 return x.N; 30 } else { 31 return 0; 32 } 33 } 34 35 public Value get(Key key) {// 返回鍵key對應的值 36 return
get(root, key); 37 } 38 39 private Value get(Node x, Key key) {// 遞迴 40 if (key == null) { 41 return null; 42 } 43 int cmp = key.compareTo(x.key); 44 if (cmp < 0) { 45 return get(x.left, key); 46 } else if (cmp > 0) { 47 return get(x.right, key); 48 } else 49 return x.val; 50 } 51 52 /* 53 * private Value getTwo(Node x, Key key) {// 非遞迴 if (key == null) { return null; 54 * } int cmp; while (x != null) { cmp = key.compareTo(x.key); if (cmp < 0) { x = 55 * x.left; } else if (cmp > 0) { x = x.right; } else return x.val; } return 56 * null; } 57 */ 58 59 public void put(Key key, Value val) { 60 root = put(root, key, val); 61 } 62 63 private Node put(Node x, Key key, Value val) { 64 if (x == null) {// 建立新節點 65 return new Node(key, val, 1); 66 } 67 int cmp = key.compareTo(x.key); 68 if (cmp < 0) { 69 x.left = put(x.left, key, val); 70 } else if (cmp > 0) { 71 x.right = put(x.right, key, val); 72 } else { 73 x.val = val; 74 } 75 x.N = size(x.left) + size(x.right) + 1; 76 return x;// 在插入結束時返回(更新節點的相關資訊) 77 } 78 79 private Node putTwo(Node x, Key key, Value val) {// 在存在基本操作基礎上的非遞迴put() 80 if (get(key) != null) { 81 select(root, rank(key)).val = val; 82 } 83 return x; 84 } 85 86 public Key min() { 87 return min(root).key; 88 } 89 90 private Node min(Node x) { 91 if (x.left == null) { 92 return x; 93 } 94 return min(x.left); 95 } 96 97 public Key max() { 98 return max(root).key; 99 } 100 101 private Node max(Node x) { 102 if (x.right == null) { 103 return x; 104 } 105 return min(x.right); 106 } 107 108 public Key floor(Key key) { 109 Node x = floor(root, key); 110 if (x == null) { 111 return null; 112 } 113 return x.key; 114 } 115 116 // private Node floor(Node x, Key key) {//測試(個人思路 117 // if(x==null) { 118 // return null; 119 // } 120 // int cmp=key.compareTo(x.key); 121 // if(cmp<0) { 122 // return floor(x.left,key); 123 // }else if(cmp>0) { 124 // if(x.right==null) { 125 // return x.right; 126 // } 127 // return floor(x.right,key); 128 // } 129 // else { 130 // return x; 131 // } 132 // } 133 134 private Node floor(Node x, Key key) {// 類似前序遍歷 找到後不再執行後續操作 135 if (x == null) { 136 return null; 137 } 138 int cmp = key.compareTo(x.key); 139 if (cmp == 0) { 140 return x; 141 } 142 if (cmp < 0) { 143 return floor(x.left, key); 144 } 145 Node f = floor(x.right, key); 146 if (f != null) { 147 return f; 148 } else { 149 return x; 150 } 151 } 152 153 public Key ceiling(Key key) { 154 Node x = ceiling(root, key); 155 if (x == null) { 156 return null; 157 } 158 return x.key; 159 } 160 161 private Node ceiling(Node x, Key key) { 162 if (x == null) { 163 return null; 164 } 165 int cmp = key.compareTo(x.key); 166 if (cmp == 0) { 167 return x; 168 } 169 if (cmp > 0) {// 往大找 170 return ceiling(x.right, key); 171 } 172 Node f = floor(x.left, key); 173 if (f != null) { 174 return f; 175 } else { 176 return x; 177 } 178 } 179 180 public Key FOC(Key key, String s) {// 合併兩個方法(自創 181 Node x = null; 182 if (s.equals("floor")) { 183 x = floor(root, key); 184 } else if (s.equals("ceiling")) { 185 x = ceiling(root, key); 186 } else { 187 System.out.println("輸入錯誤!將返回null"); 188 } 189 if (x == null) { 190 return null; 191 } 192 return x.key; 193 } 194 195 public Key select(int k) {// 返回排名為k的鍵 196 return select(root, k).key; 197 } 198 199 public Node select(Node x, int k) {// 返回排名為k的節點 200 if (x == null) { 201 return null; 202 } 203 int t = size(x.left); 204 if (t > k) { 205 return select(x.left, k); 206 } else if (t < k) { 207 return select(x.right, k - t - 1); 208 } else { 209 return x; 210 } 211 } 212 213 public Node selectTwo(Node x, int k) { 214 if (x == null) { 215 return null; 216 } 217 while (k != size(x.left)) { 218 if (size(x.left) > k) { 219 x = x.left; 220 } else { 221 x = x.right; 222 k = k - size(x.left) - 1; 223 } 224 } 225 return x; 226 } 227 228 public int rank(Key key) {// 返回key的排名 229 return rank(key, root); 230 } 231 232 private int rank(Key key, Node x) { 233 if (key == null) { 234 return 0; 235 } 236 int cmp = key.compareTo(x.key); 237 if (cmp < 0) { 238 return rank(key, x.left); 239 } else if (cmp > 0) { 240 return rank(key, x.right) + size(x.left) + 1; 241 } else { 242 return size(x.left); 243 } 244 } 245 246 public void deleteMin() { 247 root = deleteMin(root); 248 } 249 250 private Node deleteMin(Node x) { 251 if (x.left == null) { 252 return x.right; 253 } 254 x.left = deleteMin(x.left); 255 x.N = size(x.left) + size(x.right) + 1; 256 return x;// 在刪除結束後返回節點的相關資訊 257 } 258 259 public void delete(Key key) { 260 root = delete(root, key); 261 } 262 263 private Node delete(Node x, Key key) { 264 if (x == null) { 265 return null; 266 } 267 int cmp = key.compareTo(x.key); 268 if (cmp > 0) { 269 x.right = delete(x.right, key); 270 } else if (cmp < 0) { 271 x.left = delete(x.left, key); 272 } else {// 找到key 273 if (x.right == null) {// 無右子樹 將左子樹接上 274 return x.left; 275 } 276 if (x.left == null) { 277 return x.right; 278 } 279 Node t = x; 280 // ********************************************** 281 x = min(t.right); // *被刪除節點有左右子樹,用右子樹中的最小節點代替它 282 x.left = t.left; // *替換後,左子樹保持不變 283 x.right = deleteMin(t.right); // *右子樹刪除最小節點後再接入 284 // ********************************************** 285 } 286 x.N = size(x.left) + size(x.right) + 1;// 更新新節點和上一個節點的n 287 return x;// 不一定會用到 288 } 289 290 private void print(Node x) {//x為樹的根節點 291 if(x==null) { 292 return; 293 } 294 print(x.left); 295 System.out.println(x.key); 296 print(x.right);; 297 } 298 299 public Iterable<Key> keys() {// 返回查詢二叉樹中的所有鍵 300 return keys(min(), max()); 301 } 302 303 public Iterable<Key> keysTwo() {// 範圍查詢非遞迴方法 304 Stack<Node> stack = new Stack(); 305 Queue<Key> queue = new Queue<Key>(); 306 Node x = root; 307 while (x != null || !stack.isEmpty()) {// 中序遍歷非遞減 308 if (x != null) { 309 stack.add(x); 310 x = x.left; 311 } else { 312 x = stack.pop(); 313 queue.enqueue(x.key); 314 x = x.right; 315 } 316 } 317 /* 318 * while(x!=null||stack.isEmpty()) {// 中序遍歷非遞增 if(x!=null) { stack.add(x); 319 * x=x.right; }else { x=stack.pop(); queue.enqueue(x.key); x=x.left; } } 320 */ 321 return queue;// 返回非降序佇列 322 } 323 324 public Iterable<Key> keysThree(int i) {// 範圍查詢非遞迴方法(包含前中序遍歷) 325 Stack<Node> stack = new Stack(); 326 Queue<Key> queue1 = new Queue<Key>();// 儲存前序遍歷 327 Queue<Key> queue2 = new Queue<Key>();// 儲存中序遍歷 328 Node x = root; 329 while (x != null || !stack.isEmpty()) { 330 for (; x != null; x = x.left) { 331 stack.add(x); 332 queue1.enqueue(x.key);// 前序遍歷 333 } 334 for (; x == null && !stack.isEmpty(); x = x.right) { 335 x = stack.pop(); 336 queue2.enqueue(x.key);// 中序遍歷 337 } 338 } 339 if (i == 1) { 340 return queue1; 341 } 342 return queue2; 343 } 344 345 public Iterable<Key> keysFour() {// 範圍查詢非遞迴方法(後序遍歷) 346 Stack<Node> stackA = new Stack(); 347 Stack<Node> stackB = new Stack(); 348 Queue<Key> queue = new Queue<Key>();// 儲存後序遍歷 349 Node x = root; 350 while (x != null || !stackB.isEmpty()) { 351 for (; x != null; x = x.right) { 352 stackA.add(x); 353 stackB.add(x); 354 } 355 for (; x == null && !stackB.isEmpty(); x = x.left) { 356 x = stackB.pop(); 357 } 358 } 359 360 while (!stackA.isEmpty()) { 361 queue.enqueue(stackA.pop().key); 362 } 363 return queue; 364 } 365 366 public Iterable<Key> keys(Key lo, Key hi) {// 二叉樹的範圍查詢操作 367 Queue<Key> queue = new Queue<Key>(); 368 keys(root, queue, lo, hi); 369 return queue; 370 } 371 372 private void keys(Node x, Queue<Key> queue, Key lo, Key hi) { 373 if (x == null) { 374 return; 375 } 376 int cmplo = lo.compareTo(x.key); 377 int cmphi = hi.compareTo(x.key); 378 // 三個if類似於中序遍歷 379 if (cmplo < 0) { 380 keys(x.left, queue, lo, hi); 381 } 382 if (cmplo <= 0 && cmphi >= 0) { 383 queue.enqueue(x.key); 384 } 385 if (cmphi > 0) { 386 keys(x.right, queue, lo, hi); 387 } 388 } 389 390 public static void main(String[] args) { 391 BST<Integer, String> bst = new BST<Integer, String>(); 392 bst.put(5, "one"); 393 bst.put(4, "two"); 394 bst.put(2, "one"); 395 bst.put(6, "two"); 396 bst.put(3, "one"); 397 for (Integer x : bst.keysFour()) {// 中序遍歷 398 System.out.println(x + " " + bst.get(x)); 399 } 400 // bst.delete(2); 401 } 402 }