散列表(hashmap)

一、直接寻址表

1.直接寻址:适用于全域U比较小时,直接让关键字对应hashmap(数组)的下标。

2.为了表示动态集合,我们可以用数组(或称为直接寻址表),其中每个位置称为槽,对应全域U中的一个关键字,槽k指向集合中一个关键字为k的元素

二、散列表

1.当U很大时,无法直接在数组中表示,那么就需要使用散列表,在散列方式下,元素存放在槽hash(k)中,即利用散列函数(hash)由关键字k计算出槽的位置,hash(k)被称为散列值。简言之,散列函数缩小了数组下标的范围

2.对数组来说,易访问,难插入删除;对链表来说,易插入删除,难访问;对于散列表来说,它具有二者的优点,但是也有自己的缺陷

3.对于两个不同的关键字,,可能映射到同一个槽中,我们称这种情形为冲突

三、散列函数

1.好的散列函数:(近似地)满足简单均匀序列,每个关键字都被等可能的散列到m个槽位中地任何一个

2.将关键字转换为自然数,多数散列函数都假定关键字的全域为自然数集N,例如一个字符串可以转化成十进制整数

3.除法散列法:

通过取k除以m的余数,将关键字k映射到m个槽位中的某一个上,散列函数为:

hash(k)=k mod m

对于模数通常选取不太接近2的整数幂的素数

4.乘法散列法:

用关键字乘上常数A(0<A<1),提取kA的小数部分,用m乘以这个值再向下取整,散列函数为:

hash(k)=(int)(m*(k*A mod 1))

对于m,它的选择不是很关键,一般选择它为2的某个幂次;对于A,限制A为形如:s/2^\omega的一个分数,\omega为某计算机的字长,A的值趋近于(\sqrt5-1)/2=0.618...

 5.全域散列法:

散列函数最坏的情况是所有关键字都散列到同一个槽中,对任何一个特定的散列函数都可能出现这种情况,唯一有效的改进方法是随机的选择散列函数,使之独立于要储存的关键字,这就是全域散列,平均性能很好

四、冲突解决

1.链接法:

在链接法中,把散列到同一个槽中的所有元素都放在一个链表中,槽中有一个指针,指向储存所有散列到j的元素的链表的表头,为了更快的删除某一元素,链表可以设计为双向链接

给定一个能存放n个元素的、具有m个槽位的散列表T,定义T的载装因子\alpha为:n/m

2.开放寻址法:

在开放寻址法中,所有的元素都存放在散列表中,散列表可能会被填满,以至于不能插入任何新的元素,载装因子不超过1,这种方法不用储存指针节省了更多空间

为了使用开放寻址法插入一个元素,需要连续地检查散列表,或称为探查,直到找到一个空槽来放置待插入的关键字位置位置

使用开放寻址法时,删除元素比较困难,删除元素时我们将槽标识为空,当我们再次寻找元素时(遇到空停止寻找)该元素后面连续的槽就无法被找到,无法找到关键字k,所有删除元素时需要将槽标记为DELETED标识,以此继续向下寻找元素。也正是因为这个原因,在必须删除关键字的应用中,更常见的做法是用链接法

三种探查方法:

(1)、线性探查

给定一个普通的散列函数hash',称之为辅助散列函数,则线性探查方法采用的散列函数为:

hash(k,i)=(hash'(k)+i) mod m

也就是探查T[hash'(k)],然后是T[hash'(k)+1]........,如果超过m对m取模。

线性探查存在一个问题,一次集群:当一个空槽前有i个满的槽时,该空槽为下一个被占用的概率为(i+1)/m,随着连续占用的槽不断增加,平均查找时间也不断增加,集群现象很容易出现

(2)、二次探查

使用如下形式的散列函数:

hash(k,i)=(hash'(k)+c1*i+c2*i*i) mod m

(3)、双重散列

是用于开放寻址法的最好的方法之一,使用如下形式的散列函数:

hash(k,i)=(hash1(k)+i*hash2(k)) mod m

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值