二叉查找树(Binary Search Tree),或者是一棵空树,或者是具有下列性质的二叉树:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于或者等于它的根结点的值;
- 它的左、右子树也分别为二叉排序树。
二叉查找树的表示:
class Node {
int data;
Node leftChild = null;
Node rightChild = null;
}
二叉查找树的常用方法:
1. 查找(lookup)
/*
Given a binary tree, return true if a node with the target data is found in the tree. Recurs down the tree, chooses the left or right branch by comparing the target to each node.
*/
static boolean lookup(Node rootNode, int target) {
// 1. Base case == empty tree
// in that case, the target is not found so return false
if (rootNode == null) return false;
else if (target == rootNode.data) return true;
else if (target < rootNode.data) return(lookup(rootNode.leftChild, target));
else return(lookup(rootNode.rightChild, target));
}
2. 最大(max)
/*
return the node with maximum key value. It should be last right child of the tree, or the root if the root does not have any child
*/
public Node maxNode(Node rootNode) {
while (rootNode.righttChild != null) {
rootNode = rootNode.rightChild;
}
return rootNode;
}
3. 最小 (min)
/*
return the node with minimum key value. It should be last left child of the tree, or the root if the root does not have any child
*/
public Node minNode(Node rootNode) {
while (rootNode.leftChild != null) {
rootNode = rootNode.leftChild;
}
return rootNode;
}
public static Node insert(Node root, int data) {
// 1. If the tree is empty, the new node is the root
if (root == null) {
return new Node(data);
}else {
// 2. Otherwise, recur down the tree
if (data <= root.data) root.leftChild = insert(root.leftChild, data);
else root.rightChild = insert(root.rightChild, data);
}
return root;
}
5. in-order tree walk
public void inorder(Node rootNode) {
if (rootNode != null) {
inorder(rootNode.leftChild);
print(nodeNode.data);
inorder(rootNode.rightChild);
}
}
6. successor and predecessor
一个node的successor可以通过in-order walk看出来,因为in-order walk实际上是把二叉查找树做了一个排序。 predecesor 刚好和successor 相反。
Search consists of two cases.
1) If node x has a non-empty right subtree, then x’s successor is the minimum in the right subtree of x.
2) If node x has an empty right subtree, then as long as we move to the left up the tree (move up through right children), we are visiting smaller keys. x’s successor y is the node that x is the predecessor of (x is the maximum in y’s left subtree). In other words, x’s successor y, is the lowest ancestor of x whose left child is also an ancestor of x.
public Node Successor(Node node) {
if (node.rightChild != null) {
return minNode(node.rightChild);
}
Node parentNode = node.parent;
while (parentNode != null && node == parentNode.rightChild) {
node = parentNode;
parentNode = parentNode.parent;
}
return parentNode;
}
If node has two children, its predecessor is the maximum value in its left subtree. If it does not have a left child a node's predecessor is its first left ancestor.
7. 删除 (delete)
case 1: if x has no children, then remove x;
case 2: if x has one child, then make p[x] point to child;
case 3: if x has two children (subtrees) , then swap x with its successor, perform case 0 or case 1 to delete it.
伪代码:
delete(x)
if x.left = NIL and x.right = NIL //case 1
if x.parent.left = x
x.parent.left = NIL
else
x.parent.right = NIL
else if x.left = NIL //case 2a
connect x.parent to x.right
else if x.right = NIL //case 2b
connect x.parent to x.left
else //case 3
y = successor(x)
connect y.parent to y.right
replace x with y
/*
Compute the number of nodes in a tree.
*/
int size(Node rootNode) {
if (node == NULL) {
return(0);
} else {
return(size(rootNode.leftChild) + 1 + size(rootNode.rightChild));
}
}