文章首發於此,BST是後面自平衡二叉樹AVL樹,B樹等數據結構的基礎,所以理解BST的基本性質和操作很有必要,如果讀者對BST不是很瞭解可以查下wiki或者是參考嚴蔚敏的《數據結構與算法》或者《算法導論》,對於該數據結構有較詳細解釋,下面是我查詢資料實現的Java版本。
package com.mars.search; public class BinarySeachTree { private Node mRoot; private Node getRoot() { return mRoot; } public int search(Node root, int key) { if (root == null) { return 0xffffffff; } if (key < root.key) { return search(root.leftNode, key); } if (key > root.key) { return search(root.rightNode, key); } else { return key; } } public void insert(int data) { if (mRoot == null) { mRoot = new Node(data, null, null); // mRoot.key = data; } Node root = mRoot; while (root != null) { if (data == root.key) { return; } else if (data < root.key) { if (root.leftNode == null) { root.leftNode = new Node(data, null, null); return; } else { root = root.leftNode; } } else { if (root.rightNode == null) { root.rightNode = new Node(data, null, null); return; } else { root = root.rightNode; } } } } /* * http://courses.csail.mit.edu/6.006/spring11/rec/rec03.pdf Description: * Remove the node x from the binary search tree, making the necessary * adjustments to the binary search tree to maintain its properties. (Note * that this operation removes a specified node from the tree. If you wanted * to delete a key k from the tree, you would have to first call find(k) to * find the node with key k and then call delete to remove that node) Case 1: * x has no children. Just delete it (i.e. change parent node so that it * doesn’t point to x) Case 2: x has one child. Splice out x by linking x’s * parent to x’s child Case 3: x has two children. Splice out x’s successor * and replace x with x’s successor * * BST刪除分析可以看這裏 http://webdocs.cs.ualberta.ca/~holte/T26/del-from-bst.html */ public boolean delete(int key) { Node root = deleteNode(this.mRoot, key); if (root != null) { return true; } return false; } /** * * 刪除有左右子樹節點的時候其實等價於:1將右子樹的最左葉子節點的值覆蓋要刪除節點的值, * 然後刪除右子樹最左葉子節點。 遞歸的過程中找到刪除節點然後將右子樹的最左子葉子節點的 * 值賦給刪除節點,然後刪除右子樹的最左葉子節點。這步在遞歸退出的時候就做了,如果想不 * 通可以細細的看下第一個if語句 * * */ private Node deleteNode(Node root, int key) { if (key < root.key) { if (root.leftNode != null) { root.leftNode = deleteNode(root.leftNode, key); } else { return null; } } else if (key > root.key) { if (root.rightNode != null) { root.rightNode = deleteNode(root.rightNode, key); } else { return null; } } else { if (root.leftNode == null) { root = root.rightNode; } else if (root.rightNode == null) { root = root.leftNode; } else { Node newRoot = findMin(root); root.key = newRoot.key; // 此步遞歸調用相當於把右子樹的最左子樹的左葉子給刪了,因爲遞歸退出的時候leftNode = null; //如果Node的結構裏有指向parent的引用,刪除會方便些 root.rightNode = deleteNode(root.rightNode, root.key); } } return root; } // 左子樹的最右葉子節點 private Node findMin(Node root) { Node newRoot = root.rightNode; while (newRoot.leftNode != null) { newRoot = newRoot.leftNode; } return newRoot; } public void travel(Node root) { Node node = root; if (node == null) { return; } travel(node.leftNode); System.out.print(node.key + " "); travel(node.rightNode); } public static class Node { int key; Node leftNode; Node rightNode; Node(int key, Node left, Node right) { this.key = key; this.leftNode = left; this.rightNode = right; } } public static void main(String[] args) { BinarySeachTree bst = new BinarySeachTree(); int[] a = { 0, 4, 3, 2, 5, 1, 7, 6, 8, 9 }; for (int i : a) { bst.insert(i); } bst.travel(bst.getRoot()); int i = bst.search(bst.getRoot(), 3); System.out.println("\nsearch :" + i); System.out.println("after delete:"); bst.delete(4); bst.travel(bst.getRoot()); } }
參考資料http://en.wikipedia.org/wiki/Binary_search_tree
數據結構與算法