哈希表(hash_table)的原理
创始人
2024-01-27 05:46:51
0

一、hash_table的介绍

hash_table可提供对任何键值对的存取和删除操作。由于操作对象是键值对,所以hash table也可被视为一种字典结构(dictionary)。这种结构的用意在于提供常数时间的基本操作,就像stack或queue那样。乍听之下这几乎是不可能的任务,因为约束制条件如此之少,而随着元素个数增加,搜寻操作必定耗费更多时间。

二、问题

举个例子,这里有一些元素,都是16-bits且不带正负号的整数,范围0-65535,如何存储这些整数,并快速的查找呢?
我们用一个array就可以满足上述期望。 首先配置一个array A,它拥有65536个元素,索引号码0-65535,初值全部为0,如下图5-21,每一个元素值代表相应元素的出现次数。如果插入元素i,我们就执行A[i]++,如果删除元素i,我们就执行A[i]--,如果搜寻元素i,我们就检查A[i]是否为0。以上的每一个操作都是常数时间.这种解法的额外负担的是array的空间和初始化时间。

三、分析

这个解法存在两个问题:

第一,如果元素是32-bits,而非16-bits,我们所准备的array A的大小就必须是2的32次方=4GB,这就大得不切实际了。

第二,如果元素型态是字符串而非整数,将无法被拿来作为array的索引。

第二个问题不难解决。就像数值1234是由阿拉伯数字1,2,3,4构成一样,字符串"jhou”是由字符·j',‘j',h','o,'u'构成。那么,既然数值1234是1*103+2*102+3*101+4*10°,我们也可以把字符编码,每个字符以一个7-bits数值来表示(也就是ASCII编码),从而将字符串"jjhou·表现为:
'j*128+·j1*1283+"h'*1282+"0'*1281+·u'*1280。于是先前的array实现法就可适用于“元素型别为字符串”的情况了。但这并不实用,因为这会产生出非常巨大的数值."jhou·的案引值将是:
106*1284+106*1283+104*1282+111*1282+117*128°=28678174709。这太不切合实际了。更长的字符串会导致更大的索引值!

这就回归到第一个问题:array的大小。如何避免使用一个大得荒谬的array呢?办法之一就是使用某种映射函数,将大数映射为小数。负责将某一元素映射为一个“大小可接受之索引”,这样的函数称为hash function(散列函数)

例如,假设X是任意整数,Tablesize是array大小,则X%Tablesize会得到一个整数,范围在0-Tablesize-1之间,正好作为表格(也就是array)的索引,使用散列函数会带来一个问题:可能有不同的元素被映射到相同的位置(即有相同的索引)。这无法避免,因为元素个数大于array容量,这便是所谓的“碰撞(collision)”问题。解决碰撞问题的方法有许多种,包括线性探测(linear probing)、二次探测(quadratic probing)、开链(separate chaining)…等做法。

四、线性探测(linear probing)

当hash function计算出某个元素的插人位置,而该位置上的空间已不再可用时,我们应该怎么办?

最简单的办法依次向后探测,直到寻找到下一个空位置为止。(如果到达尾端,就绕到头部继续寻找)。只要表格(亦即array)足够大,总是能够找到一个安身立命的空间,但是要花多少时间就很难说了,进行元素搜寻操作时,道理也相同,如果hash function计算出来的位置上的元素值与我们的搜寻目标不符,就循序往下一一寻找,直到找到吻合者,或直到遇上空格元素。

 五、二次探测(quadratic probing)

二次探测法是指采用前后跳跃方式探测的方法,发生冲突时,向后 1 位探测,向前 1 位探测,向后 4 位探测,向前 4 位探测......以跳跃式探测,避免堆积。

二次探测的增量序列为 d=1,-1,4,-4,9,-9,16,-16,,,

若当前扫描的元素的地址已经有元素了,那么,当前元素就保存在该地址的后移偏量。

举个例子:有数组{47, 7, 29, 11, 16, 92, 22, 8, 3} ,接下来我们将所有元素对11取余,如下图所示。

 首先创建一个散列表,现在根据取余的值将元素放入散列表,如下图所示。

 其中47,7,11,16,92这些元素是根据取余的值直接放入散列表的。而29取余的值为7,7的位置上已经有元素了,那么我们放在7+1^2的位置上。3取余的值是3,3的位置上也已经有元素了,那么我们看3+1^2上也有元素,再看3-1^2的位置上没有元素,那么我们现在就放在这里。那么其他元素也是一样的道理。

 六、开链(separate chaining)

另一种与二次探测法分庭抗礼的,是所谓的开链(separate chaining)法。这种做法是在每一个表格元素中维护一个list。散列函数为我们分配某一个list,然后我们在那个list身上执行元素的插入,搜寻、删除等操作.虽然针对list而进行的搜寻只能是一种线性操作,但如果list够短,速度还是够快的

 

 

参考:

ixaC++ STL中哈希表 hash_map从头到尾详细介绍_yousss的博客-CSDN博客_std::hash_maph

线性探测-闭散列_小羊教你来编程的博客-CSDN博客_线性探测

开放地址法哈希实现——二次探测法_chengqiuming的博客-CSDN博客_二次探测法

【干货】C++哈希桶(开链法解决哈希冲突)类的实现_weixin_34206899的博客-CSDN博客

相关内容

热门资讯

小本生意加盟加盟合作,餐饮项目... 创业小项目 个人创业加盟创业小投资项目创业小项目小成本创业好项目有哪些一千元投资创业小项目适合创业的...
残疾人贷款怎么贷 残疾人贷款去... 营业执照20万无息贷款小微企业三年无息贷款只招残疾人的工作国家免息创业贷款15万残疾人创业贷款最高能...
残疾人创业无息贷款怎么申请?需... 营业执照20万无息贷款小微企业三年无息贷款只招残疾人的工作国家免息创业贷款15万残疾人创业贷款最高能...
创业可行性报告范文 可行性分析... 项目可行性报告可行性分析报告创业项目可行性分析什么是可行性报告项目可行性分析报告案例项目分析报告有哪...
永城用心代写可行性分析报告高水... 项目可行性报告可行性分析报告创业项目可行性分析什么是可行性报告项目可行性分析报告案例项目分析报告有哪...
招商创业 招商创业 招商创业板... 代理商加盟项目商机网创业小投资正规的招商加盟网站成都招商加盟网项目加盟网靠谱的创业项目平台加盟平台品...
一万元创业项目招商公司电话 成... 代理商加盟项目商机网创业小投资正规的招商加盟网站成都招商加盟网项目加盟网靠谱的创业项目平台加盟平台品...
70后大学生创业招商 加盟平台... 代理商加盟项目商机网创业小投资正规的招商加盟网站成都招商加盟网项目加盟网靠谱的创业项目平台加盟平台品...
5个适合白手起家 穷人自主创业... 2021年小本创业项目适合女人开的小店穷人创业一千元以下的不愁销路的小型加工厂农村生财之道有哪些在农...
2021年适合小本创业的最佳项... 什么项目适合创业投资小项目创业小型致富创业好项目2021年创业小项目创业小项目 个人创业加盟创业小投...