【哈希表专题-基础知识】

1.哈希表

首先什么是 哈希表,哈希表(英文名字为Hash table,国内也有一些算法书籍翻译为散列表,大家看到这两个名称知道都是指hash table就可以了)。

哈希表是根据关键码的值而直接进行访问的数据结构。

在这里插入图片描述
上图中数组就是一张哈希表,哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素。
那么哈希表能解决什么问题呢,一般哈希表都是用来快速判断一个元素是否出现集合里。

例如如果我们要在数组中查找是否存在某个元素时,需要依次遍历数组中的元素来判断是否存在指定查找的元素,这样查找的效率就比较低;如果我们使用哈希表来存储元素,那么在进行查找时就非常方便,只需要根据指定的元素,通过hashcode()函数生成对应的哈希值,根据哈希值直接找到集合汇总对应的位置,判断该位置上是否存在元素?因此不需要遍历其他的元素,查找效率较高。

在平时的刷题中,哈希表的用途基本都是判断一个元素是否出现在集合中!

2.哈希函数

首先,通过如下的图示可知,对于整型元素(这里只是举例,使用整型),通过哈希函数的计算,每个元素都对对应一个哈希表中的索引。(上图中每个元素都会对应一个哈希表中的位置)

在这里插入图片描述
通过上图我们可以发现,如果整型元素较多,而哈希表的长度有限,那么就会出现元素拥有相同地址的情况,这就我们要讲的哈希冲突或哈希碰撞。

2.1 常用的哈希函数的构造方法

1,直接寻址法或者k的某个线性函数为Hash地址

特点:由于直接地址法相当于有多少个关键字就必须有多少个相应地址去对应,所以不会产生冲突,也正因为此,所以实际中很少使用这种构造方法。

2,数字分析法

首先分析待存的一组关键字 ,比如是一个班级学生的出生年月日 ,我们发现他们的出生年 大体相同,那么我们肯定不能用他们的年 来作为存储地址 ,这样出现冲突 的几率很大;但是,我们发现月日 的具体数字差别很大,如果我们用月日 来作为Hash地址 ,则会明显降低冲突几率。因此,数字分析法就是找出关键字 的规律,尽可能用差异数据来构造Hash地址 ;

特点:需要提前知道所有可能的关键字,才能分析运用此种方法,所以不太常用。

3,平方取中法

先求出关键字的平方值,然后按需要取平方值的中间几位作为哈希地址。这是因为:平方后中间几位和关键字中每一位都相关,故不同关键字会以较高的概率产生不同的哈希地址。

4,折叠法

将关键字分割成位数相同的几部分(最后一部分位数可以不同),然后取这几部分的叠加和(去除进位)作为散列地址。数位叠加可以有移位叠加和间界叠加两种方法。移位叠加是将分割后的每一部分的最低位对齐,然后相加;间界叠加是从一端向另一端沿分割界来回折叠,然后对齐相加。

5,随机数法

选择一个随机函数,取关键字的随机函数值作为Hash地址 ,通常用于关键字长度不同的场合。即

特点:通常,关键字长度不相等时,采用此法构建Hash函数 较为合适。

6,除留余数法

取关键字被某个不大于Hash表 长m 的数p 除后所得的余数为Hash地址 。

特点:这是最简单也是最常用的Hash函数构造方法。可以直接取模,也可以在平法法、折叠法之后再取模。

值得注意的是,在使用除留取余法 时,对p 的选择很重要,如果p 选的不好会容易产生同义词 。由经验得知:p 最好选择不大于表长m的一个质数 、或者不包含小于20的质因数的合数。

3.哈希碰撞

如下图所示,10和40都指向了相同的索引位置,就是哈希碰撞。
在这里插入图片描述
理解:冲突是指由关键字得到的哈希地址的位置上已存有记录,则“处理冲突”就是为该关键字的记录找到另一个“空”的哈希地址。
在处理冲突的过程中可能得到一个地址序列。即在处理哈希地址的冲突时,若得到的另一个哈希地址仍然发生冲突,则再求下一个地址,若仍然冲突,再求,依次类推,直至不发生冲突为止,则为记录在表中的地址。 (需要注意此定义不太适合链地址法)

1,开放地址法

哈希函数; 为哈希表表长;
增量序列,有3种取法:

(1)称为线性探测再散列

(2)称为二次探测在散列

(3)称为伪随机探测再散列

2,再哈希法

均是不同的哈希函数,即在同义词产生地址冲突时计算另一个哈希函数地址,直到冲突不再发生,这种方法不易产生聚集 ,但增加了计算时间;

3,链地址法

将所有关键字为同义词的记录存储在同一线性表中。即在Hash 出来的哈希地址中不直接存Key ,而是存储一个Key 的链表 ,当发生冲突 时,将同义的Key 加入链表 ,如下图所示为链地址法的示意图,数组+链表结合。
在这里插入图片描述
4,公共溢出

可以建立一个公共溢出区,用来存放有冲突的Key 。比如设立另一个哈希表,专门用来存放出现冲突的同义词。

4.常见的哈希结构(刷题时使用)

用哈希表解决问题,常会使用如下三种数据结构:

  • 数组
  • set集合
  • map映射

对于set集合:
|-----Set接口:仅接受一次,不可重复,并做内部排序

|----------|-HashSet使用hash表(数组)存储元素

|-----------------LinkedHashSet链表维护元素的插入次序

|----------|-TreeSet底层实现位二叉树,元素排好序

对于map映射:
Map接口 键值对的集合(双列集合)

|-----Hashtable 接口实现类,同步,线程安全

|-----HashMap 接口实现类,没有同步,线程不安全

|-----------------LinkedHashMap 双向链表和哈希表实现

|-----------------WeakHashMap

|-----TreeMap 红黑树对所有的key进行排序

|-----IdentifyHashMap

在刷题中,如果仅仅需要存储单列元素set来存储,如仅仅只将元素放入哈希表中;如果不仅要将元素放入哈希表,而且还要记录元素的次数或位置,那就需要使用双列集合map来存储。

该文部分内容与代码随想录相似,仅作为个人学习复习所用,并已注明。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值