散列表(哈希表)的介绍与理解

哈希表
1.定义:哈希表,英文为Hash Table,中文也可以叫做散列表,它是通过关键码值(key value)映射到表中一个位置来访问表中的元素内容,这样就可以加快查找的速度。这个映射函数叫做散列函数,存放元素内容(或者说是记录)的数组叫做散列表。


2.HashSet和HashMap的底层实现都是哈希表(散列表)!
HashSet是通过HashMap来实现的,HashSet是保存单值的,而HashMap是保存键值对的,HashMap的输入参数有Key、Value两个,在实现HashSet的时候,保持HashMap的value为常量,相当于在HashMap中只对key对象进行处理,因为HashSet只是保存单值的,这个单值就是Key对象。


3.HashMap的底层是一个数组结构,数组中的每一项对应了一个链表,这种结构称为"链表散列"的数据结构,即数组和链表的结合体,也叫散列表、哈希表。这种实现方法是哈希表最常见的实现方法,叫做拉链法,我们可以理解为"链表的数组",就是链表和数组的结合体。


4.为何哈希表是链表和数组的结合体呢?
数组:易于读取(通过for循环),不便存储(数组长度有限制),插入和删除难;
链表:易于存储(插入和删除容易),不易于快速读取。


5.哈希表原理
对HashMap的Key调用hashCode()方法,返回int值,即hashCode值,也可以说这是关键字Key通过哈希函数变成了一个整型数字,然后将这些散列地址对数组进行取余,把这些散列地址映射成该数组的下标,再把value存储在该下标对应的数组空间中。把任意长度的输入,通过散列算法(散列函数),变成固定长度的输出,该输出就是散列值,散列地址也就是这些映射成数组下标的值。如果该集合中存储的对象元素有成百上千个甚至成千上万个,那么就很有可能许多个元素的Key的散列地址映射成了数组中相同的下标值(毕竟数组长度有限,而且它是拉链法实现的,映射成数组中相同下标值的元素可以放在同一个链表当中去)。


6.HashMap存储对象过程
1)对HashMap的Key调用hashCode()方法,返回int类型的散列地址,此时散列地址会映射到数组的下标。

2)根据数组的下标,尝试把该Key代表的对象元素放在该下标对应数组的位置空间,如果该位置没有对象,则放进去;如果有对象,则查找到该索引位置的链表,利用equals()方法去判断是否与这些元素相同(返回true),如果存在相同的,则把该元素的值替换成新的,如果equals()方法返回false,则说明你所要添加进去的对象和所在链表中的对象没有出现重复的,于是,就把所要添加的对象链接到该链表的头部,以前存在对象的链表接到该对象的后面,于是就形成了Entry链。<Key的hashCode(key.hashCode)相同的话就存储在数组中同一下标的Entry链中>


7.散列函数构造方法

   好的散列函数参考原则:①计算简单。散列函数的计算时间不应该超过其他查找技术与关键字比较的时间;②散列地址均匀分布。地址均匀分布,可以保证存储空间的有效利用,减少为处理冲突而耗费的时间。

  常见散列函数构造方法如下:

  (1)直接定址法:取关键字或关键字的某个线性函数值为哈希地址,即H(key)=key或H(key)=a*key+b。由于直接定址法所得地址集合和关键字集合大小相同,因此对于不同的关键字不会发生冲突,但实际中使用这种哈希函数的情况很少。直接定址法适用于事先知道关键字的分布情况,查找表较小且连续的情况

    例:制作0~100岁的人口数字统计表,可将关键字0~100分别对应存放于0~100的连续地址中,此时H(key)=key。

  (2)数字分析法:分析关键字中的数字,找出差异较大的部分作为哈希函数的输入值。数字分析法适用于事先知道关键字的分布情况,关键字较长且若干位分布较均匀的情况

    例:根据某单位员工的手机号码制作散列表,可取手机号码的后四位作为散列表的输入。

  (3)平方取中法:取关键字平方后的中间几位数字作为哈希函数的输入值。一个数的平方中间几位与每位数字都有关,当数字分析法不合适时,可考虑使用此方法。平方取中法适用于不知道关键字的分布且位数又不是很大的情况

    例:1)关键字1234的平方是1522756,取中间三位就是227。 2)关键字4321平方是18671041,取中间三位为671或710。

  (4)折叠法:将关键字从左到右分割成位数相等的几部(最后一部分位数允许短些),然后将这几部分叠加求和,并按散列表表长,取后几位作为散列地址。折叠法事先不需要知道关键的分布适用于关键字位数较多的情况

    例:散列表表长为0~999,地址位数为3位,我们将关键字9876543210分为四组,987|654|321|0,然后这几部分求和987+654+321+0=1962,取后3位962即为散列地址。

  (5)除留余数法:取关键字或关键字折叠、平方取中后对某个数p取模,对于散列表表长为m的散列函数公式为:H(key)=key mod p(p<=m)。

除留余数法最重要的就是p的选择,p选择的好坏直接影响冲突的个数。前辈们的经验,通常p为小于等于表长m(最好接近m)的最小质数或不包含小雨20质因子的和数。

  (6)随机数法:H(key)=random(key)。随机数法相关资料很少,使用情况有待进一步考证


8.散列表的查找

   散列表查找时,现根据散列函数将关键字转换成散列地址,再到对应的散列地址中取值,若值的标记与关键字相等,则查找成功;若不相等,则说明该关键字值存在冲突,根据相应处理冲突的方法进行相应的查找。

  散列表的平均查找长度取决于以下因素:①散列表是否均匀;②处理冲突的方法;③散列表的装填因子(装填因子a=关键字个数/散列表长度)。

 




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值