二叉查找树
原帖地址 http://www.iteye.com/topic/561590
1 import java.util.Collection; 2 import java.util.Iterator; 3 import java.util.NoSuchElementException; 4 5 public class BinarySearchTree<E extends Comparable<E>> 6 { 7 8 public static void main(String[] args) 9 { 10 BinarySearchTree<Integer> bst = new BinarySearchTree<Integer>(); 11 bst.add(50); 12 bst.add(37); 13 bst.add(75); 14 bst.add(25); 15 bst.add(61); 16 bst.add(15); 17 bst.add(30); 18 bst.add(55); 19 bst.add(68); 20 bst.add(28); 21 bst.add(32); 22 bst.add(59); 23 bst.add(36); 24 bst.add(36); 25 26 //是否包含 27 System.out.println(bst.contains(36));//true 28 System.out.println(bst.contains(38));//false 29 30 //大小 31 System.out.println(bst.size());//13 32 33 //遍历 34 Iterator<Integer> itr = bst.iterator(); 35 while (itr.hasNext()) { 36 //15 25 28 30 32 36 37 50 55 59 61 68 75 37 System.out.print(itr.next() + " "); 38 } 39 System.out.println(); 40 41 42 //删除根叶子节点36 43 bst.remove(36); 44 System.out.println(bst.size());//12 45 itr = bst.iterator(); 46 while (itr.hasNext()) { 47 //15 25 28 30 32 37 50 55 59 61 68 75 48 System.out.print(itr.next() + " "); 49 } 50 System.out.println(); 51 52 //删除只有一个左子节点的节点37 53 bst.remove(37); 54 System.out.println(bst.size());//11 55 itr = bst.iterator(); 56 while (itr.hasNext()) { 57 //15 25 28 30 32 50 55 59 61 68 75 58 System.out.print(itr.next() + " "); 59 } 60 System.out.println(); 61 62 //删除只有一个右子节点的节点55 63 bst.remove(55); 64 System.out.println(bst.size());//10 65 itr = bst.iterator(); 66 while (itr.hasNext()) { 67 //15 25 28 30 32 50 59 61 68 75 68 System.out.print(itr.next() + " "); 69 } 70 System.out.println(); 71 72 //删除有左右子节点的根节点50 73 bst.remove(50); 74 System.out.println(bst.size());//9 75 itr = bst.iterator(); 76 while (itr.hasNext()) { 77 //15 25 28 30 32 59 61 68 75 78 System.out.print(itr.next() + " "); 79 } 80 System.out.println(); 81 82 //下面通过迭代器删除节点根节点59 83 itr = bst.iterator(); 84 while (itr.hasNext()) { 85 if (itr.next() == 59) { 86 itr.remove();//删除最近一次next返回的节点 87 break; 88 } 89 } 90 91 while (itr.hasNext()) { 92 //61 68 75 93 System.out.print(itr.next() + " "); 94 itr.remove(); 95 } 96 97 System.out.println(); 98 System.out.println(bst.size());//5 99 } 100 101 102 private Node root; 103 104 private int size; 105 106 107 public BinarySearchTree() 108 { 109 root = null; 110 } 111 112 113 /* 114 * 二叉树插入操作,如果插入节点大于 115 */ 116 public boolean add(E e) 117 { 118 Node<E> x = root, y = null; 119 int compare = 0; 120 121 while (x != null) { 122 // y为每次循环x的父节点 123 y = x; 124 compare = e.compareTo(x.value); 125 126 /* 127 * 插入节点于当前结点相同则直接返回False 128 * 如果插入节点e如比当前节点x小则将当前节点e指向当前节点的左节点e.left 129 * 否则则将当前节点e指向当前结点右节点e.right 130 */ 131 if (compare == 0) return false; 132 133 if (compare == 1) 134 x = x.right; 135 else 136 x = x.left; 137 } 138 139 if (y == null) { 140 // y为空则表示root为空 141 root = new Node(e, null); 142 } 143 else { 144 // 根据之前判断创建新节点并指定为父节点y的左子节点或右子节点 145 if (compare == 1) 146 y.right = new Node(e, y); 147 else 148 y.left = new Node(e, y); 149 } 150 size++; 151 return true; 152 } 153 154 155 public boolean contains(E e) 156 { 157 return getNode(e) != null; 158 } 159 160 161 private Node<E> getNode(E e) 162 { 163 Node<E> node = root; 164 int compare; 165 166 while (node != null) { 167 compare = e.compareTo(node.value); 168 169 if (compare == 0) return node; 170 if (compare == 1) 171 node = node.right; 172 else 173 node = node.left; 174 } 175 176 return null; 177 } 178 179 180 public boolean remove(E e) 181 { 182 // 如果为空则直接返回 183 Node<E> node = getNode(e); 184 if (node == null) return false; 185 removeNode(node); 186 return true; 187 } 188 189 190 /* 191 * 如果删除节点n是叶子节点,则直接删除该节点 192 * 如果删除节点只有一个子节点,则将n的子节点与n的父节点直接连接,然后删除节点n 193 * 如果删除节点n有两个子节点,则使用中序立遍历方式得到直接前置节点c或直接后继节点c得知代替节点n的值,然后删除c 194 */ 195 private void removeNode(Node<E> node) 196 { 197 // 有两个子节点 198 if (node.left != null && node.right != null) { 199 Node<E> child = intervalNode(node); 200 node.value = child.value; 201 node = child; 202 } 203 204 // 没有子节点,自身为叶子节点 205 if (node.left == null && node.right == null) { 206 // 207 if (node.parent == null) { 208 root = null; 209 } 210 else { 211 if (node == node.parent.left) 212 node.parent.left = null; 213 else 214 node.parent.right = null; 215 } 216 } 217 else { 218 // 只有一个节点的情况 219 Node<E> replace; 220 221 replace = node.left != null ? node.left : node.right; 222 223 replace.parent = node.parent; 224 225 if (node.parent == null) { 226 root = replace; 227 } 228 else if (node == node.parent.left) { 229 node.parent.left = replace; 230 } 231 else { 232 node.parent.right = replace; 233 } 234 } 235 node.parent = null; 236 node.left = node.right = null; 237 size--; 238 } 239 240 241 /* 242 * 查找中序遍历的直接后继节点 243 * 244 * 如果待查找的节点有右子树,则后继节点一定在右子树上,此时右子树上的某个节点可能成为后 245 * 继节点:一是如果待查节点的右子树没有左子树(有没有右子树无所谓)时,直接就返回该待查节点 246 * 的右子节点;二是如果待点节点的右子节点有左子树,则查找右子节点的最左边的左子树节点(注, 247 * 该节点一点是左叶子节点或只有一个右子节点的左节点,查找过程要一直向左,即遍历时只向左拐, 248 * 不可向右) 249 * 250 * 如果待查找的节点没有右子树,则需要从该节点向根的方向遍历(不可向左或右拐),后继节点只 251 * 可能在祖宗节点中产生(包括父节点与根节点在内),此情况分两种:一种就是待查节点为某节点的左 252 * 子树,则此时的后继为父节点;第二种就是当待查节点为某个节点的右子树时,则需沿根的方向向上找, 253 * 一直找到第一个有左子树的祖宗节点即为后继节点,或到根为止还没有找到(则该节点只可能为中序遍 254 * 历的最后节点 255 */ 256 private Node intervalNode(Node node) 257 { 258 if (node == null) { 259 return null; 260 } 261 else if (node.right != null) { 262 /* 263 * 查找50节点的直接后继,查找结果为55 264 * 50 265 * \ 266 * 75 267 * / 268 * 61 269 * /\ 270 * 55 68 271 * \ 272 * 59 273 */ 274 275 Node<E> child = node.right; 276 while (child.left != null) { 277 child = child.left; 278 } 279 return child; 280 } 281 else { 282 /* 283 * 没有右子树的节点且为父节点的右子节点36的直接后继为37,同样节点68的直接后继为75 284 * 没有右子树的节点且为父节点的左子节点37的直接后继为50,同样节点28的直接后继为30 285 * 75为最后节点,所以直接后继为null 286 * 287 * 50 288 * /\ 289 * 37 75 290 * / / 291 * 25 61 292 * /\ /\ 293 * 15 30 55 68 294 * /\ \ 295 * 28 32 59 296 * \ 297 * 36 298 * / 299 * 35 300 */ 301 302 Node<E> parent = node.parent; 303 Node<E> current = node; 304 305 while (parent != null && current == parent.right) { 306 current = parent; 307 parent = parent.parent; 308 } 309 return parent; 310 } 311 } 312 313 314 public int size() 315 { 316 return size; 317 } 318 319 320 public Iterator<E> iterator() 321 { 322 return new TreeIterator(); 323 } 324 325 326 public class TreeIterator implements Iterator<E> 327 { 328 private Node<E> lastReturned; 329 330 private Node<E> next; 331 332 private Node<E> endNode; 333 334 335 public TreeIterator() 336 { 337 next = root; 338 if (next != null) { 339 while (next.left != null) { 340 next = next.left; 341 } 342 } 343 } 344 345 public boolean hasPreVious() 346 { 347 return (next != null && intervalNode(next) != null) || endNode != null; 348 } 349 350 351 public E previous() 352 { 353 if (next != null && intervalNode(next) == null) { 354 throw new NoSuchElementException(); 355 } 356 357 if (endNode != null) { 358 lastReturned = next = endNode; 359 endNode = null; 360 } 361 else { 362 lastReturned = next = intervalNode(next); 363 } 364 return lastReturned.value; 365 } 366 367 public boolean hasNext() 368 { 369 return next != null; 370 } 371 372 public E next() 373 { 374 if (next == null) 375 throw new NoSuchElementException(); 376 377 lastReturned = next; 378 next = intervalNode(next); 379 380 if (next == null) { 381 endNode = lastReturned; 382 } 383 return lastReturned.value; 384 } 385 386 387 public void remove() 388 { 389 if (lastReturned == null) { 390 throw new IllegalStateException(); 391 } 392 393 if (lastReturned.left != null && lastReturned.right != null) { 394 next = lastReturned; 395 } 396 removeNode(lastReturned); 397 lastReturned = null; 398 } 399 400 } 401 402 403 public void preOrder(Collection<E> collect) 404 { 405 preOrder(root, collect); 406 } 407 408 409 private final void preOrder(Node<E> n, Collection<E> collect) 410 { 411 if (n != null) { 412 collect.add(n.value); 413 preOrder(n.left, collect); 414 preOrder(n.right, collect); 415 } 416 } 417 418 419 public void inOrder(Collection<E> collect) 420 { 421 inOrder(root, collect); 422 } 423 424 425 private void inOrder(Node<E> n, Collection<E> collect) 426 { 427 if (n == null) return; 428 inOrder(n.left, collect); 429 collect.add(n.value); 430 inOrder(n.right, collect); 431 } 432 433 434 public void postOrder(Collection<E> collect) 435 { 436 postOrder(root, collect); 437 } 438 439 440 private final void postOrder(Node<E> n, Collection<E> collect) 441 { 442 if (n == null) return; 443 postOrder(n.left, collect); 444 postOrder(n.right, collect); 445 collect.add(n.value); 446 } 447 448 449 private class Node<E> 450 { 451 private E value; 452 453 private Node parent; 454 455 private Node left; 456 457 private Node right; 458 459 public Node(E value, Node parent) 460 { 461 this.value = value; 462 this.parent = parent; 463 } 464 } 465 }