Hash算法介绍

本文介绍了Hash算法的基本概念,包括哈希表和哈希函数的工作原理,以及如何通过线性探测法、链地址法、再哈希法和布谷鸟Hash算法解决哈希冲突。特别提到了OvS(OpenvSwitch)在处理查表过程中如何利用链地址法解决冲突。
摘要由CSDN通过智能技术生成


在OvS查表的过程中,频繁的使用到Hash算法,本文主要介绍Hash算法的功能和原理。

1 Hash算法简介

哈希查找算法又称散列查找算法,是一种借助哈希表(散列表)查找目标元素的方法。哈希表(Hash table)又称散列表,是一种存储结构,通常用来存储多个元素。每个存储到哈希表中的元素,都配有一个唯一的标识(又称“索引”或者“键”),用户想查找哪个元素,凭借该元素对应的标识就可以直接找到它,无需遍历整个哈希表。

多数场景中,哈希表是在数组的基础上构建的。使用数组构建哈希表,最大的好处在于:可以直接将数组下标当作已存储元素的索引,不再需要为每个元素手动配置索引,极大得简化了构建哈希表的难度。在数组中查找一个元素,除非提前知晓它存储位置处的下标,否则只能遍历整个数组。哈希表的解决方案是:各个元素并不从数组的起始位置依次存储,它们的存储位置由专门设计的函数计算得出,我们通常将这样的函数称为哈希函数。

2 Hash算法原理

哈希函数类似于数学中的一次函数,我们给它传递一个元素,它反馈给我们一个结果值,这个值就是该元素对应的索引,也就是存储到哈希表中的位置。举个例子,将{10, 20, 30, 50, 60}存储到哈希表中,我们设计的哈希函数为 y=x/10,最终各个元素的存储位置如下图所示。在下图的基础上,假设我们想查找元素50,只需将它带入y=x/10这个哈希函数中,计算出它对应的索引值为5,直接可以在数组中找到它。借助哈希函数,我们提高了数组中数据的查找效率,这就是哈希表存储结构。

在这里插入图片描述
构建哈希表时,哈希函数的设计至关重要。假设将{5, 20, 30, 33, 55}存储到哈希表中,哈希函数是y=x%10,各个元素在数组中的存储位置如下图所示。可以看到,5和55、20和30对应的索引值是相同的,它们的存储位置发生了冲突,我们习惯称为哈希冲突或者哈希碰撞。设计一个好的哈希函数,可以降低哈希冲突的出现次数。哈希表提供了很多解决哈希冲突的方案,比如线性探测法、链地址法、再哈希法等。

在这里插入图片描述

3 Hash冲突解决方案

3.1 线性探测法

如果使用线性探测法解决哈希冲突,解决方法是:当元素的索引值(存储位置)发生冲突时,从当前位置向后查找,直至找到一个空闲位置,作为冲突元素的存储位置,则上图所示的存储关系变换为下图所示。假设我们从下图所示的哈希表中查找元素30,查找过程需要经过以下几步:

  • 根据哈希函数y=x%10,目标元素的存储位置为0,但经过和下标为0处的元素20比较,该位置存储的并非目标元素。
  • 根据线性探测法,比较下标位置为1处的元素30,二者相等,成功找到目标元素。

在这里插入图片描述

3.2 链地址法

链表地址法是使用一个链表数组,来存储相应数据,当hash遇到冲突的时候依次添加到链表中。链地址在处理的流程如下:

  • 添加一个元素的时候,首先计算元素key的hash值,确定插入数组中的位置。
  • 如果当前位置下没有重复数据,则直接添加到当前位置。
  • 当遇到冲突的时候,添加到同一个hash值的链表中,这个链表的特点是同一个链表上的hash值相同。

在这里插入图片描述

OvS中便是使用链地址法来解决hash冲突,key-value的索引存储在hash表中,如果多个key映射到同一hash table bucket中,通过链表的形式连接起来。每个hash链表以first作为链表的头,hash链表是由多个以first作为头的链表组成。每个hlist_node的next成员保存的是下一个hlist_node的地址,hlist_node的pprev成员保存的是前一个hlist_node的地址。如果是链表第一个元素,保存的是first的地址,最后一个hlist_node的next成员的内容是null,也就是指向null。新增的key-value项插入到链表的头部。
在这里插入图片描述

3.3 再Hash法

再Hash法同时构造多个不同的哈希函数,如h1=x%10,h2=x%7。当使用h1发生冲突时,再用h2进行计算,直到冲突不再产生,这种方法不易产生聚集,但是增加了计算时间。
在这里插入图片描述

3.4 布谷鸟Hash算法

布谷鸟Hash算法引入kick的概念来解决Hash冲突。在该算法中,定义了两个hash table,同时定义了两个hash函数h1和h2。每个key可以存储在table 1的h1(x)槽或table 2的h2(x)槽中,插入步骤如下:

  • 在插入key x时,查询table 1的h1(x)槽是否已被占据。
  • 如果没有,则插入,结束任务;
  • 如被占据,仍然将x插入该位置,将原来的y插入T2的h2(y)中。
  • 如此循环,直至所以的key都插入指定位置。
  • 在插入key的过程中可能出现loop,因此存在一个最大循环次数。
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值