1.数据表示
我们嵌套定义一个私有Node类来表示二叉查找树上的一个结点。每个结点都含有一个键,一个值,一条左链接,一条右链接。左链接指向一棵由小于该结点的所有键组成的二叉查找树,右链接指向一棵由大于该结点的所有键组成的二叉查找树。变量N给出以该结点为根的子树的结点总数。这样有
size(x) = size(x.left) + size(x.right) + 1
2.查找
在符号表中查找一个键有两种结果:命中和未命中。在二叉查找树中查找一个键:
-- 如果树为空,查找未命中
--如果查找的键与根节点的键相等,返回根节点的值
--如果查找的键比根节点的键大,则查找根节点的右子树
--否则,查找根节点的左子树
//根据键找对应的值,如果找不到返回Null
public Value get(Key key) {
return get(root,key);
}
private Value get(Node x, Key key) {
while (x != null) {
int cmp = key.compareTo(x.key);
if (cmp > 0) x = x.right;
else if (cmp < 0) x = x.left;
else return x.val;
}
return null;
}
3.插入
插入的逻辑:
--如果树为空,创建对于键值对的新结点
--如果插入的键小于根结点的键,继续向左子树中插入该键
--否则在右子树中插入该键
//向树中插入结点
public void put(Key key, Value val) {
root = put(root, key, val);
}
private Node put(Node x, Key key, Value val) {
if (x == null) return new Node(key, val, 1);
int cmp = key.compareTo(x.key);
if (cmp > 0) x.right = put(x.right, key, val);
else if (cmp < 0) x.left = put(x.left, key, val);
else x.val = val;
x.N = size(x.right) + size(x.left) + 1;
return x;
}
最小键
--如果根结点左子树为空,那么根结点为最小键
--如果左链接非空,那么最小键为左子树的最小键
//找到最小的键
public Key min() {
return min(root);
}
private Key min(Node x) {
if (x == null)return null;
while (x.left != null) {
x = x.left;
}
return x.key;
}
最大键与最小键类似,不再赘述。
5.删除操作
二叉查找树中对较难实现的方法就是delete()方法。我们先考虑deleteMin()方法。对于deleteMin(),我们要不断深入根结点的左子树
直至遇到一个空连接,然后将指向该结点的链接指向该结点的右子树。
public void deleteMin() {
root = deleteMin(root);
}
private Node deleteMin(Node x) {
if (x == null) return null;
if (x.left == null) return x.right;
x.left = deleteMin(x.left);
x.N = size(x.left) + size(x.right) + 1;
return x;
}
deleteMax()与此类似,不再赘述
接下来我们考虑delete()方法,我们用四个步骤完成将x替换为它的后继结点。
--将指向即将被删除的结点的链接保存为t
--将x指向他的后继结点min(t.right)
--将x的右链接指向deleteMin(t.right),也就是在删除后所有结点都大于x.key的子二叉查找树
--将x的左链接设为t.left
public void delete(Key key) {
root = delete(root,key);
}
private Node delete(Node x, Key key) {
if (x == null) return null;
int cmp = key.compareTo(x.key);
if (cmp < 0) x.left = delete(x.left, key);
else if (cmp > 0) x.right = delete(x.right, key);
else {
if (x.right == null) return x.left;
if (x.left == null) return x.right;
Node t = x;
x = min(t.right);
x.right = deleteMin(t.right);
x.left = t.left;
}
x.N = size(x.left) + size(x.right) + 1;
return x;
}
最后附上完整代码:
package com.tong.Test;
public class BST<Key extends Comparable<Key> , Value> {
private Node root;
private class Node {
private Key key;
private Value val;
private Node left, right;
private int N;
public Node(Key key, Value val, int n) {
this.key = key; this.val = val; this.N = n;
}
}
//返回二叉搜索树的结点数
public int size() {
return size(root);
}
private int size(Node x) {
if (x == null) return 0;
return x.N;
}
//根据键找对应的值,如果找不到返回Null
public Value get(Key key) {
return get(root,key);
}
private Value get(Node x, Key key) {
while (x != null) {
int cmp = key.compareTo(x.key);
if (cmp > 0) x = x.right;
else if (cmp < 0) x = x.left;
else return x.val;
}
return null;
}
//向树中插入结点
public void put(Key key, Value val) {
root = put(root, key, val);
}
private Node put(Node x, Key key, Value val) {
if (x == null) return new Node(key, val, 1);
int cmp = key.compareTo(x.key);
if (cmp > 0) x.right = put(x.right, key, val);
else if (cmp < 0) x.left = put(x.left, key, val);
else x.val = val;
x.N = size(x.right) + size(x.left) + 1;
return x;
}
//找到最小的键
public Key min() {
return min(root).key;
}
private Node min(Node x) {
if (x == null)return null;
while (x.left != null) {
x = x.left;
}
return x;
}
public void deleteMin() {
root = deleteMin(root);
}
private Node deleteMin(Node x) {
if (x == null) return null;
if (x.left == null) return x.right;
x.left = deleteMin(x.left);
x.N = size(x.left) + size(x.right) + 1;
return x;
}
public void delete(Key key) {
root = delete(root,key);
}
private Node delete(Node x, Key key) {
if (x == null) return null;
int cmp = key.compareTo(x.key);
if (cmp < 0) x.left = delete(x.left, key);
else if (cmp > 0) x.right = delete(x.right, key);
else {
if (x.right == null) return x.left;
if (x.left == null) return x.right;
Node t = x;
x = min(t.right);
x.right = deleteMin(t.right);
x.left = t.left;
}
x.N = size(x.left) + size(x.right) + 1;
return x;
}
public static void main(String[] args) {
BST<Integer, String> table = new BST<>();
table.put(3, "三");
table.put(2, "二");
table.put(1, "一");
table.put(4, "四");
table.put(6, "五");
System.out.println(table.get(5));
System.out.println(table.min());
}
}