哈希表是一种存储记录的连续内存通过哈希函数的应用,通过哈希函数的应用,可以快速存取与查找数据。所谓哈希法(Hashing),就是将本身的键(Key)通过特定的数学函数运算或使用其他的方转化成对应的数据存储地址。
注:哈希法所使用的数学函数称为“哈希函数”(Hashing Function)。另外,Key在不混淆“键值对”时也可称之为键值。
先来了解一下有关哈希函数的相关名词
·Bucket(桶):哈希表中存储数据的位置,每一个位置对应唯一的地址(Bucket Address)桶就好比存在一个记录的位置
·Slot(槽):每一个记录可能包含多个字段,而Slot指的就是“桶”中的字段
·Collision(碰撞):两个不同的数据经过哈希函数运算得到相同的地址、
·溢出:如果数据经过哈希函数原酸后所对应的Bucket已满,就会使Bucket发生溢出
·哈希表:存储记录的连续内存。哈希表是一种类似数据表的索引表格,其中可以分为n个Bucket,每个Bucket又可分为m个Slot
·同义词(Synonym):当两个标识符和经过哈希函数运算后所得的数值相同时,即f()=f(),就称和对于f这个哈希函数是同义词
·加载密度:标识符的使用数目除以哈希内槽的总数,加载密度越大,表示哈希存储空间的使用率越高,碰撞或溢出的概率也会越高
·完美哈希:没有碰撞也没有溢出的哈希函数
在设计哈希函数时应遵循以下原则:
(1)避免碰撞和溢出的发生
(2)哈希函数不宜过于复杂,越容易计算约佳
(3)尽量把文字的键值转换成数字的键值,以利于哈希函数的运算
(4)所设计哈希函数计算得到的值尽量能均匀地分布在每一桶中,不要过于集中度在某些桶中,这样既可以降低碰撞又能减少溢出
解决哈希冲突的办法有哪些?
解决哈希冲突的办法有:开放定址法,再哈希法,链地址法(拉链法),建立公共溢出区。HashMap中采用的是链地址法
·开发定址法也成为了再散列法,基本思想就是如果P=H(Key)出现冲突是,则以P为基础,再次hash, p1=H(p),如果p1再出现冲突,则以p1为基础,以此类推,直到找到一个不冲突的哈希地址pi因此开放定址法所需要的hash表的长度要大于等于所需要存放的元素,而且因为存在再次hash,所以只能在删除的节点上做标记,而不能真正删除结点。
再哈希法(双重散列,多重散列):提供多个不同的hash函数,当R1=H1(Key1)发生冲突时,再计算R2=H2(Key2),直到没有冲突为止。这样虽然不容易产生堆集,但增加了计算时间。
链地址法(拉链法),将哈希值相同的元素工程一个同义词的单链表,并将单链表的头指针存放在哈希表的第i个单元中,查找,插入和删除主要在同一链表中进行。链表法适用于经常进行插入和删除的情况
建立公共溢出区:将哈希表分公共表和已出表,当一处发生时,将所有溢出数据统一存放到溢出区