【数据结构之哈希表(一)】 解决哈希冲突的四种办法(举例推演(1)

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

+ [(一)开放定址法](#_16)
+ - [(1)线性探查法](#1_28)
	- [(2)线性补偿探查法](#2_49)
	- [(3)随机探测](#3_69)
	- [(4)二次探查](#4_80)
+ [(二)再哈希法](#_85)
+ [(三)链地址法](#_110)
+ [(四)建立公共溢出区](#_135)
+ [结束语](#_154)

导语

哈希表是我们在开发中经常使用到的一种数据结构。它的结构也决定了它不可避免地会产生冲突。那么,如何解决哈希冲突呢?

我搜索了一些资料,如今结合自己的理解做一个学习记录。

我们先给出一个产生哈希冲突的例子:

(16、25、3、29、5、2、19、17、34)
Hash(key)= key % 11。

对应的地址应该是:

5、3、3、7、5、2、8、6、1

很显然存在哈希冲突。
接下来我们来看一下不同方法分别是如何处理这种冲突的:

(一)开放定址法

第一种方法是开放定址法,也就是说当冲突发生时,使用某种探查技术生成一个探查序列,再按照该序列逐个寻找。

插入:

  • 寻找一个开放的地址,将待插入节点存入该地址单元,插入成功
  • 如果查找到了最后一个地址仍未找到,则代表该表已满,插入失败。

查找:

  • 寻找给定的关键字,查找成功;
  • 如果找到了开放的地址,或者查找到了最后一个地址,说明表中无待查关键字,查找失败。

有以下几种常见的探查技术:

(1)线性探查法

h(key) = d;
探查序列为:d、d+1、d+2、…、0、1、…、d-1。

解决方案

(16、25、3、29、5、2、19、17、34)
Hash(key)= key % 11。

哈希值: 533 475 6286 7 8 9、1

012345678910
342253165291917

缺点:

  • 容易造成堆聚现象。所谓堆聚现象,就是存入哈希表的记录在表中连成一片。这样一来,再有新的记录时更容易发生冲突,也就是说非同义词也可能发生冲突,进一步造成堆聚。
  • 删除工作困难,只能标记该节点已删除,而不能真正置空该位置因为会截断其后的同义词的查找。这是所有开放定址法的共同缺陷。
  • 如果发生溢出,要另外设立顺序溢出表。
(2)线性补偿探查法

h(key)=d;
哈希表长度为n,q与n互质(能保证遍历所有位置)。
探查序列为:di = (d+q)%n(0<=i<=n-1)

解决方案

(16、25、3、29、5、2、19、17、34)
Hash(key)= key % 11。
不妨取q = 5。

哈希值: 533 875 1028 2 7 161 6 0

012345678910
341922516172935

缺点:

  • 同线性探测,删除困难。
(3)随机探测

随机探测就是将线性探测的步长从常数改为随机数。

不同的关键字随机产生不同的探测序列,可以减少堆聚。

优点:

  • 减少堆聚

缺点:

  • 尽管不同关键字具有不同的探测序列,但同一关键字的探测序列却是固定的,所以仍然不能直接删除,而只能打上删除标记。
(4)二次探查

探查序列为:di = h(key) + i2(i>=0).

不能遍历所有空位,但当用该办法查找不到空位时,也是该扩充哈希表的时候。

(二)再哈希法

再哈希法也叫再散列法,是指当发生冲突时,对得到的哈希值进行再次哈希,直至不再发生冲突为止。需要多个不同的哈希函数。
h1(key) = d1;
h2(key) = d2;

hi(key) = di;

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

尝辄止,不再深入研究,那么很难做到真正的技术提升。**

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值