/**
* Introduction to Algorithms, Second Edition
* 12 Binary Search Trees
* @author 土豆爸爸
*
*/
import java.util.ArrayList;
import java.util.List;
public class BinarySearchTree {
/**
* 数据节点
*/
public static class Node {
int key;
Node parent; //父节点
Node left; //左子节点
Node right; //右子节点
public Node(int key) {
this.key = key;
}
}
private Node root;
/**
* 采用递归法查找键值为k的节点。
* @param k 节点的键值
* @return 返回键值为k的节点
*/
public Node search(int k) {
return search(root, k);
}
/**
* 采用递归法查找键值为k的节点。
* @param x 当前节点
* @param k 节点的键值
* @return 返回键值为k的节点
*/
private Node search(Node x, int k) {
if(x == null || k == x.key) {
return x;
} else if(k < x.key) {
return search(x.left, k);
} else {
return search(x.right, k);
}
}
/**
* 采用迭代法查找键值为k的节点。
* @param x 当前节点
* @param k 节点的键值
* @return 返回键值为k的节点
*/
public Node iterativeSearch(int k) {
return iterativeSearch(root, k);
}
/**
* 采用迭代法查找键值为k的节点。
* @param x 当前节点
* @param k 节点的键值
* @return 返回键值为k的节点
*/
private Node iterativeSearch(Node x, int k) {
while(x != null && k != x.key) {
if(k < x.key) {
x = x.left;
} else {
x = x.right;
}
}
return x;
}
/**
* 返回树的最小键值的节点。
* @return 最小键值的节点
*/
public Node minimum() {
return minimum(root);
}
/**
* 返回树的最小键值的节点。
* @param x 当前节点
* @return 最小键值的节点
*/
private Node minimum(Node x) {
while(x.left != null) {
x = x.left;
}
return x;
}
/**
* 返回树的最大键值的节点。
* @return 最大键值的节点
*/
public Node maximum() {
return maximum(root);
}
/**
* 返回树的最大键值的节点。
* @param x 当前节点
* @return 最大键值的节点
*/
private Node maximum(Node x) {
while(x.right != null) {
x = x.right;
}
return x;
}
/**
* 返回指定节点x的后继节点。
* @param x 当前节点
* @return x的后继节点;如果x具有最大键值,返回null
*/
public Node successor(Node x) {
if(x.right != null) {
return minimum(x);
}
Node y = x.parent;
while(y != null && x == y.right) {
x = y;
y = y.parent;
}
return y;
}
/**
* 返回指定节点x的前驱节点。
* @param x 当前节点
* @return x的前驱节点;如果x具有最小键值,返回null
*/
public Node predecessor(Node x) {
if(x.left != null) {
return maximum(x);
}
Node y = x.parent;
while(y != null && x == y.left) {
x = y;
y = y.parent;
}
return y;
}
/**
* 插入节点。
* @param z 待插入节点
*/
public void insert(Node z) {
Node y = null; //当前节点的父节点
Node x = root; //当前节点
while(x != null) { //迭代查寻z应该所在的位置
y = x;
if(z.key < x.key) {
x = x.left;
} else {
x = x.right;
}
}
z.parent = y;
if(y == null) {
root = z; //如果没有父节点,则插入的节点是根节点。
} else if(z.key < y.key) {
y.left = z;
} else {
y.right = z;
}
}
/**
* 删除节点。
* @param z 待删除节点
*/
public Node delete(Node z) {
Node y = null;
Node x = null;
if (z.left == null || z.right == null) {
y = z;
} else {
y = successor(z);
}
if (y != null) {
x = y.left;
} else {
x = y.right;
}
if (x != null) {
x.parent = y.parent;
}
if (y.parent == null) {
root = x;
} else if (y == y.parent.left) {
y.parent.left = x;
} else {
y.parent.right = x;
}
if (y != z) { //如果z包含两个子节点,用y替换z的位置
y.parent = z.parent;
if (z == z.parent.left) {
z.parent.left = y;
} else {
z.parent.right = y;
}
y.left = z.left;
y.right = z.right;
}
return y;
}
/**
* 中序历遍。即从小到大排序。
* @return 返回已排序的节点列表
*/
public List<Node> inorderWalk() {
List<Node> list = new ArrayList<Node>();
inorderWalk(root, list);
return list;
}
/**
* 中序历遍。
* @param x 当前节点
* @param list 历遍结果存储在list中
*/
private void inorderWalk(Node x, List<Node> list) {
if(x != null) {
inorderWalk(x.left, list);
list.add(x);
inorderWalk(x.right, list);
}
}
}
import java.util.List;
import junit.framework.TestCase;
public class BinarySearchTreeTest extends TestCase {
public void testLinkedList() {
BinarySearchTree tree = new BinarySearchTree();
// 插入100个随机节点
for (int i = 0; i < 100; i++) {
int key = (int) (Math.random() * 1000);
if (tree.search(key) == null) {
tree.insert(new BinarySearchTree.Node(key));
}
}
verifyOrdered(tree.inorderWalk());
BinarySearchTree.Node node = null;
for (int i = 0; i < 1000; i++) {
node = tree.search(i);
if (node != null) {
break;
}
}
assertNotNull(node);
tree.delete(node);
assertEquals(null, tree.search(node.key));
verifyOrdered(tree.inorderWalk());
}
private boolean verifyOrdered(List<BinarySearchTree.Node> list) {
for (int i = 1; i < list.size(); i++) {
if (list.get(i - 1).key > list.get(i).key) {
return false;
}
}
return true;
}
}
comes from:http://blog.csdn.net/s3n/archive/2006/06/09/781443.aspx





