数据库--线性散列
散列算法(也叫摘要算法)

散列算法(也叫摘要算法)散列算法(也叫摘要算法)是一种将任意长度的数据映射为固定长度散列值的算法。
它的主要功能是将输入数据压缩成一个固定长度的散列值,以便在数据存储、比较和检索等操作中快速查找数据,而不需要保留原始数据。
散列算法被广泛应用于密码学、数据完整性验证、数字签名、内容寻址和数据结构等领域。
散列算法的基本原理是将输入数据进行数学转换,经过一系列的操作,输出一个固定长度的散列值。
不同的输入数据会产生不同的散列值,即使只有一个比特的差异。
这种特性使得散列算法适用于唯一标识大量数据的场景,例如在密码验证中,可以将用户输入的密码经过散列算法处理后,与数据库中存储的散列值进行比较,而不需要直接存储用户的原始密码,从而提高了安全性。
散列算法的设计目标包括: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——散列

数据结构与算法分析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),发⽣冲突的两个关键码称为该散列函数的同义词。
散列算法的应用场景

散列算法的应用场景
散列算法是一种将数据映射为固定长度的散列值的算法,常见的应用场景包括:
1. 数据验证和完整性校验:散列算法可以用于验证数据的完整性,比如通过计算文件的散列值并与预先计算的散列值进行比较,来确保文件没有被篡改。
2. 密码存储和验证:散列算法常用于密码存储,将用户的密码经过散列算法处理后存储在数据库中,以防止密码泄露。
当用户登录时,输入的密码经过同样的散列算法处理后,与数据库中的散列值进行比较。
3. 数据唯一性校验:散列算法可以用于确保数据的唯一性,比如在数据库中使用散列值作为主键或索引。
4. 身份验证和数字签名:散列算法可以用于生成和验证数字签名,以确保数据的完整性和身份的真实性。
5. 数据分片和负载均衡:散列算法可以用于将数据分散存储在多个节点上,以实现数据的负载均衡和高可用性。
6. 缓存和数据一致性:散列算法可以用于缓存系统中,根据数据的散列值将数据分散存储在不同的缓存节点上,以提高缓存的命中率,并确保数据的一致性。
7. 数据加密和解密:散列算法中的哈希函数可以用于数据的加
密和解密,常见的应用包括数字证书中的数字签名和加密算法中的消息摘要。
总之,散列算法在计算领域中有着广泛的应用,可以确保数据的完整性和安全性,提高数据的访问效率,并帮助实现分布式系统中的一致性和负载均衡。
散列函数种类

散列函数种类散列函数是一种将任意长度的输入数据映射为固定长度输出数据的函数。
散列函数的主要作用是将数据压缩成固定长度的哈希值,以便于在数据结构中进行快速查找和比较。
在实际应用中,不同的散列函数有不同的特点和适用场景。
本文将介绍几种常见的散列函数种类。
1. MD5散列函数MD5散列函数是一种广泛使用的散列函数,它可以将任意长度的输入数据压缩成128位的哈希值。
MD5散列函数具有高度的安全性和不可逆性,因此在密码存储和数字签名等领域得到了广泛应用。
但是,由于MD5散列函数存在碰撞攻击的漏洞,因此在一些安全性要求较高的场景中,不建议使用MD5散列函数。
2. SHA散列函数SHA散列函数是一种安全性更高的散列函数,它可以将任意长度的输入数据压缩成160位的哈希值。
SHA散列函数具有更高的安全性和更强的抗碰撞攻击能力,因此在数字签名、消息认证和数据完整性校验等领域得到了广泛应用。
SHA散列函数有多个版本,包括SHA-1、SHA-2和SHA-3等,其中SHA-2是目前应用最广泛的版本。
3. MurmurHash散列函数MurmurHash散列函数是一种快速的散列函数,它可以将任意长度的输入数据压缩成32位或64位的哈希值。
MurmurHash散列函数具有高度的随机性和低碰撞率,因此在哈希表、布隆过滤器和数据分片等领域得到了广泛应用。
MurmurHash散列函数的速度比MD5和SHA散列函数更快,因此在对速度要求较高的场景中,可以考虑使用MurmurHash散列函数。
4. CityHash散列函数CityHash散列函数是一种高效的散列函数,它可以将任意长度的输入数据压缩成64位或128位的哈希值。
CityHash散列函数具有高度的随机性和低碰撞率,同时还具有较好的分布性和可扩展性,因此在大规模数据处理和分布式系统中得到了广泛应用。
CityHash散列函数的速度比MurmurHash散列函数更快,因此在对速度要求极高的场景中,可以考虑使用CityHash散列函数。
国家计算机三级(数据库技术)67_真题-无答案

国家计算机三级(数据库技术)67(总分100,考试时间120分钟)选择题(每题1分,共60分)1. 下列哪些条目是数据库管理系统DBMS运行所依据的信息? I.数据完整性定义II.安全保密定义III.模式、内模式和外模式定义IV.数据库开放性定义V.用户界面形式定义A. 仅I、III和IVB. 仅I、II和IIIC. 仅II、III和VD. 都是2. 设计磁盘调度算法时应考虑的两个基本因素是______。
A. 公平性和高效性B. 独立性和可靠性C. 有效性和安全性D. 以上都不对3. 信息认证是信息安全的一个重要方面,下列哪一项不属于实施信息认证的方法?A. 身份识别B. 密钥管理C. 数字签名D. 消息认证4. 在关系代数中,自然连接的运算符号为______。
A. πB. ×C. σD. ∞5. 在现在的数据库系统开发中,常采用高级语言或第四代(4GL)语言进行开发,这是为了A. 代码的可重用性B. 系统的可维护性C. 降低开发和维护费用D. 用户界面的友好性6. 下列叙述错误的是( )。
A. SYBASE企业级数据库服务器支持Java、支持扩展标记语言、支持Microsoft的DTCB. SYBASE企业级数据库服务器支持1种类型的锁机制来保证系统的并发性和性能C. SYBASE在核心层实现了存储过程和触发器的可编程能力D. SYBASE支持服务器间的失败转移和客户端透明地自动失败转移等7. 如果要在关系R中插入一个元组,下面______元组不能插入。
A. (a2,b5,7)B. (a6,b5,3)C. (a7,b7,8)D. (a8,b4,1)8. 下面关于数据库系统基于日志的恢复的叙述中,哪一个是正确的?A. 利用更新日志记录中的改前值可以进行UNDO,利用更新日志记录中的改前值可以进行REDOB. 利用更新日志记录中的改前值可以进行UNDO,利用更新日志记录中的改后值可以进行REDOC. 利用更新日志记录中的改后值可以进行UNDO,利用更新日志记录中的改前值可以进行REDOD. 利用更新日志记录中的改后值可以进行UNDO,利用更新日志记录中的改后值可以进行REDO9. 设某散列表的当前状态如下:一共有20个位置,在第0、3、4、6、13、14、17、19的位置存放着各结点的值,则该散列表的负载因子约为______。
数据结构的散列与索引技术

数据结构的散列与索引技术散列与索引技术是数据结构中常用的两种方法,用于优化数据的存储和查找过程。
散列技术是通过哈希函数将数据映射到一个固定长度的数组中,而索引技术是通过建立索引表来加速数据检索。
本文将详细介绍散列与索引技术的原理、应用场景以及其在实际开发中的使用方法。
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树是一种常用的平衡多路查找树,广泛应用于数据库系统中的索引结构。
散列表
23
搜索不成功的平均搜索长度为:
ASLunsucc
线性探查方法容易产生“堆积”, 不同探查序 列的关键码占据可用的空桶, 为寻找某一关键 码需要经历不同的探查序列, 导致搜索时间增 加。
(2) 二次探查法 (quadratic probing)
8
k i 表示第
i 1
k i
2
计算出的 k 值越小,表明在该位 (第 k 位) 各种符号分布得越均匀。
9 4 2 1 4 8 9 4 1 2 6 9 9 4 0 5 2 7 9 4 1 6 3 0 9 4 1 8 0 5 9 4 1 5 5 8 9 4 2 0 4 7 9 4 0 0 0 1 ①②③④⑤⑥ ①位, 1 = 57.60 ②位, 2 = 57.60 ③位, 3 = 17.60 ④位, 4 = 5.60 ⑤位, 5 = 5.60 ⑥位, 6 = 5.60
0
(1)
1
(1)
2
(2)
3
4
Attlee Burke Broad
5
(6)
Blum
(3)
Ekers
(1)
6
(3)
7
(1)
8
9
20
Alton Ederly Hecht
需要搜索或加入一个表项时,首先使用散列 函数计算桶号作为初始地址: H0 = hash (key) 一旦发生冲突,在表中顺次向后寻找“下一 个”空桶 Hi 的递推公式为: Hi = (Hi-1+1) % m, i =1, 2, …, m-1 即用以下的线性探查序列在表中寻找“下一 个”空桶的桶号: H0+1, H0 +2, …, m-1, 0, 1, 2, …, H0-1 亦可写成如下的通项公式:
线性探测再散列
线性探测再散列https:///qq_19446965/article/details/102290770哈希表⼜称散列表。
哈希表存储的基本思想是:以数据表中的每个记录的关键字 k为⾃变量,通过⼀种函数H(k)计算出函数值。
把这个值解释为⼀块连续存储空间(即数组空间)的单元地址(即下标),将该记录存储到这个单元中。
在此称该函数H为哈希函数或散列函数。
按这种⽅法建⽴的表称为哈希表或散列表。
处理冲突的⽅法:开放寻址法:Hi=(H(key) + di) MOD m, i=1,2,…, k(k<=m-1),其中H(key)为散列函数,m为散列表长,di为增量序列,可有下列三种取法:1.di=1,2,3,…, m-1,称线性探测再散列;2.di=1^2, -1^2, 2^2,-2^2, 3^2, …, ±(k)^2,(k<=m/2)称⼆次探测再散列;3.di=伪随机数序列,称伪随机探测再散列。
再散列法:Hi=RHi(key), i=1,2,…,k. RHi均是不同的散列函数,即在同义词产⽣地址冲突时计算另⼀个散列函数地址,直到冲突不再发⽣,这种⽅法不易产⽣“聚集”,但增加了计算时间;链地址法(拉链法):将所有关键字为同义词的记录存储在同⼀线性链表中;设哈希表长为14,哈希函数是H(key)=key%11,表中已有数据的关键字为15,38,61,84共四个,现要将关键字为49的结点加到表中,⽤⼆次探测再散列法解决冲突,则放⼊的位置是( ) 【南京理⼯⼤学 2001 ⼀、15 (1.5分)】A.8 B.3 C.5 D.9答案为A,为什么我计算出来是D呢?我的计算步骤如下:15,38,61,84⽤哈希函数H(key)=key%11计算后得地址:4,5,6,749计算后为5,发⽣冲突.⽤⼆次探测再散列法解决冲突:1:(key+1^2)%11=(49+1)%11=6,仍然发⽣冲突.2:(key-1^2)%11=(49-1)%11=4,仍然发⽣冲突.3:(key+2^2)%11=(49+4)%11=9,不再发⽣冲突.得出结果为D。
数据结构课程设计----线性开型寻址散列查找、插入、删除
山东大学软件学院数据结构课程设计报告设计题目:线性开型寻址散列查找、插入、删除学号—姓名___________年级___________专业______班级__________学期11-12学年第二学期日期:2012年月曰一、需求描述1.1散列表的研究意义:一般的线性表、树中,记录在结构中的相对位置是随机的即和记录的关键字之间不存在确定的关系,在结构中查找记录时需进行一系列和关键字的比较。
这一类查找方法建立在“比较”的基础上,查找的效率与比较次数密切相关。
理想的情况是能直接找到需要的记录,因此必须在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字和结构中一个唯一的存储位置相对应。
因而查找时,只需根据这个对应关系f找到给定值K的像f(K)。
若结构中存在关键字和K相等的记录,则必定在f(K)的存储位置上,由此不需要进行比较便可直接取得所查记录。
在此,称这个对应关系f为哈希函数,按这个思想建立的表为散列表(哈希表)。
1.2散列表的定义散列(Hash ):根据记录的关键字的值来确定其存储地址。
建立散列表,要在记录的存储地址和它的关键字之间建立一个确定的对应关系。
散列函数(Hash function ):在记录的关键字和记录的存储地址之间建立的一种对应关系。
散列函数是一种映像,是从关键字空间到存储地址空间的映像,可表示为Add (ai)=H(keyi)其中:ai是表中的一个记录,add(ai) 是ai的存储地址,keyi是ai的关键字。
冲突(collisio n) :不同的关键字经过散列函数计算后得到相同的地址,也就是说key1工key2,但是H(key1)=H(key2) 的现象叫做冲突。
具有相同函数值的几个关键字就称为该散列函数的同义词。
一般情况下,冲突只能减少,并不可避免。
当冲突发生时,就要设定一种处理冲突的办法。
散列表(Hash table ):应用散列函数和处理冲突的办法将一组关键字映像到一个有限的地址集上,并以关键字在地址集上的像作为记录在地址中的存储地址。
数据结构中的散列算法详解
数据结构中的散列算法详解散列算法(Hashing Algorithm)是数据结构中一种常用的技术,可以提高数据的查找效率。
它将数据映射到一个固定大小的数组中,通过散列函数得到数组的索引位置,从而快速定位数据。
一、什么是散列算法散列算法是一种通过将输入数据映射到固定大小的数组中,从而实现快速访问的技术。
它利用散列函数将输入数据转换为一个整数值,并将该值与数组的大小取模,得到数组的索引位置。
将数据存储在对应索引的数组位置上,称为散列存储。
散列算法有很多种,常见的包括直接定址法、平方取中法、除留余数法等。
每一种散列算法都有自己的特点和适用场景。
二、散列函数的选择散列函数的选择非常重要,它直接关系到散列算法的效率和数据的分布。
一个好的散列函数应该具备以下特点:1. 易于计算:散列函数应该具备高效的计算性能,能够在短时间内完成散列计算。
2. 分布均匀:散列函数应能够将输入数据均匀地映射到散列表的各个位置上,避免出现数据聚集的情况。
3. 最小冲突:散列函数应该尽可能减少冲突,即不同的输入值映射到相同的索引位置的情况。
三、散列算法的实现散列算法的实现主要分为两个步骤:散列函数的设计和冲突处理。
散列函数的设计是散列算法的核心。
常见的散列函数设计方法有:直接定址法、除留余数法、平方取中法、伪随机数法等。
根据不同的数据特点和应用场景,选择合适的散列函数。
冲突处理是指当多个数据映射到相同的索引位置时,如何解决冲突的问题。
常见的冲突处理方法有:开放定址法、链地址法、再散列法等。
不同的冲突处理方法有不同的优势和适用场景,可以根据具体情况选择合适的方法。
四、散列算法的应用散列算法在实际应用中被广泛使用,主要用于提高数据的查找、插入和删除效率。
以下是散列算法的几个典型应用场景:1. 数据库索引:散列算法可用于构建数据库中的索引,加快数据的检索速度。
2. 缓存管理:散列算法可用于缓存的管理,快速找到对应的缓存数据。
3. 字典查找:散列算法可用于字典的查找,通过散列存储可以高效地实现快速查找。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
静态散列
桶的数目B固定,从来不改变的。 桶的数目 固定,从来不改变的。可以存在溢 固定 出桶。 出桶 静态散列表索引的缺点:当数据库数据增加, 静态散列表索引的缺点:当数据库数据增加, 初始的Bucket太小, 需要建立溢出块。如果 太小, 初始的 太小 需要建立溢出块。 一个索引中大部分的桶都有溢出块, 一个索引中大部分的桶都有溢出块,将影响查 找效率。 找效率。 因此引入了动态散列表索引:可扩展散列表, 因此引入了动态散列表索引:可扩展散列表, 线性散列表。 线性散列表。
希,它是根据哈希函数和冲突处理 定义:散列又叫哈希,它是根据哈希函数和冲突处理 哈希函数 的方法将一组关键字影射到一个有限的连续地址集上, 的方法将一组关键字影射到一个有限的连续地址集上, 并以关键字在地址集中的“ 作为存储位置。 并以关键字在地址集中的“象”作为存储位置。 优势:跟一般的查找方法(如线性表、树等)相比。它 优势:跟一般的查找方法(如线性表、树等)相比。 如线性表 相比 在定位过程中不用进行关键字的比较, 在定位过程中不用进行关键字的比较,查找效率不依 赖查找过程所进行的比较次数,记录存储位置 存储位置和 赖查找过程所进行的比较次数,记录存储位置和关键 值存在着一个确定的对应关系, 在着一个确定的对应关系 值存在着一个确定的对应关系,通过关键值就可以影 射到其存储地址。因此具有较高的查找效率。 射到其存储地址。因此具有较高的查找效率。
i=2 0000 00 n=3 r=6 0001 01 0101
10
0111 1111
1010
这样对吗?会不会出现什么问题? 这样对吗?会不会出现什么问题?
还记得我们前面讲的比率r/n吗 她将一直伴随我们, 还记得我们前面讲的比率 吗?她将一直伴随我们,最后 必须检查。 必须检查。
上题中r=6,n=3,r/n=2。该 , 上题中 。 散列表的记录与桶的比率已 超过1.7。 超过 。 因此, 因此,我们必须创建一个编 号为11的新桶 的新桶, 号为 的新桶,该桶碰巧是 新记录所需的桶。 新记录所需的桶。 分裂桶01中的四个记录 中的四个记录, 分裂桶 中的四个记录,散 列值为0001和0101的记录保 列值为 和 的记录保 散列值为0111和1111的 留,散列值为 和 的 记录存入新的第11号桶 号桶。 记录存入新的第 号桶。 现在01桶中只有两个值 桶中只有两个值, 现在 桶中只有两个值,所 以删除其溢出块。 以删除其溢出块。
动态散列
动态散列表允许B的改变, 动态散列表允许 的改变,使B近似于记录总 的改变 近似于记录总 数除以块中能容纳的记录数所得到的商; 数除以块中能容纳的记录数所得到的商;也就 是说,每个桶大约有一个存储块。 是说,每个桶大约有一个存储块。 动态散列表可以分为两种: 动态散列表可以分为两种:
可扩展散列 线性散列
线性散列表的插入
在进行插入时注意的细节问题: 在进行插入时注意的细节问题: 插入一个新记录时, 其中K是记录的键 是记录的键, 插入一个新记录时,我们计算 h ( K ) ,其中 是记录的键,并确 序列后面用做桶号的正确位数。并将记录放入该桶, 定 h ( K ) 序列后面用做桶号的正确位数。并将记录放入该桶,或 在桶号大于等于n时 放入把第一个二进制由1改为 改为0后确定 者(在桶号大于等于 时)放入把第一个二进制由 改为 后确定 的桶中。如果桶没有空间,那么我们创建一个溢出块, 的桶中。如果桶没有空间,那么我们创建一个溢出块,连接在那 个桶上,并将记录存入该溢出块中。 个桶上,并将记录存入该溢出块中。 每次插入,必须用当前的记录总数 于阀值 比较,若比率太大, 于阀值r/n比较 每次插入,必须用当前的记录总数r于阀值 比较,若比率太大, 就增加下一个桶到线性散列表中。 就增加下一个桶到线性散列表中。 一个重要的细节就是: 时的情况。这时参数i就递增 就递增1。 一个重要的细节就是:当n超过 2i 时的情况。这时参数 就递增 超过
i=1 n=2 r=3
0 1
0000 1010 1111
图1 线性散列表
现在我们来详细的分析下这个线性散列的大致结构,提出一 现在我们来详细的分析下这个线性散列的大致结构, 些注意事项帮助大家的学习。 些注意事项帮助大家的学习。
我们在图1中看到两个桶 每个桶包含一个存储块,标号分别为0 中看到两个桶, 一. 我们在图 中看到两个桶,每个桶包含一个存储块,标号分别为 的放入第0号桶中 和1。并且散列值的最后一位为 的放入第 号桶中,最后一位为 。并且散列值的最后一位为0的放入第 号桶中,最后一位为1 的放入第1号个桶中 号个桶中。 的放入第 号个桶中。 参数i(当前被使用的散列函数值的位数)、 (当前的桶数) 二. 参数 (当前被使用的散列函数值的位数)、 n(当前的桶数)和r 当前散列表中的记录总数), ),这些参数和数据共同构成了线性 (当前散列表中的记录总数),这些参数和数据共同构成了线性 散列表。 散列表。 比率r/n将受到限制 使一般的桶都只需要约一个磁盘存储块。 将受到限制, 三. 比率 将受到限制,使一般的桶都只需要约一个磁盘存储块。在 选择桶数n时 要注意的策略是使文件中的记录个数不超过1.7n, 选择桶数 时,要注意的策略是使文件中的记录个数不超过 , 即r<=1.7n。 。
线性散列表的基本组织结构
例题1. 例题
图1所示为一个 所示为一个n=2的线散 所示为一个 的线散 列表。 列表。并用散列值的一位 来确定记录所属的桶(i=1)。 来确定记录所属的桶 。 并假定散列函数产生四位, 并假定散列函数产生四位, 用将散列函数作用到记录 的查找键上所产生的值来 表示记录。 表示记录。
对其进行修正
将提高n,使其等于 ; 将提高 ,使其等于3; 并将i 改为2。 并将 改为 。 考虑把桶0和1改为桶 考虑把桶 和 改为桶00 改为桶 和01,并且增加下一个 , 桶到散列表中, 桶到散列表中,该桶编 号为10。 号为 。 分裂桶00,在分裂时, 分裂桶 ,在分裂时, 键值散列为0000的记录 键值散列为 的记录 保留在00桶中 桶中, 保留在 桶中,因为以 00结尾;键值散列为 结尾; 结尾 1010的记录存入桶 。 的记录存入桶10。 的记录存入桶 如图示: 如图示:
i=1 i=2 n=2 n=3 r=3 r=4
00 0
0000
1010 0101 1111 01 1 1111
10
1010
例题3 例题 我们现在增加一个键值散列 的纪录。 为0001的纪录。记录最后 的纪录 记录最后2 位是01, 的桶存在, 位是 ,且01的桶存在,那 的桶存在 么将记录放入该桶中。 么将记录放入该桶中。这时 问题出现了, 问题出现了,该桶块已经被 装满了,怎么办? 装满了,怎么办? 我们增加一个溢出块, 我们增加一个溢出块,将三 个纪录分配到这个桶中的两 个块中; 个块中;按散列键的值顺序 保存。 保存。 不要忘记检查纪录与桶的比 小于1.7, 率r/n。题中 小于 ,故 。题中5/3小于 我们不需要创建新桶。 我们不需要创建新桶。
线性散列表
正是由于可扩展散列表的一些缺点,我们引入了另一 正是由于可扩展散列表的一些缺点, 种策略:线性散列表,其中桶的增长较为缓慢。 种策略:线性散列表,其中桶的增长较为缓慢。在线 性散列中出现了一些新的要点: 性散列中出现了一些新的要点: 桶数n的选择总是使存储块的平均记录数保持与存储 桶数n的选择总是使存储块的平均记录数保持与存储 块所能容纳的记录总数成一个固定的比例, 块所能容纳的记录总数成一个固定的比例,如80%。 。 由于存储块并不是可以分裂,所以允许有溢出块, 由于存储块并不是可以分裂,所以允许有溢出块,尽 管每个桶的平均溢出块数远小于1。 管每个桶的平均溢出块数远小于
i=2 0000 00 n=3 r=5 0001 01 0101
10
1111
1010
例题4 例题 我们将考虑插入散列值为0111的 我们将考虑插入散列值为 的 记录。该记录最后两位11, 记录。该记录最后两位 ,但是 不存在, 桶11不存在,我们将记录存放在 不存在 哪个地方呢? 哪个地方呢? 我们回顾下前面注意事项的④ 我们回顾下前面注意事项的④ 由此可知, 由此可知,因为 (11)10=3,此时 , n<=m< 2i,我们把第一位 变为 , 我们把第一位1变为 我们把第一位 变为0, 即记录将被存在第01号桶中该记 即记录将被存在第 号桶中该记 录将被存入该桶的溢出块中? 录将被存入该桶的溢出块中?
可扩展散列表
它在简单的静态散列表结构上主要增加了: 它在简单的静态散列表结构上主要增加了
为桶引入了一个简接层, 为桶引入了一个简接层,即用一个指向块的指针数组来表 示桶,而不是用数据块本身组成的数组来表示桶。 示桶,而不是用数据块本身组成的数组来表示桶。 指针数组能增长,它的长度总是 的幂 的幂, 指针数组能增长,它的长度总是2的幂,因而数组每增长 一次,桶的数目就翻倍。 一次,桶的数目就翻倍。 并非每个桶都有一个数据块; 并非每个桶都有一个数据块;如果某些桶中的所有记录都 可以放在一个块中,那么这些桶可能共享一个块。 可以放在一个块中,那么这些桶可能共享一个块。
i=1 n=2 r=3
0 1
0000 1010 1111
0101
大家想想这样对吗? 大家想想这样对吗?
存在的问题: 存在的问题:
首先,现在 个桶里有四个记录 不能保证r<=1.7n, 个桶里有四个记录, 首先,现在2个桶里有四个记录,不能保证 , 超出比率,因此,我们必须把n提高到 提高到3。 超出比率,因此,我们必须把 提高到 。 其次, 调整为2, 其次,当n=3时, log 2 3 =2,应考虑把参数 调整为 , 时 ,应考虑把参数i调整为 即使用的散列函数值的位数为2。 即使用的散列函数值的位数为2。 最后,就是根据最后两位的值分对桶进行的分裂。 最后,就是根据最后两位的值分对桶进行的分裂。
线性散列表的插入
例题2 例题 我们考虑在例题1的散 我们考虑在例题 的散 列表中, 列表中,插入键值散列 的记录。 为0101的记录。因为其 的记录 最后一位为1, 最后一位为 ,记录应插 入到第二个桶中,即第1 入到第二个桶中,即第 号桶。桶中有空间, 号桶。桶中有空间,不 需要创建溢出块。 需要创建溢出块。