散列表也叫哈希表,是一种根据关键字直接访问内存存储位置的数据结构,它是用一个数组实现的无序符号表.将键作为数组的索引而数组中键i处存储的就是它对应的值,这样就可以实现快速访问任意键的值.散列表是算法在时间和空间上做出权衡的经典例子.

散列表简介

 

散列表的查找算法分为两步:

1.用散列函数将键转化为数组索引,可能会出现多个键散列到相同的索引值上面,这是就要进行第二步了.

2.处理碰撞冲突(拉链法和线性探测法).

 

 

散列函数的概念

散列函数应该易于计算并且能够均匀分布所有的键, 即对于任意键, 0到M-1之间每个整数都有相同的可能性与之对应(与键无关),  严格地说每种类型的键都应该有对应的散列函数.

 

正整数: 一般用除留余数法,选择素数为M的数组,对于任意正整数k,计算k除以M的余数.可以有效的散布在0-M-1之间.如果M不是素数,可能不会均匀散布.

 

     散列表简介

 

浮点数:java中将键表示为二进制然后使用除留取余法

.

字符串:java中charAt()返回一个非负16位整数,只要R足够小,不造成溢出,那么结果就会落在0至M-1之间

int hash = 0;
for (int i = 0; i < s.length(); i++)
    hash = (R * hash + s.charAt(i)) % M;

 

组合键:如果键中含有多个整型变量, 我们可以和String类型一样将它们混合起来,例如Date类型, 含有几个整型的域: day, month和year, 我们可以这样计算散列值:

int hash = (((day * R + montn) % M) * R + year) % M;

只要R足够小不造成溢出,也可以得到一个0至M-1之间的散列值. 

 

软缓存

如果散列值的计算很耗时,我们可以将每个键的散列值缓存起来,即每个键中使用一个hash变量保存它的hasCode()的返回值。

 

 

基于拉链法的散列表

 

散列表简介

 

 

public class SeparateChainingHashST<Key, Value> {
    
    private int N; //键值对总数
    private int M; //散列表大小
    private SequentialSearchST<Key,Value>[] st;    //存放链表对象的数组
    
    public SeparateChainingHashST(){
        this(100);
    }
    
    public SeparateChainingHashST(int M){
        //创建M条链表
        this.M = M;
        st = (SequentialSearchST<Key,Value>[]) new SequentialSearchST[M];
        for(int i=0; i<M; i++){
            st[i] = new SequentialSearchST(); 
        }
    }
    
    private int hash(Key key){
        return (key.hashCode() & 0x7fffffff) % M;
    }
    
    private Value get(Key key){
        return (Value)st[hash(key)].get(key);
    }
    
    private void put(Key key,Value val){
        st[hash(key)].put(key, val);
    }
}
View Code

相关文章:

猜你喜欢
  • 2022-12-23
  • 2021-12-12
相关资源
相似解决方案