您的位置:首页 > 其它

查找:链表顺序查找和有序数组二分查找

2017-03-17 11:07 330 查看

符号表

符号表是一种存储键值对的数据结构,支持两种操作:插入(put)和查找(get)。

可以分为无序符号表和有序符号表。

本节的实现基于

每个键只对应着一个值,表不允许存在重复的键

向表中存入新的键值对和已有的键冲突时,新的值会替代旧的值

键不能为空null

值不能为空null

无序链表中的顺序查找

非常的低效

向一个空表插入N个不同的键需要N^2/2次比较。

只适用于小型问题,对于大型符号表很慢

public class SequentialSearchST<Key,Value>{
private Node first;  // 链表首结点
private class Node{
Key key;
Value val;
Node next;
public Node(Key key, Value val, Node next){
this.key = key;
this.val = val;
this.next = next;
}
}
public Value get(Key key){
for(Node x = first; x != null; x = x.next){
if(key.equals(x.key))
return x.val;
}
return null;
}
public void put(Key key, Value val){
for(Node x = first; x != null; x = x.next){
if(key.equals(x.key)){
x.val = val;
return ;
}
}
first = new Node(key, val, first); // 放在首结点位置(链表)
}
}


有序数组的二分查找

rank() 是核心

除了符号表的get/put等关键操作,还基于有序的数组实现其它方法

最优的查找效率和空间需求,进行有序性相关的操作。但是插入操作很慢

注:

有序数组在插入时就进行了排序。

package com.base;

public class BinarySearchST<Key extends Comparable<Key>, Value> {
private static final int INIT_CAPACITY = 2;
private Key[] keys;
private Value[] vals;
private int N = 0;

// 默认容量初始化
public BinarySearchST() { this(INIT_CAPACITY); }

// 给定容量初始化
public BinarySearchST(int capacity) {
keys = (Key[]) new Comparable[capacity];
vals = (Value[]) new Object[capacity];
}

// 调整数组大小
private void resize(int capacity) {
assert capacity >= N;
Key[]   tempk = (Key[])   new Comparable[capacity];
Value[] tempv = (Value[]) new Object[capacity];
for (int i = 0; i < N; i++) {
tempk[i] = keys[i];
tempv[i] = vals[i];
}
vals = tempv;
keys = tempk;
}

// 是否包含
public boolean contains(Key key) {
return get(key) != null;
}

// 键值对个数
public int size() {
return N;
}

// 符号表是否为空
public boolean isEmpty() {
return size() == 0;
}

// 根据键得到值
public Value get(Key key) {
if (isEmpty()) return null;
int i = rank(key);
if (i < N && keys[i].compareTo(key) == 0) return vals[i];
return null;
}

// 返回比跟定键小的键
public int rank(Key key) {
int lo = 0, hi = N-1;
while (lo <= hi) {
int m = lo + (hi - lo) / 2;
int cmp = key.compareTo(keys[m]);
if      (cmp < 0) hi = m - 1;
else if (cmp > 0) lo = m + 1;
else return m;
}
return lo;
}

// 更新值,或插入键值
public void put(Key key, Value val)  {
if (val == null) { delete(key); return; }

int i = rank(key);

// key is already in table
if (i < N && keys[i].compareTo(key) == 0) {
vals[i] = val;
return;
}

// 扩展keys
if (N == keys.length) resize(2*keys.length);

for (int j = N; j > i; j--)  {
keys[j] = keys[j-1];
vals[j] = vals[j-1];
}
keys[i] = key;
vals[i] = val;
N++;
}

// 删除键值对
public void delete(Key key)  {
if (isEmpty()) return;

// compute rank
int i = rank(key);

// key not in table
if (i == N || keys[i].compareTo(key) != 0) {
return;
}

for (int j = i; j < N-1; j++)  {
keys[j] = keys[j+1];
vals[j] = vals[j+1];
}

N--;
keys
= null;  // to avoid loitering
vals
= null;

// resize if 1/4 full
if (N > 0 && N == keys.length/4) resize(keys.length/2);

}

// 删除最小键和关联的值
public void deleteMin() {
if (isEmpty()) throw new RuntimeException("Symbol table underflow error");
delete(min());
}

// 删除最大键和关联的值
public void deleteMax() {
if (isEmpty()) throw new RuntimeException("Symbol table underflow error");
delete(max());
}

/*****************************************************************************
*  Ordered symbol table methods
*  有序符号表的方法
*****************************************************************************/
// 最小
public Key min() {
if (isEmpty()) return null;
return keys[0];
}
// 最大
public Key max() {
if (isEmpty()) return null;
return keys[N-1];
}
// 排名在k的键
public Key select(int k) {
if (k < 0 || k >= N) return null;
return keys[k];
}
// 小于等于key的最大键
public Key floor(Key key) {
int i = rank(key);
if (i < N && key.compareTo(keys[i]) == 0) return keys[i];
if (i == 0) return null;
else return keys[i-1];
}
// 大于等于key的最小键
public Key ceiling(Key key) {
int i = rank(key);
if (i == N) return null;
else return keys[i];
}
// lo--hi 之间的键的数量
public int size(Key lo, Key hi) {
if (lo.compareTo(hi) > 0) return 0;
if (contains(hi)) return rank(hi) - rank(lo) + 1;
else              return rank(hi) - rank(lo);
}
// 迭代
public Iterable<Key> keys() {
return keys(min(), max());
}

public Iterable<Key> keys(Key lo, Key hi) {
Queue<Key> queue = new Queue<Key>();
if (lo == null && hi == null) return queue;
if (lo == null) throw new RuntimeException("lo is null in keys()");
if (hi == null) throw new RuntimeException("hi is null in keys()");
if (lo.compareTo(hi) > 0) return queue;
for (int i = rank(lo); i < rank(hi); i++)
queue.enqueue(keys[i]);
if (contains(hi)) queue.enqueue(keys[rank(hi)]);
return queue;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐