哈 希 常 见 算 法 及 原 理
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Python算法系列-哈希算法
哈希算法一、常见数据查找算法简介二、什么是哈希三、实例:两个数字的和1.问题描述2.双指针办法解决3.哈希算法求解四、总结哈希算法又称散列函数算法,是一种查找算法。
就是把一些复杂的数据通过某种映射关系。
映射成更容易查找的方式,但这种映射关系可能会发生多个关键字映射到同一地址的现象,我们称之为冲突。
在这种情况下,我们需要对关键字进行二次或更多次处理。
出这种情况外,哈希算法可以实现在常数时间内存储和查找这些关键字。
一、常见数据查找算法简介
常见的数据查找算法:
顺序查找:是最简单的查找方法。
需要对数据集中的逐个匹配。
所以效率相对较低,不太适合大量数据的查找问题。
二分法查找:效率很高,但是要求数据必须有序。
面对数据排序通常需要更多的时间。
深度优先和广度优先算法:对于大量的数据查找问题,效率并不高。
这个我们后面专门讲解。
阿希查找算法:查找速度快,查询插入,删除操作简单等原因获得广泛的应用。
二、什么是哈希
哈希查找的原理:根据数量预先设一个长度为M的数组。
使用一个哈希函数F并以数据的关键字作为自变量得到唯一的返回值,返回值的范围
是0~M-1。
这样就可以利用哈希函数F将数据元素映射到一个数组的某一位下标,并把数据存放在对应位置,查找时利用哈希函数F计算,该数据应存放在哪里,在相应的存储位置取出查找的数据。
这里就有一个问题:
关键字的取值在一个很大的范围,数据在通过哈希函数进行映射时。
很难找到一个哈希函数,使得这些关键字都能映射到唯一的值。
就会出现多个关键字映射到同一个值的现象,这种现象我们称之为冲突。
哈西算法冲突的解决方案有很多:链地址法,二次再散列法。
线性探测再散列建立一个公共溢出区
注意:链地址法本质是数组+链表的数据结构
链地址法存储数据过程:
首先建立一个数组哈希存储所有链表的头指针。
由数组的关键字key 通过对应的哈希函数计算出哈希地址。
找到相应的桶号之后,建立新的节点存储该数据。
并把节点放到桶内的链表的最后面或者最前面。
链地址法查找数据:由数据关键字通过哈希。
函数计算关键字对应的哈希地址之后顺序比较同类不节点。
是否与所查到的关键字一样,直到找到数据为止,如果全部节点都不和关键字一样,则书名哈系表里没有该数据。
解决了哈希函数的冲突。
用链地址法构造的散列表插入和删除节点操作易于实现,所以构造链表的时间开销很低。
但是指针需要开辟额外的地址空间,当数据量很大时会扩大哈希表规模,内存空间要求较大。
三、实例:两个数字的和
1.问题描述
要求在给定的一些数字中找出两个数,使得它们的和为嗯,前提是这些数据中保证有答案,并且只有一个答案。
例如给3、4、5、7、10。
从中选出两个数字使它们的和为11,可以选择4和7。
2.双指针办法解决
def twosum(nums,target):
res = [] #存放结果编号
newnumber = nums [:] #将数据深拷贝一份
newnumber.sort() #对拷贝结果排序
left = 0 #定义左指针
right = len(newnumber) -1 # 定义右指针
while left right:
if newnumber[left] + newnumber[right] ==target: #在原始数组中第一个元组寻找原始下标
for i in range(0,len(nums)):
if nums[i] == newnumber[left]:
res.append(i) #将下标结果接入集
for i in range(len(nums) - 1 , -1 , -1):#向回找,寻找第二个元组
if nums[i] == newnumber[right]:
res.append(i)
res.sort()
elif newnumber[left] +newnumber[right] target:
left = left +1
right = right -1
return (res[0] + 1 ,res[1] + 1 )
s =twosum([3,4,5,7,10],11)
print('下标是:',s)
双指针解决方案:
第一步:对数据进行排序
第二步:移动指针寻找答案
第三步:发现答案去原始数据中查找这两个元素的位置
显然第一步和第三步很浪费时间,我们使用哈希算法,规避排序问题,直接查找数据和下标的对应关系。
3.哈希算法求解
def twosum(nums,target):
这个函数只能解决两个数字和,且答案有且仅有一个的情况
dict = {}
for i in range(len(nums)):
m = nums[i]
if target - m in dict:#判定target - m 是否在字典中
return (dict[target-m]+1,i +1) #存在返回连个数的下标
dict[m] = i #若不存在则记录键值对的值
s =twosum([3,4,5,7,10],11)
print('下标是:',s)
字典使用dict[key] = value 来记录键值对的关系
四、总结
使用哈希算法解决查找问题,不仅效率高,而且代码更少更容易理解,我们使用哈希算法解决查找问题将事半功倍,
这个示例问题是一个经典问题,还有后续一些问题,三个数、四个数求和问题。
上面介绍的方法解决的都是以图搜图的问题,在其他的一些应用方面,深度哈希算法也有用武之地。
下面我举两个例子进行说明。
其中Hash是一个从字符串到正整数的哈希映射函数。
这样,如果我们将Memcached Server分别编号为0、1、2,那么就可以根据上式和key 计算出服务器编号h,然后去访问。
为了更好的实现负载均衡,我们需要引入虚拟节点的概念,就是将一个节点虚拟化为多个节点将其中的请求落在N1上,入下图所示
this.hashtable = newHashTable;
工作量证明需要有一个目标值。
比特币工作量证明的目标值(target)的计算公式如下:
阿希查找算法:查找速度快,查询插入,删除操作简单等原因获得广泛的应用。
@OutputTimeUnit(TimeUnit.MICROSECONDS)
根据ServerIPIndex[QQNUM%n]得到请求的服务器,这种方法很方便将
①用开放定址法建立散列表时,建表前须将表中所有单元(更严格地
说,是指单元中存储的关键字)置空。
for(int i = 0; i 《 str.length(); i++)。