8.3.4 冲突处理技术之双散列法
- 格式:pdf
- 大小:350.08 KB
- 文档页数:9
散列算法(也叫摘要算法)散列算法(也叫摘要算法)是一种将任意长度的数据映射为固定长度散列值的算法。
它的主要功能是将输入数据压缩成一个固定长度的散列值,以便在数据存储、比较和检索等操作中快速查找数据,而不需要保留原始数据。
散列算法被广泛应用于密码学、数据完整性验证、数字签名、内容寻址和数据结构等领域。
散列算法的基本原理是将输入数据进行数学转换,经过一系列的操作,输出一个固定长度的散列值。
不同的输入数据会产生不同的散列值,即使只有一个比特的差异。
这种特性使得散列算法适用于唯一标识大量数据的场景,例如在密码验证中,可以将用户输入的密码经过散列算法处理后,与数据库中存储的散列值进行比较,而不需要直接存储用户的原始密码,从而提高了安全性。
散列算法的设计目标包括:1.处理速度快:散列算法需要高效地处理大量数据,以便在实时应用中实现快速的数据处理和查询。
2.均匀分布:散列算法应该能够将输入数据均匀分布到散列值空间中,以减少碰撞(即不同数据产生相同散列值的情况)的概率,提高散列算法的效果。
3.不可逆性:散列算法应是不可逆的,即不应该能够通过散列值反推原始数据。
这样可以保证数据的机密性,同时在密码学中也能够提供不可伪造的数字签名。
常用的散列算法包括:1. MD5(Message Digest Algorithm 5):MD5是一种常见的散列算法,可以将任意长度的数据转换为128位的散列值。
然而,由于其设计上的弱点,MD5已经不再被推荐在安全领域使用,因为存在碰撞攻击(即找到两个不同的输入数据,但散列值相同的情况)的风险。
2. SHA(Secure Hash Algorithm):SHA系列算法是美国国家标准技术研究所(NIST)设计的一系列散列算法。
包括SHA-1、SHA-256、SHA-512等不同长度的散列值。
SHA-1也已经不再被推荐在安全领域使用,而SHA-256和SHA-512仍然被广泛应用。
3. CRC(Cyclic Redundancy Check):CRC算法是一种用来检测和纠正数据传输错误的算法,常用于数据完整性验证。
数据结构与算法分析java——散列1. 散列的概念 散列⽅法的主要思想是根据结点的关键码值来确定其存储地址:以关键码值K为⾃变量,通过⼀定的函数关系h(K)(称为散列函数),计算出对应的函数值来,把这个值解释为结点的存储地址,将结点存⼊到此存储单元中。
检索时,⽤同样的⽅法计算地址,然后到相应的单元⾥去取要找的结点。
通过散列⽅法可以对结点进⾏快速检索。
散列(hash,也称“哈希”)是⼀种重要的存储⽅式,也是⼀种常见的检索⽅法。
按散列存储⽅式构造的存储结构称为散列表(hash table)。
散列表中的⼀个位置称为槽(slot)。
散列技术的核⼼是散列函数(hash function)。
对任意给定的动态查找表DL,如果选定了某个“理想的”散列函数h及相应的散列表HT,则对DL中的每个数据元素X。
函数值h(X.key)就是X在散列表HT中的存储位置。
插⼊(或建表)时数据元素X将被安置在该位置上,并且检索X时也到该位置上去查找。
由散列函数决定的存储位置称为散列地址。
因此,散列的核⼼就是:由散列函数决定关键码值(X.key)与散列地址h(X.key)之间的对应关系,通过这种关系来实现组织存储并进⾏检索。
⼀般情况下,散列表的存储空间是⼀个⼀维数组HT[M],散列地址是数组的下标。
设计散列⽅法的⽬标,就是设计某个散列函数h,0<=h( K ) < M;对于关键码值K,得到HT[i] = K。
在⼀般情况下,散列表的空间必须⽐结点的集合⼤,此时虽然浪费了⼀定的空间,但换取的是检索效率。
设散列表的空间⼤⼩为M,填⼊表中的结点数为N,则称为散列表的负载因⼦(load factor,也有⼈翻译为“装填因⼦”)。
建⽴散列表时,若关键码与散列地址是⼀对⼀的关系,则在检索时只需根据散列函数对给定值进⾏某种运算,即可得到待查结点的存储位置。
但是,散列函数可能对于不相等的关键码计算出相同的散列地址,我们称该现象为冲突(collision),发⽣冲突的两个关键码称为该散列函数的同义词。
二次探测再散列法
二次再散列法是指第一次散列产生哈希地址冲突,为了解决冲突,采用另外的散列函数或者对冲突结果进行处理的方法。
散列函数的选择有两条标准:简单和均匀。
简单指散列函数的计算简单快速;
均匀指对于关键字集合中的任一关键字,散列函数能以等概率将其映射到表空间的任何一个位置上。
也就是说,散列函数能将子集K随机均匀地分布在表的地址集{0,1,…,m-1}上,以使冲突最小化。
扩展资料:
设所有可能出现的关键字集合记为U(简称全集)。
实际发生(即实际存储)的关键字集合记为K(|K|比|U|小得多)。
散列方法是使用函数h将U映射到表T[0..m-1]的下标上(m=O(|U|))。
这样以U 中关键字为自变量,以h为函数的运算结果就是相应结点的存储地址。
从而达到在O(1)时间内就可完成查找。
其中:
①h:U→{0,1,2,…,m-1} ,通常称h为散列函数(Hash Function)。
散列函数h的作用是压缩待处理的下标范围,使待处理的|U|个值减少到m个值,从而降低空间开销。
②T为散列表(Hash Table)。
③h(Ki)(Ki∈U)是关键字为Ki结点存储地址(亦称散列值或散列地址)。
④将结点按其关键字的散列地址存储到散列表中的过程称为散列(Hashing)2、直接把被子晒在大桥的扶手上
1。
哈希表处理冲突的方法哈希表是一种常见的数据结构,用于实现快速查找和插入操作。
它通过将关键字映射到数组的特定位置来存储数据。
然而,当两个或多个关键字映射到同一个位置时,就会发生冲突。
为了解决冲突,哈希表采用了多种方法。
1. 链地址法(Chaining):在哈希表中的每个位置上维护一个链表或链表数组。
如果发生冲突,新的数据将被添加到链表的末尾。
这种方法可以处理任意数量的冲突,但需要额外的空间来存储链表。
2. 开放地址法(Open Addressing):在哈希表中的每个位置上存储一个数据,并通过探测序列来处理冲突。
探测序列是一个确定的规则,用于寻找下一个可用的位置。
常见的探测方法包括线性探测(Linear Probing),二次探测(Quadratic Probing)和双重散列(Double Hashing)。
这种方法不需要额外的存储空间,但可能会导致聚集现象,即连续的冲突会增加查找的时间复杂度。
3. 再哈希法(Rehashing):当发生冲突时,重新计算关键字的哈希值,并将数据存储在计算得到的新位置上。
这种方法需要额外的存储空间来保存原始数据,但可以避免聚集现象,并减少冲突的概率。
4. 建立公共溢出区(Primary Clustering):将哈希表分为两个区域,一个区域用于存储主要数据,另一个区域用于存储冲突的数据。
当发生冲突时,将数据存储在冲突区域中。
这种方法可以减少聚集现象的发生,但需要额外的存储空间来存储冲突数据。
5. 完全散列(Perfect Hashing):在构建哈希表时,通过一系列算法和数据预处理,使得每个关键字都映射到唯一的位置,从而避免冲突。
这种方法需要较高的计算成本和空间消耗,但可以实现最佳的查找和插入性能。
以上所述的方法都是常见的哈希表处理冲突的方式。
在选择合适的方法时,需要考虑数据的特点、内存限制和性能需求等因素。
数据结构的散列与索引技术散列与索引技术是数据结构中常用的两种方法,用于优化数据的存储和查找过程。
散列技术是通过哈希函数将数据映射到一个固定长度的数组中,而索引技术是通过建立索引表来加速数据检索。
本文将详细介绍散列与索引技术的原理、应用场景以及其在实际开发中的使用方法。
1. 散列技术散列技术是一种将数据映射到哈希表的方法,通过哈希函数将关键字转化为一个数组中的地址,从而实现对数据的快速访问。
散列技术的核心是哈希函数的设计,一个好的哈希函数能够使数据均匀地散列到哈希表中,尽量避免碰撞(即不同的关键字映射到了同一个地址)的发生。
1.1 哈希函数的设计原则一个好的哈希函数应该满足以下几个原则:1.1.1 均匀性原则:哈希函数应能够将数据均匀地散列到哈希表中,避免碰撞的发生。
1.1.2 简单性原则:哈希函数的计算应简单快速,以提高散列效率。
1.1.3 一致性原则:对于相同的关键字,哈希函数应始终返回相同的散列地址。
1.1.4 随机性原则:哈希函数的输出应具有随机性,避免出现特定模式的散列结果。
1.2 常见的散列方法常见的散列方法包括直接定址法、除留余数法、平方取中法等。
除留余数法是最常用的散列方法之一,其思想是通过对关键字取余数来获取散列地址。
例如,对于一个哈希表的大小为n的散列表,哈希函数可以定义为:h(key) = key % n。
2. 索引技术索引技术是建立索引表来加速数据的检索过程。
索引表通常由键值和指向数据的指针组成,可以根据键值快速地查找到对应的数据记录。
索引技术的核心是索引表的设计,索引表的结构应具有高效的查找和更新操作。
2.1 主索引与辅助索引主索引是基于主关键字建立的索引表,通过主索引可以直接找到对应的数据记录。
辅助索引是基于其他非主关键字建立的索引表,通过辅助索引可以加速对数据的查询和过滤操作。
主索引和辅助索引的组合可以构建复杂的索引结构,以满足不同的查找需求。
2.2 B树索引B树是一种常用的平衡多路查找树,广泛应用于数据库系统中的索引结构。
哈希表处理冲突的⼏种⽅式1、链地址法指把所有的冲突关键字存储在⼀个线性链表中,这个链表由其散列地址唯⼀标识。
2、开放定址法开放地址法通常需要有三种⽅法:线性探测、⼆次探测、再哈希法。
线性探测线性探测⽅法就是线性探测空⽩单元。
当数据通过哈希函数计算应该放在700这个位置,但是700这个位置已经有数据了,那么接下来就应该查看701位置是否空闲,再查看702位置,依次类推。
当哈希表越来越满时聚集越来越严重,这导致产⽣⾮常长的探测长度,后续的数据插⼊将会⾮常费时。
线性探测就是使⽤算术取余的⽅法计算余数,当产⽣冲突时就通过线性递增的⽅法进⾏探测,⼀直到数组的位置为空,插⼊数据项即可。
⼆次探测⼆次探测是过程是x+1,x+4,x+9,以此类推。
⼆次探测的步数是原始位置相隔的步数的平⽅。
⼆次探测可以消除在线性探测中产⽣的聚集问题,但是⼆次探测还是会产⽣⼀种更明确更细的聚集。
⼆次聚集的产⽣是在⼆次探测的基础上产⽣的现象。
例如N个数据经hash函数计算后都映射到到数组下标10,探测第⼆个数字需要以⼀步长,第三个数字需要以4步长为单位,第四个数字则需要以九为步长。
好在⼆次探测并不常⽤,解决聚集问题还是有⼀种更好的办法:再哈希法。
再哈希法再哈希是把关键字⽤不同的哈希函数再做⼀遍哈希化,⽤这个结果作为步长,对指定的关键字,探测的步长是不变的,可以说不同的关键字可以使⽤不同的步长,并且步长可以控制。
⼀般来说,再哈希函数可以采⽤以下这种:stepSize=constant-(key%constant);3、再散列法当发⽣冲突时,利⽤另⼀个哈希函数再次计算⼀个地址。
直到冲突不再发⽣。
4、建⽴⼀个公共溢出区⼀旦由哈希函数得到的地址冲突,就都填⼊溢出表。
以下是列举收集来的三个题目,三个题目是同一个意思,一,利用线性探测法构造散列表(用除余法来得出散列地址,用开放地址法解决同义词问题)题目:已知一组关键字为(26,36,41,38,44,15,68,12,06,51),用除余法构造散列函数,用线性探查法解决冲突构造这组关键字的散列表。
解答:为了减少冲突,通常令装填因子α<l。
这里关键字个数n=10,不妨取m=13,此时α≈0.77,散列表为T[0..12],散列函数为:h(key)=key%13。
由除余法的散列函数计算出的上述关键字序列的散列地址为(0,10,2,12,5,2,3,12,6,12)。
前5个关键字插入时,其相应的地址均为开放地址,故将它们直接插入T[0],T[10),T[2],T[12]和T[5]中。
当插入第6个关键字15时,其散列地址2(即h(15)=15%13=2)已被关键字41(15和41互为同义词)占用。
故探查h1=(2+1)%13=3,此地址开放,所以将15放入T[3]中。
当插入第7个关键字68时,其散列地址3已被非同义词15先占用,故将其插入到T[4]中。
当插入第8个关键字12时,散列地址12已被同义词38占用,故探查hl=(12+1)%13=0,而T[0]亦被26占用,再探查h2=(12+2)%13=1,此地址开放,可将12插入其中。
类似地,第9个关键字06直接插入T[6]中;而最后一个关键字51插人时,因探查的地址12,0,1,…,6均非空,故51插入T[7]中。
二、题目:已知一个线性表(38,25,74,63,52,48),假定采用h(k)=k%6计算散列地址进行散列存储,若用线性探测的开放定址法处理冲突,则在该散列表上进行查找的平均查找长度为()。
A. 1.5B. 1.7C. 2D. 2.32、解题过程:(1)计算h(k):38%6 = 2 25%6 = 1 74%6 = 2 63%6 = 3 52%6 = 4 48%6 = 0(2)定址:把不冲突的和冲突的全部列出来即可地址:0 1 2 3 4 51、线性表第1个元素(38):38(第1 次不冲突)2、线性表第2个元素(25):25(第1次不冲突)3、线性表第3个元素(74):74(第1 次冲突,地址+ 1)4、线性表第3个元素(74):74(第2 次不冲突)5、线性表第4个元素(63):63(第1 次冲突,地址+ 1)6、线性表第4个元素(63):63(第2 次不冲突)7、线性表第5个元素(52):52(第1 次冲突,地址+ 1)8、线性表第5个元素(52):52(第2 次不冲突)9、线性表第6个元素(48):48(第1次不冲突)经过上述定址过程,线性表中的各个元素都有了唯一的地址。
散列表冲突处理方案散列表(Hash Table)是一种重要的数据结构,它能够快速地进行插入、查找和删除等操作。
然而,在实际应用中,冲突(Collision)是散列表中常见的问题之一。
本文将介绍散列表冲突处理的几种常见方案,以及它们的优缺点。
一、开放定址法开放定址法是一种解决冲突的常见方法。
其原理是,当发生冲突时,通过一定的探测序列找到下一个可用的空槽,将待插入的元素放入该槽内。
常用的探测序列有线性探测、二次探测以及双重散列等。
1. 线性探测线性探测是最简单的开放定址法策略。
当发生冲突时,直接往后查找下一个空槽,并将待插入元素放入该槽内。
即使数组中只有少数位置被占用,线性探测也可能导致长时间的查找。
此外,线性探测容易产生一次聚集(Primary Clustering)现象,即冲突后的元素倾向于聚集在一起,进一步影响散列表的性能。
2. 二次探测二次探测对线性探测进行了改进。
当发生冲突时,根据一个二次探测序列进行查找下一个空槽,并将待插入元素放入该槽内。
二次探测的探测序列可以是平方探测、斐波那契探测等。
相比线性探测,二次探测能够减少聚集现象,但仍然存在聚集的问题。
3. 双重散列双重散列是一种更为高效的开放定址法策略。
当发生冲突时,通过计算另一个散列函数的值,并将其与原始散列值相加,得到下一个空槽的位置。
双重散列能够更好地解决聚集问题,提高散列表的性能。
二、链表法链表法是另一种常见的散列表冲突处理方案。
基本思想是,将散列得到的相同索引值的元素存储在同一个链表中。
当插入元素时,只需要将其插入到对应索引位置的链表尾部即可。
链表法对于散列冲突的处理效果较好,但在插入和查找操作上需要额外的链表遍历开销。
三、再散列法再散列法是一种结合链表法和开放定址法的冲突处理方法。
当发生冲突时,使用一个新的散列函数对待插入的元素进行再散列,并将其放入新的散列位置。
再散列法能够在一定程度上减少冲突的概率,提高散列表的性能。
综上所述,散列表冲突处理的方案有开放定址法、链表法以及再散列法等。
数据结构中的散列算法详解散列算法(Hashing Algorithm)是数据结构中一种常用的技术,可以提高数据的查找效率。
它将数据映射到一个固定大小的数组中,通过散列函数得到数组的索引位置,从而快速定位数据。
一、什么是散列算法散列算法是一种通过将输入数据映射到固定大小的数组中,从而实现快速访问的技术。
它利用散列函数将输入数据转换为一个整数值,并将该值与数组的大小取模,得到数组的索引位置。
将数据存储在对应索引的数组位置上,称为散列存储。
散列算法有很多种,常见的包括直接定址法、平方取中法、除留余数法等。
每一种散列算法都有自己的特点和适用场景。
二、散列函数的选择散列函数的选择非常重要,它直接关系到散列算法的效率和数据的分布。
一个好的散列函数应该具备以下特点:1. 易于计算:散列函数应该具备高效的计算性能,能够在短时间内完成散列计算。
2. 分布均匀:散列函数应能够将输入数据均匀地映射到散列表的各个位置上,避免出现数据聚集的情况。
3. 最小冲突:散列函数应该尽可能减少冲突,即不同的输入值映射到相同的索引位置的情况。
三、散列算法的实现散列算法的实现主要分为两个步骤:散列函数的设计和冲突处理。
散列函数的设计是散列算法的核心。
常见的散列函数设计方法有:直接定址法、除留余数法、平方取中法、伪随机数法等。
根据不同的数据特点和应用场景,选择合适的散列函数。
冲突处理是指当多个数据映射到相同的索引位置时,如何解决冲突的问题。
常见的冲突处理方法有:开放定址法、链地址法、再散列法等。
不同的冲突处理方法有不同的优势和适用场景,可以根据具体情况选择合适的方法。
四、散列算法的应用散列算法在实际应用中被广泛使用,主要用于提高数据的查找、插入和删除效率。
以下是散列算法的几个典型应用场景:1. 数据库索引:散列算法可用于构建数据库中的索引,加快数据的检索速度。
2. 缓存管理:散列算法可用于缓存的管理,快速找到对应的缓存数据。
3. 字典查找:散列算法可用于字典的查找,通过散列存储可以高效地实现快速查找。
散列冲突解决的⽅式⼀、散列思想散列表的英⽂叫Hash Table,也叫哈希表或者Hash表。
散列表⽤的是数组⽀持按照下标随机访问数据的特性,所以散列表其实就是数组的⼀种扩展,由数组演化⽽来。
可以说,如果没有数组,就没有散列表。
散列表时间复杂度是O(1)的特性。
我们通过散列函数把元素的键值映射为下标,然后将数据存储在数组中对应下标的位置。
当我们按照键值查询元素时,我们⽤同样的散列函数,将键值转化为数组下标,从对应的数组下标的位置取数据。
⼆、散列函数散列函数在散列表中起着⾮常关键的作⽤。
散列函数,顾名思义,它是⼀个函数。
可以把它定义成hash(key),其中key表⽰元素的键值,hash(key)的值表⽰经过散列函数计算得到的散列值。
如何改造散列函数?散列函数设计的基本要求:1、散列函数计算得到的散列值是⼀个⾮负整数;2、如果key1=key2,那hash(key1)==hash(key2);3、如果key1≠key2,那hash(key1)≠hash(key2)解释⼀下上述三点:其中,第⼀点理解起来应该没有任何问题。
因为数组下标是从0开始的,所以散列函数⽣成的散列值也要是⾮负整数。
第⼆点也很好理解。
相同的key,经过散列函数得到的散列值也应该是相同的。
第三点看起来合情合理,但是在真实的情况下,要想找到⼀个不同key对应的散列值都不⼀样的散列函数,⼏乎是不可能的。
即使像业界著名的MD5、SHA、CRC等哈希算法,也⽆法完全避免这种散列冲突。
⽽且,因为数组的存储空间有限,也会加⼤散列冲突的概率。
三、散列冲突再好的散列函数也⽆法避免散列冲突。
如何解决散列冲突呢?常⽤的散列冲突解决⽅法有两类:开放寻址法(open addressing)和链表法(chaining)1、开放寻址法开放寻址法的核⼼思想是,如果出现了散列冲突,我们就重新探测⼀个空闲位置,将其插⼊。
那如何重新探测新的位置呢?先讲⼀个⽐较简单的探测⽅法,线性探测(Linear Probing)。
事务处理中的数据冲突与事务冲突解决在数据处理的过程中,经常会遇到数据冲突的情况。
数据冲突指的是多个事务同时对相同的数据进行读写操作,导致数据的一致性受到破坏。
为了解决这个问题,需要引入一些技术手段来处理数据冲突,保证事务的正确执行。
一、数据冲突的原因及表现形式数据冲突的原因主要有以下几个方面:1. 并发操作:多个事务同时对数据库进行读写操作,容易导致数据冲突。
2. 不一致的读写顺序:当某个事务在读取数据的同时,另一个事务对同一份数据进行修改,会导致数据的不一致。
数据冲突的表现形式主要有以下几种:1. 丢失修改:当两个事务同时对同一份数据进行修改,其中一个事务的修改可能被另一个事务覆盖掉,导致修改丢失。
2. 读脏数据:当一个事务在读取数据的同时,另一个事务对同一份数据进行修改,读取到的数据可能是“脏”的,即不符合实际的数据。
二、解决数据冲突的技术手段为了解决数据冲突问题,需要使用一些技术手段来保证事务的正确执行。
以下是一些常用的数据冲突解决技术。
1. 锁机制:锁机制是一种常用的解决数据冲突的手段。
事务在对数据进行读写操作之前,需要先获得相应的锁。
通过锁的方式,可以保证同一时间只有一个事务对数据进行操作,从而避免数据的冲突。
2. 事务隔离级别:事务隔离级别是控制多个事务并发执行时的隔离程度。
常用的事务隔离级别有读未提交、读已提交、可重复读和串行化。
不同的隔离级别可以通过锁机制或多版本并发控制(MVCC)来实现,以解决数据冲突问题。
3. 悲观并发控制:悲观并发控制是一种基于锁的机制,它假设在整个事务执行过程中,会发生数据冲突。
因此,在事务执行期间,会对数据进行加锁,以防止其他事务对其进行修改。
这种机制可以有效地避免数据冲突,但是会增加系统开销。
4. 乐观并发控制:乐观并发控制是一种基于版本的机制,它假设在整个事务执行过程中,不会发生数据冲突。
因此,在事务提交时,会检查数据的版本号,如果发现版本号不一致,则说明数据已被其他事务修改,此时需要回滚当前事务并重新执行。
解决哈希冲突的三种⽅法(拉链法、开放地址法、再散列法)解决哈希冲突的三种⽅法(拉链法、开放地址法、再散列法) - ⼩猛同学的博客 - CSDN博客https:///qq_32595453/article/details/806606762018年06⽉12⽇ 10:16:57上篇博客我们说到了,什么是哈希冲突,其实就是再采⽤哈希函数对输⼊域进⾏映射到哈希表的时候,因为哈希表的位桶的数⽬远⼩于输⼊域的关键字的个数,所以,对于输⼊域的关键字来说,很可能会产⽣这样⼀种情况,也就是,⼀个关键字会映射到同⼀个位桶中的情况,这种情况就就叫做哈希冲突,解决哈希冲突的有三种⽅案,⼀种叫做拉链法(也叫作链接法、链地址法,⼀个意思),另外三种分别为开发地址法和再散列法。
⼀、拉链法上篇博⽂我们举的例⼦,HashMap,HashSet其实都是采⽤的拉链法来解决哈希冲突的,就是在每个位桶实现的时候,我们采⽤链表(jdk1.8之后采⽤链表+红⿊树)的数据结构来去存取发⽣哈希冲突的输⼊域的关键字(也就是被哈希函数映射到同⼀个位桶上的关键字)。
⾸先来看使⽤拉链法解决哈希冲突的⼏个操作:①插⼊操作:在发⽣哈希冲突的时候,我们输⼊域的关键字去映射到位桶(实际上是实现位桶的这个数据结构,链表或者红⿊树)中去的时候,我们先检查带插⼊元素x是否出现在表中,很明显,这个查找所⽤的次数不会超过装载因⼦(n/m:n为输⼊域的关键字个数,m为位桶的数⽬),它是个常数,所以插⼊操作的最坏时间复杂度为O(1)的。
②查询操作:和①⼀样,在发⽣哈希冲突的时候,我们去检索的时间复杂度不会超过装载因⼦,也就是检索数据的时间复杂度也是O(1)的③删除操作:如果在拉链法中我们想要使⽤链表这种数据结构来实现位桶,那么这个链表⼀定是双向链表,因为在删除⼀个元素x的时候,需要更改x的前驱元素的next指针的属性,把x从链表中删除。
这个操作的时间复杂度也是O(1)的。
散列表
Content 散列技术简介1
常见散列函数2
冲突处理技术3
PART THREE
D 双散列法利用两个散列函数,改善“二次聚集”现象
具备两个散列函数h
1和h
2
,探查序列为:
h1(key), (h1(key)+ h2(key))%M, (h1(key)+ 2h2(key))%M, …,
(h1(key)+ i*h2(key))%M,…
h2的作用:
•对h1散列值产生一个固定增量,实现跳跃式探查
•改善“二次聚集”,对两个散列函数都为同义词的关键字很少
具备两个散列函数h
1和h
2
,探查序列为:
h1(key), (h1(key)+ h2(key))%M, (h1(key)+ 2h2(key))%M, …,
(h1(key)+ i*h2(key))%M,…
h2(key)应该是小于M且与M互质的整数,以保证探测序列能够最多经过M次探测(i=0, 1, …, M-1)即可遍历表中所有地址
若M为素数,则可取h
2
(key)=key % (M-2)+1
(h 1(key)+ i*h 2(key))%M, i =0, 1, …, M -101234567891024801565插入58h 1(key)=58%11=3
h 2(key)=58%9+1=5
(h 1(key)+h 2(key))%11=(3+5)%11=8
58h 1(key) = key % 11 h 2(key) = key % 9 + 1
(h 1(key)+ i*h 2(key))%M, i =0, 1, …, M -101234567891024801565
插入35h 1(key)=35%11=2
h 2(key)=35%9+1=9(h 1(key)+h 2(key))%11=(2+9)%11=0
58h 1(key) = key % 11 h 2(key) = key % 9 + 1
35
常见错误
⚫将h
2散列值列入探查序列
(h1(key)+ i*h2(key))%M, i=0, 1, …, M-1
END。