超萌新级的学习心得——哈希表

哈希表

哈希表是一个很重要的数据结构,是一个使用散列函数储存数据的数组。

首先,要区分一个概念,哈希表是一个数组,而日常听人解释说:根据一个键值(key)找到一个值(value),这个东西是映射函数,也叫散列函数,哈希表就是使用这个函数将两个值并存起来的一个数据结构,本质其实是一个数组,不是两个数组。

      存储值的步骤如下:

  1. 获得值x,根据散列函数f(x)计算出一个值k。
  2. 然后将x存在地址k处(如果是数组的话为a[k]=x)。.

散列函数可以是根据数据的不同,场合的不同进行改变,按应用场合来制定,可以是比较简单的分类如:fx=x mod 13,也可以是超级复杂的。


举个例子,这里有一个散列函数:fx=x mod 13,然后存一个序列: 15 13 14 37。

经过计算:

 

哈希表就会是以下情况:

 


在编写程序实现功能时,一直会有一个矛盾,就是时间空间上的矛盾,大多数情况下是两者取其一。因此大佬们在编写程序时会对这两个方面进行权衡,因此在设计存储数据的数据结构时,可以使用值(value)作为地址直接进行存储,在无视空间大小的前提下,以达到极端的节省时间;也可以无序的存储,顺序查找,在无视时间的前提下,以达到较极端的节省空间。而哈希表在这两者之间做出了权衡,它会根据散列函数来调整时间和空间。

这个说法就很微妙,理论上来说哈希表在查找元素时的时间复杂度应该是O(1),应该是不会存在降低的可能,但是这个情况是一种理想情况,与物理的理想模型类似,通常哈希函数不可能达到O(1)的复杂度,但是哈希函数在字符串哈希的线性的搜索中确实是非常快的,并且在某种程度上是稳定的,这里只是简单提一下,不深入探讨。


但是上面的例子没有考虑到重复的情况。例如上述情况下我们存入的序列是:15 13 14 37 26。这个就很有意思了,因为

两个应该是会存到同一个地址里的,这明显会出现冲突,这种情况就是哈希冲突

哈希冲突

 一般而言,再好的散列函数都不能避免上述的重复情况,因此为了防止潜在的危险,必须要解决哈希冲突。

1.开放地址法

也称再散列法,意思是对地址进行再次散列,基本操作为:假设地址k出现冲突,就以k为基础,产生另一个地址k1,k2,k3……直到没有冲突为止,此时将值(value)存在地址kn中。通项公式:

一般而言有三种再散列方式:

  • 线性探测再散列:

上述公式的di=1,2,3……m-1,意思是发现冲突会顺序查看表的下一个单元,直到找到空单元或者查完表。

例如,在序列15 13 14 37 26发生冲突时,26是与13冲突,因此进行计算,当di=1时,与14冲突;当di=2时,与15冲突;当di=3时,出现空位,存入地址3位置。

 

如果出现了16等应该存在3位置的值(value)时,同样处理。

  • 二次探测再散列:

同理:di=12,-12,22……,寻找一个合法的空位并存入。

  • 伪随机探测再散列:di=伪随机的数列。

 

2.再哈希法

我们不难看出哈希冲突与散列函数有关,因为散列函数设置的不当导致了两个值(value)产生了同一个键(key),假设这个散列函数是

在当前数据就不会出现哈希冲突。但是一旦加入10,即15 13 14 37 26 10,这也出现了哈希冲突,但是只加入10去掉26,即15 13 14 37 10,使用散列函数

就不会出现哈希冲突。这个就很有说法了,那我们是不是还要绞尽脑汁想出一个哈希函数来保证哈希表能存下15 13 14 37 26 10呢?

答案是没有必要,我们可以同时使用这两个散列函数来消除哈希冲突,即一旦第一个散列函数出现冲突时,使用第二个散列函数来重新计算一下,就会大大降低哈希冲突的几率。

严谨一点讲就是:创建多个哈希函数

fikey出现冲突时,再计算fi+1key……直到冲突不产生为止,然后选取地址储存。这种方法不容易产生聚集(多个数据堆在相邻的地址),但是增加了存取时计算的时间。

3.链地址法

也叫拉链法,这个方法解决哈希冲突的原理类似于分类,即:将产生冲突的数据存在一个单链表里,图示是比较好理解的。

例如之前的数据,13 14 15 37 26

 

然后查找时就遍历单链表知道找到为止,但是这个方法必须建立在良好的散列函数的基础上,即散列的值尽可能的均匀分布,不然就可能出现聚集的情况,并大大增加存取时间。

4.建立一个公共溢出区

大致意思是建立一个溢出区,将发生冲突的放入溢出区,这里不会细讲。

 

哈希表的基础和哈希冲突的心得暂时到这里,关于哈希的其他知识可能会在之后补全。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值