二分检索树的左子树比根小,右子树比根大。这里用二分检索树实现了一个符号表,包括常用的api。
package symbolForm;
import simpleStructure.Queue;
public class BST<K extends Comparable<K>, V> implements SymbolForm<K, V>
{
private Node root;
private class Node
{
public K key;
public V value;
public int num; // 以该节点为根的树的节点总数
public Node left, right;
public Node(K key, V value, int N)
{
this.key = key;
this.value = value;
this.num = N;
}
public Node(Node n)
{
this.key = n.key;
this.value = n.value;
this.num = n.num;
this.left = n.left;
this.right = n.right;
}
}
@Override
public void put(K key, V value)
{
root = put(root, key, value);
}
private Node put(Node root, K key, V value)
{
if (root == null)
return new Node(key, value, 1);
int cmp = key.compareTo(root.key);
if (cmp < 0)
root.left = put(root.left, key, value);
else if (cmp > 0)
root.right = put(root.right, key, value);
else
root.value = value;
root.num = size(root.left) + size(root.right) + 1;
return root;
}
@Override
public V get(K key)
{
// TODO Auto-generated method stub
Node x = get(root, key);
if(x == null) return null;
return x.value;
}
private Node get(Node root, K key)
{
if (root == null)
return null;
int cmp = root.key.compareTo(key);
if (cmp > 0)
return get(root.left, key);
if (cmp < 0)
return get(root.right, key);
return root;
}
@Override
public boolean contain(K key)
{
// TODO Auto-generated method stub
return get(key) != null;
}
@Override
public boolean isEmpty()
{
// TODO Auto-generated method stub
return size() == 0;
}
@Override
public int size()
{
// TODO Auto-generated method stub
return size(root);
}
private int size(Node n)
{
if (n == null)
return 0;
return n.num;
}
@Override
public K min()
{
// TODO Auto-generated method stub
if (root == null)
return null;
Node r = new Node(root);
while (r.left != null)
{
r = r.left;
}
return r.key;
}
@Override
public K max()
{
// TODO Auto-generated method stub
if (root == null)
return null;
Node r = new Node(root);
while (r.right != null)
{
r = r.right;
}
return r.key;
}
@Override
public K floor(K key)
{
// TODO Auto-generated method stub
Node x = floor(root, key);
if (x == null)
return null;
return x.key;
}
/**
* 逻辑:如果给定的键key小于二叉查找树的根节点的键, 那么小于等于key的最大键floor(key)一定在根节点的左子树中,
* 如果给定的键key大于二叉查找数的根节点,那么只有当根节点右子树 中存在小于等于key的节点时,floor(key)才会出现在右子树中
* 否则根节点就是floor(key)
*
* @param n
* @param key
* @return
*/
private Node floor(Node n, K key)
{
if (n == null)
return null;
int cmp = key.compareTo(n.key);
if (cmp < 0)
return floor(n.left, key);
else if (cmp > 0)
{
Node t = floor(n.right, key);
if (t == null)
return n;
else
return t;
} else
return n;
}
@Override
public K ceiling(K key)
{
// TODO Auto-generated method stub
Node x = ceiling(root, key);
if (x == null)
return null;
return x.key;
}
private Node ceiling(Node n, K key)
{
if (n == null)
return null;
int cmp = key.compareTo(n.key);
if (cmp > 0)
return ceiling(n.right, key);
if (cmp == 0)
return n;
Node t = ceiling(n.left, key);
if (t == null)
return n;
else
return t;
}
@Override
public int rank(K key)
{
// TODO Auto-generated method stub
return rank(root, key);
}
private int rank(Node n, K key)
{
if (n == null)
return 0;
int cmp = key.compareTo(n.key);
if (cmp == 0)
return size(n.left);
if (cmp < 0)
return rank(n.left, key);
return size(n.left) + 1 + rank(n.right, key);
}
@Override
public K select(int k)
{
// TODO Auto-generated method stub
Node x = select(root, k);
return x.key;
}
private Node select(Node n, int k)
{
int t;
if (n.left != null)
t = n.left.num;
else
t = 0;
if (t == k)
return n;
if (t > k)
return select(n.left, k);
return select(n.right, k - t - 1);
}
@Override
public void deleteMin()
{
// TODO Auto-generated method stub
root = deleteMin(root);
}
private Node deleteMin(Node n)
{
if (n.left == null)
return n.right;
n.left = deleteMin(n.left);
n.num = size(n.left) + size(n.right) + 1;
return n;
}
@Override
public void deleteMax()
{
// TODO Auto-generated method stub
root = deleteMax(root);
}
private Node deleteMax(Node n)
{
if (n.right == null)
return n.left;
n.right = deleteMax(n.right);
n.num = size(n.left) + size(n.right) + 1;
return n;
}
@Override
public void delete(K key)
{
// TODO Auto-generated method stub
root = delete(root, key);
}
private Node delete(Node n, K key)
{
if (n == null)
return null;
int cmp = key.compareTo(n.key);
if (cmp < 0)
n.left = delete(n.left, key);
else if (cmp > 0)
n.right = delete(n.right, key);
else
{
Node t = n;
n = min(t.right);
if (n != null)
{
n.right = deleteMin(t);
n.left = t.left;
}
}
if (n != null)
n.num = size(n.left) + size(n.right) + 1;
return n;
}
/**
* 心得,要写好一个递归,先准确理解当前函数的用途,含义. 因为要在当前函数中再使用这个函数
* @param n
* @return
*/
private Node min(Node n)
{
if (n == null)
return null;
if (n.left == null)
return n;
return min(n.left);
}
@Override
public int size(K lo, K hi)
{
// TODO Auto-generated method stub
return size(root, lo, hi);
}
// 这是我写过的最牛叉的递归算法了
private int size(Node n, K lo, K hi)
{
if (n == null)
return 0;
int sum = 0;
int cmplo = lo.compareTo(n.key);
int cmphi = hi.compareTo(n.key);
if (cmplo < 0)
sum += size(n.left, lo, hi);
if (cmplo <= 0 && cmphi >= 0)
sum += 1;
if (cmphi >= 0)
sum += size(n.right, lo, hi);
return sum;
}
@Override
public Iterable<K> keys()
{
// TODO Auto-generated method stub
return keys(min(), max());
}
@Override
public Iterable<K> keys(K lo, K hi)
{
// TODO Auto-generated method stub
Queue<K> queue = new Queue<K>();
keys(root, lo, hi, queue);
return queue;
}
// 这是我目前见过最牛叉的递归算法了。。。
private void keys(Node n, K lo, K hi, Queue<K> queue)
{
if (n == null)
return;
int cmp1 = lo.compareTo(n.key);
int cmp2 = hi.compareTo(n.key);
if (cmp1 < 0)
keys(n.left, lo, hi, queue);
if (cmp1 <= 0 && cmp2 >= 0)
queue.enqueue(n.key);
if (cmp2 > 0)
keys(n.right, lo, hi, queue);
}
}