1. API
1.1 符号表
键值对的集合
- 插入键值对
- 给定键,快速找到相关值
1.2 基本的API
public class ST<Key, Value>
------------------------------------------------------
ST()
void put(Key key, Value value)
Value get(Key key)
void delete(Key key)
boolean contains(Key key)
boolean isEmpty()
int size()
Iterable<Key> keys()
1.3 默认的约定
- 符号表中的值(Values)不为null
- 如果键不在符号表中,get()返回null
- put()方法对于某键有新值时会覆盖旧值
1.4 键与值
值的类型:泛型
键的类型:
- 如果键实现了Comparable接口,使用compareTo()方法去比较大小
- 如果键是泛型,使用equals()去检验相等,使用hashCode()去映射key
equals()不仅包含对象引用相等的检查,而且包括业务上相等的检查
public final class Date implements Comparable<Date> {
private final int month;
private final int day;
private final int year;
...
public boolean equals(Object y) {
//check for null
if(y == null) retrun false;
//check for true equals
if(y == this) return true;
//objects must be in the same class
if(y.getClass() != this.getClass()) return false;
//
Date that = (Date) y;
if (this.day != that.day ) return false;
if (this.month != that.month) return false;
if (this.year != that.year ) return false; return true;
}
}
通用方法:
- 检查引用是否相等
- 检查是否为null
- 检查两个对象是否为相同的数据类型,如果是,强转
- 根据业务上的需求,检查相应的成员变量
- 如果成员变量为基本数据类型,使用 ==
- 如果成员变量为对象,使用quals()
- 如果成员变量为数组, 检查数组的每一项。此外,还可以使用Arrays.equals(a, b)或者Arrays.deepEquals(a, b),绝对避免使用equals(a, b)。
2. 初级实现
2.1 链表中的顺序查找
- 数据结构:维护一个无序的链表去存储键值对
- 搜索:扫描链表
- 插入:扫描链表,如果有匹配的键,更新值;如果没有匹配的键,插入键值对到链表的头。
复杂度:
ST实现 | 最坏 | 平均 | 按序遍历 | 键需要实现的接口 | ||
查找 | 插入 | 查找 | 插入 | |||
顺序查找 | N | N | N/2 | N | no | equals() |
2.2 有序数组的二分查找
- 数据结构:维护一个有序数组去存储键值对
- 排序方法rank(key):返回keys<key的数量
java实现
public Value get(Key key) {
if(isEmpty()) return null;
int i = rank(key);
if(i < N && keys[i].compareTo(key) == 0) return vals[i];
else return null;
}
//number of keys < key
private int rank(Key key) {
int lo = 0, hi = N - 1;
while(lo <= hi) {
int mid = lo + (hi - lo) / 2;
int cmp = key.compareTo(keys[mid]);
if(cmp < 0) hi = mid - 1;
else if (cmp > 0) lo = mid + 1;
else return mid;
}
return lo;
}
复杂度:
ST实现 | 最坏 | 平均 | 按序遍历 | 键需要实现的接口 | ||
查找 | 插入 | 查找 | 插入 | |||
顺序查找 | N | N | N/2 | N | no | equals() |
二分查找 | log N | N | log N | N/2 | yes | compareTo() |
3. 有序的符号表实现
3.1 有序符号表的API
public class ST<Key extends Comparable<Key>, Value>
-----------------------------------------------------
ST()
void put(Key key, Value val)
Value get(Key key)
void delete(Key key)
boolean contains(Key key)
boolean isEmpty()
int size()
Key min()
Key max()
Key floor(Key key)
Key ceiling(Key key)
int rank(Key key)
Key select(int k)
void deleteMin()
void deleteMax()
int size(Key lo, Key hi)
Iterable<Key> keys(Key lo, Key hi)
Iterable<Key> keys()
3.2 性能分析
顺序查找 | 二分查找 | |
search | N | log N |
insert/delete | N | N |
min/max | N | 1 |
floor/ceiling | N | log N |
rank | N | log N |
select | N | 1 |
ordered iteration | NlogN | N |