所有学习内容全部来自于《算法》第四版
简单概述
二叉查找树是符号表的一种实现。
符号表,又称为字典,或者索引之类的。主要目的就是讲一个键和一个值联系起来,能够通过键增删改查等操作。
符号表有二叉查找树、红黑树以及散列表的实现。基于这些算法,能够扩展出很多应该用。
符号表API定义
主要实现如下方法:
key的话需要继承于Comparable。
public interface SymbolTable<Key extends Comparable<Key>,Value> {
Value get(Key key);
void put(Key key,Value value);
void delete(Key key);
Key max();
Key min();
int size();
boolean isEmpty();
boolean contains(Key key);
/**
* 小于等于key的最大键,向下取整。
* @param key
* @return
*/
Key floor(Key key);
/**
* 大于等于key的最小键,向上取整。
* @param key
* @return
*/
Key ceiling(Key key);
/**
* 小于key的数量
* @param key
* @return
*/
int rank(Key key);
/**
* 排名为k的键,即树中刚好有k个小于它的键,
* 那么实际上排名应该是k+1
* @param k
* @return
*/
Key select(int k);
void deleteMax();
void deleteMin();
/**
* [lo,hi]之间的键的数量
* @param lo
* @param hi
* @return
*/
int size(Key lo,Key hi);
/**
* [lo,hi]之间的所有的键,已经排序。
* @param lo
* @param hi
* @return
*/
Iterable<Key> keys(Key lo,Key hi);
/**
* 表中所有键的集合,已经排序。
* @return
*/
Iterable<Key> keys();
}
抽象符号表
接口里面有一些方法的实现可以依赖于其它方法。子类不需要进一步实现,如下:
public abstract class AbstractSymbolTable<Key extends Comparable<Key>,Value> implements SymbolTable<Key,Value>{
public boolean contains(Key key) {
return null!=get(key);
}
public boolean isEmpty() {
return size()==0;
}
public Iterable<Key> keys() {
return keys(min(),max());
}
public int size(Key lo, Key hi) {
if (lo.compareTo(hi)>0)
return 0;
else if (contains(hi))
return rank(hi)-rank(lo)+1;
else
return rank(hi)-rank(lo);
}
}
二叉查找树的算法详解
二叉查找树的具体实现
所有的实现都用的递归,如下:
public class BST<Key extends Comparable<Key>,Value> extends AbstractSymbolTable<Key,Value>{
public static void main(String[] args) {
BST<Integer,Integer> bst=new BST<Integer,Integer>();
bst.put(1,3);
bst.put(2,2);
bst.put(3,1);
System.out.println(bst.toString());
System.out.println(bst.size());
System.out.println(bst.select(1));
System.out.println(bst.select(0));
}
private class Node{
private Key key;
private Value value;
private Node left,right;
private int n;
public Node(Key key, Value value, int n) {
this.key = key;
this.value = value;
this.n = n;
}
@Override
public String toString() {
return "(key:"+key+" value:"+value+") ";
}
}
private Node root;
@Override
public String toString() {
return toString(root);
}
private String toString(Node node){
if (node==null) return "";
return toString(node.left)+node.toString()+toString(node.right);
}
public int size(){
return size(root);
}
private int size(Node node){
if (node==null) return 0;
return size(node.left)+size(node.right)+1;
}
public Value get(Key key){
return get(root,key);
}
private Value get(Node node,Key key){
if (node==null) return null;
int temp=node.key.compareTo(key);
if (temp==0) return node.value;
else if (node.key.compareTo(key)<0) return get(node.right,key);
else return get(node.left,key);
}
public void put(Key key,Value value){
root=put(root,key,value);
}
private Node put(Node node,Key key,Value value){
if (node==null) return new Node(key,value,1);
int temp=key.compareTo(node.key);
if (temp==0) node.value=value;
else if (temp>0) node.right=put(node.right,key,value);
else node.left=put(node.left,key,value);
node.n=size(node.left)+size(node.right)+1;
return node;
}
public void delete(Key key){
root=delete(root,key);
}
public Node delete(Node node,Key key){
if (node==null) return null;
int result=node.key.compareTo(key);
if (result<0) node.right=delete(node.right,key);
else if (result>0) node.left=delete(node.left,key);
else{
if (node.left==null) return node.right;
if (node.right==null) return node.left;
Node temp=node;
Node replaceNode=min(node.right);
node=replaceNode;
node.right=deleteMin(temp);
node.left=temp.left;
}
node.n=size(node.left)+size(node.right)+1;
return node;
}
public Key max() {
return max(root).key;
}
private Node max(Node node) {
if(node.right==null) return node;
else return max(node.right);
}
public Key min() {
return min(root).key;
}
private Node min(Node node) {
if(node.left==null) return node;
else return min(node.left);
}
public boolean contains(Key key){
return false;
}
public Key floor(Key key) {
Node x=floor(root,key);
if (x!=null) return x.key;
else return null;
}
private Node floor(Node node,Key key){
if (node ==null) return null;
int result=node.key.compareTo(key);
if (result==0) return node;
if (result>0) return floor(node.left,key);
Node rightNode=floor(node.right,key);
if (rightNode!=null) return rightNode;
else return node;
}
public Key ceiling(Key key) {
Node x=ceiling(root,key);
if (x!=null) return x.key;
else return null;
}
private Node ceiling(Node node,Key key) {
if (node==null) return null;
int result=node.key.compareTo(key);
if (result==0) return node;
if (result<0) return ceiling(node.right,key);
Node leftNode=floor(node.left,key);
if (leftNode!=null) return leftNode;
else return node;
}
public int rank(Key key) {
return rank(root,key);
}
public int rank(Node node,Key key) {
if (node==null) return 0;
int result=node.key.compareTo(key);
if (result>0) return rank(node.left,key);
else if (result<0) return size(node.left)+1+rank(node.right,key);
else return size(node.left);
}
public Key select(int k) {
Node x=select(root,k);
if (x!=null) return x.key;
else return null;
}
public void deleteMax() {
root=deleteMax(root);
}
private Node deleteMax(Node node) {
if (node.right==null) return node.left;
node.right=deleteMax(node.right);
node.n=size(node.left)+size(node.right)+1;
return node;
}
public void deleteMin() {
root=deleteMin(root);
}
private Node deleteMin(Node node) {
if (node.left==null) return node.right;
node.left=deleteMin(node.left);
node.n=size(node.left)+size(node.right)+1;
return node;
}
public Node select(Node node,int k) {
if (node==null) return null;
int t=size(node.left);
if (t>k) return select(node.left,k);
if (t==k) return node;
return select(node.right,k-t-1);
}
public Iterable<Key> keys(Key lo, Key hi) {
return null;
}
}