二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树。二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
如下图所示:
1、查询二叉查找树
查找30的查找顺序为50-20-30
2、二叉查找树插入
首先执行查找算法,找出被插结点的父亲结点。判断被插结点是其父亲结点的左、右儿子。将被插结点作为叶子结点插入。若二叉树为空。则首先单独生成根结点。
注意:新插入的结点总是叶子结点。
3、二叉查找树删除
删除分为三种情况
1)删除的节点为叶子节点:直接删除即可
2)删除的节点只有左子树或者只有右子树:将节点的子树上移一层即可
3)删除的节点既有右子树也有左子树:找到需要删除的结点p的直接前驱(或直接后继)s,用s来替换结点p,然后再删除此结点s
注意:这里的前驱和后继是指中序遍历时的顺序。
Java代码
public class IntBinaryTree {
private static final boolean CHECK_INVARIANT = true;
private Node root;
private int size;
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
private Node minimumNode(Node node) {
assert node != null;
while (node.left != null) {
node = node.left;
}
return node;
}
public int minimum() {
if (size == 0) throw new IllegalStateException("no data");
return minimumNode(root).data;
}
private Node maximumNode(Node node) {
assert node != null;
while (node.right != null) {
node = node.right;
}
return node;
}
public int maximum() {
if (size == 0) throw new IllegalStateException("no data");
return maximumNode(root).data;
}
private Node successorNode(Node node) {
assert node != null;
if (node.right != null) {
return minimumNode(node.right);
} else {
Node parent = node.parent;
while (parent != null && parent.right == node) {
node = parent;
parent = node.parent;
}
return parent;
}
}
public IntIterator ascendingIterator() {
return new IntIterator() {
private Node next = root == null ? null : minimumNode(root);
public boolean hasNext() {
return next != null;
}
public int next() {
if (next == null) throw new NoSuchElementException();
int result = next.data;
next = successorNode(next);
return result;
}
};
}
private Node predecessorNode(Node node) {
assert node != null;
if (node.left != null) {
return maximumNode(node.left);
} else {
Node parent = node.parent;
while (parent != null && parent.left == node) {
node = parent;
parent = node.parent;
}
return parent;
}
}
public IntIterator desendingIterator() {
return new IntIterator() {
private Node next = root == null ? null : maximumNode(root);
public boolean hasNext() {
return next != null;
}
public int next() {
if (next == null) throw new NoSuchElementException();
int result = next.data;
next = predecessorNode(next);
return result;
}
};
}
Node searchNode(int d) {
return searchNode(root, d);
}
private Node searchNode(Node node, int d) {
while (node != null && node.data != d) {
if (d < node.data) node = node.left;
else node = node.right;
}
return node;
}
public void insert(int d) {
Node prev = null;
Node cur = root;
while (cur != null) {
prev = cur;
if (d < cur.data) {
cur = cur.left;
} else {
cur = cur.right;
}
}
if (prev == null) {
root = new Node(d);
} else {
Node newNode = new Node(d, prev);
if (d < prev.data) {
prev.left = newNode;
} else {
prev.right = newNode;
}
}
size++;
if (CHECK_INVARIANT) checkInvarient();
}
public boolean delete(int d) {
Node node = searchNode(d);
if (node != null) {
delete(node);
if (CHECK_INVARIANT) checkInvarient();
return true;
} else {
return false;
}
}
private void delete(Node node) {
assert node != null;
Node d; // d为要删除的结点
if (node.left == null || node.right == null) {
d = node;
} else {
d = successorNode(node);
}
Node c = d.left != null ? d.left : d.right; // c为要链接到的子结点
if (c != null) c.parent = d.parent;
if (d.parent == null) {
root = c;
} else {
if (d.parent.left == d) {
d.parent.left = c;
} else {
d.parent.right = c;
}
}
if (d != node) {
node.data = d.data;
}
size--;
}
private void checkInvarient() {
IdentityHashMap<Node, Node> set = new IdentityHashMap<Node, Node>();
checkLeftRightParentPointer(root, set);
if (set.size() != size) {
throw new IllegalStateException(String.format("actual size(%d) is not the expected size(%d)", set.size(), size));
}
}
/**
* 检查left, right, parent指针之间的引用关系是否正确。
*/
private void checkLeftRightParentPointer(Node node, IdentityHashMap<Node, Node> set) {
if (node == null) return;
if (set.containsKey(node)) {
throw new IllegalStateException("circular reference detected!");
}
set.put(node, node);
Node l = node.left; Node r = node.right;
if (l != null) {
if (l.parent != node) {
throw new IllegalStateException("left-parent relation violated");
}
if (l.data > node.data) {
throw new IllegalStateException(String.format("left node(%s) > parent node(%s)", l, node));
}
}
if (r != null) {
if (r.parent != node) {
throw new IllegalStateException("right-parent relation violated");
}
if (r.data < node.data) {
throw new IllegalStateException(String.format("right node(%s) < parent node(%s)", r, node));
}
}
checkLeftRightParentPointer(node.left, set);
checkLeftRightParentPointer(node.right, set);
}
public String toString() {
if (root == null) return "[empty]";
StringBuilder sb = new StringBuilder();
Node node = minimumNode(root);
while (node != null) {
sb.append(String.format("%d: %s %s %s%n", node.data,
node.left == null ? "-" : node.left.data,
node.right == null ? "-" : node.right.data,
node.parent == null ? "-" : node.parent.data));
node = successorNode(node);
}
return sb.toString();
}
private static class Node {
private int data;
private Node left;
private Node right;
private Node parent;
public Node(int d) { data = d; }
public Node(int d, Node p) { data = d; parent = p; }
public Node(int d, Node p, Node l, Node r) {
data = d; parent = p; left = l; right = r;
}
public String toString() { return Integer.toString(data); }
}
public static void main(String[] args) {
IntBinaryTree btree = new IntBinaryTree();
int[] data = new int[] { 8, 9, 6, 5, 13, 7};
for (int i = 0; i < data.length; i++) {
btree.insert(data[i]);
}
System.out.println("tree: " + btree);
System.out.println("minimum: " + btree.minimum());
System.out.println("maximum: " + btree.maximum());
System.out.println("ascendingIterator");
for (IntIterator itor = btree.ascendingIterator(); itor.hasNext();) {
System.out.println(itor.next());
}
System.out.println("desendingIterator");
for (IntIterator itor = btree.desendingIterator(); itor.hasNext();) {
System.out.println(itor.next());
}
btree.delete(6);
System.out.println("ascendingIterator");
for (IntIterator itor = btree.ascendingIterator(); itor.hasNext();) {
System.out.println(itor.next());
}
btree = new IntBinaryTree();
Random random = new Random();
for (int i = 0; i < 100; i++) {
btree.insert(random.nextInt(200));
}
for (int i = 0; i < 200; i++) {
btree.delete(random.nextInt(200));
}
}
}