数据库--线性散列
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
线性散列表
用来做桶数组项序号二进制位数是[ 用来做桶数组项序号二进制位数是 log 2 n ],其中 ,其中n 是当前的桶数。 是当前的桶数。这些位总是从散列函数得到的位序 列的右(低位)端开始取。 列的右(低位)端开始取。 假定散列函数值的i位正在用来给桶数组项编号, 假定散列函数值的 位正在用来给桶数组项编号,且 有一个键值为K的记录想要插入到编为 有一个键值为 的记录想要插入到编为 a1 a 2 ...ai 的桶 中;即 a1a2 ...ai 是 h ( K ) 的后i位。那么,把 a1a2 ...ai 当 位 那么, 作二进制整数,设它为m。如果m<n,那么编号为 作二进制整数,设它为 。如果 , m的桶存在并把记录存入该桶中。如果≤ m<i ,那 的桶存在并把记录存入该桶中。 的桶存在并把记录存入该桶中 如果n 2 那 么桶m还不存在 因此我们把记录存入桶m 还不存在, 么桶 还不存在,因此我们把记录存入桶− 2i−1 ,就 时对应的桶。 是当我们把1 (它肯定是 )改为 时对应的桶。 a 它肯定是1)改为0时对应的桶
静态散列
桶的数目B固定,从来不改变的。 桶的数目 固定,从来不改变的。可以存在溢 固定 出桶。 出桶 静态散列表索引的缺点:当数据库数据增加, 静态散列表索引的缺点:当数据库数据增加, 初始的Bucket太小, 需要建立溢出块。如果 太小, 初始的 太小 需要建立溢出块。 一个索引中大部分的桶都有溢出块, 一个索引中大部分的桶都有溢出块,将影响查 找效率。 找效率。 因此引入了动态散列表索引:可扩展散列表, 因此引入了动态散列表索引:可扩展散列表, 线性散列表。 线性散列表。
线性散列表的插入
在进行插入时注意的细节问题: 在进行插入时注意的细节问题: 插入一个新记录时, 其中K是记录的键 是记录的键, 插入一个新记录时,我们计算 h ( K ) ,其中 是记录的键,并确 序列后面用做桶号的正确位数。并将记录放入该桶, 定 h ( K ) 序列后面用做桶号的正确位数。并将记录放入该桶,或 在桶号大于等于n时 放入把第一个二进制由1改为 改为0后确定 者(在桶号大于等于 时)放入把第一个二进制由 改为 后确定 的桶中。如果桶没有空间,那么我们创建一个溢出块, 的桶中。如果桶没有空间,那么我们创建一个溢出块,连接在那 个桶上,并将记录存入该溢出块中。 个桶上,并将记录存入该溢出块中。 每次插入,必须用当前的记录总数 于阀值 比较,若比率太大, 于阀值r/n比较 每次插入,必须用当前的记录总数r于阀值 比较,若比率太大, 就增加下一个桶到线性散列表中。 就增加下一个桶到线性散列表中。 一个重要的细节就是: 时的情况。这时参数i就递增 就递增1。 一个重要的细节就是:当n超过 2i 时的情况。这时参数 就递增 超过
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桶中只有两个值 桶中只有两个值, 现在 桶中只有两个值,所 以删除其溢出块。 以删除其溢出块。
线性散列
散列表
定义:散列又叫哈希,它是根据哈希函数和冲突处理 定义:散列又叫哈希,它是根据哈希函数和冲突处理 哈希函数 的方法将一组关键字影射到一个有限的连续地址集上, 的方法将一组关键字影射到一个有限的连续地址集上, 并以关键字在地址集中的“ 作为存储位置。 并以关键字在地址集中的“象”作为存储位置。 优势:跟一般的查找方法(如线性表、树等)相比。它 优势:跟一般的查找方法(如线性表、树等)相比。 如线性表 相比 在定位过程中不用进行关键字的比较, 在定位过程中不用进行关键字的比较,查找效率不依 赖查找过程所进行的比较次数,记录存储位置 存储位置和 赖查找过程所进行的比较次数,记录存储位置和关键 值存在着一个确定的对应关系, 在着一个确定的对应关系 值存在着一个确定的对应关系,通过关键值就可以影 射到其存储地址。因此具有较高的查找效率。 射到其存储地址。因此具有较高的查找效率。
i=1 n=2 r=3
0 1
0000 1010 1111
Fra Baidu bibliotek
图1 线性散列表
现在我们来详细的分析下这个线性散列的大致结构,提出一 现在我们来详细的分析下这个线性散列的大致结构, 些注意事项帮助大家的学习。 些注意事项帮助大家的学习。
我们在图1中看到两个桶 每个桶包含一个存储块,标号分别为0 中看到两个桶, 一. 我们在图 中看到两个桶,每个桶包含一个存储块,标号分别为 的放入第0号桶中 和1。并且散列值的最后一位为 的放入第 号桶中,最后一位为 。并且散列值的最后一位为0的放入第 号桶中,最后一位为1 的放入第1号个桶中 号个桶中。 的放入第 号个桶中。 参数i(当前被使用的散列函数值的位数)、 (当前的桶数) 二. 参数 (当前被使用的散列函数值的位数)、 n(当前的桶数)和r 当前散列表中的记录总数), ),这些参数和数据共同构成了线性 (当前散列表中的记录总数),这些参数和数据共同构成了线性 散列表。 散列表。 比率r/n将受到限制 使一般的桶都只需要约一个磁盘存储块。 将受到限制, 三. 比率 将受到限制,使一般的桶都只需要约一个磁盘存储块。在 选择桶数n时 要注意的策略是使文件中的记录个数不超过1.7n, 选择桶数 时,要注意的策略是使文件中的记录个数不超过 , 即r<=1.7n。 。
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号桶中该记 即记录将被存在第 号桶中该记 录将被存入该桶的溢出块中? 录将被存入该桶的溢出块中?
动态散列
动态散列表允许B的改变, 动态散列表允许 的改变,使B近似于记录总 的改变 近似于记录总 数除以块中能容纳的记录数所得到的商; 数除以块中能容纳的记录数所得到的商;也就 是说,每个桶大约有一个存储块。 是说,每个桶大约有一个存储块。 动态散列表可以分为两种: 动态散列表可以分为两种:
可扩展散列 线性散列
线性散列表的插入
例题2 例题 我们考虑在例题1的散 我们考虑在例题 的散 列表中, 列表中,插入键值散列 的记录。 为0101的记录。因为其 的记录 最后一位为1, 最后一位为 ,记录应插 入到第二个桶中,即第1 入到第二个桶中,即第 号桶。桶中有空间, 号桶。桶中有空间,不 需要创建溢出块。 需要创建溢出块。
可扩展散列表
它在简单的静态散列表结构上主要增加了: 它在简单的静态散列表结构上主要增加了
为桶引入了一个简接层, 为桶引入了一个简接层,即用一个指向块的指针数组来表 示桶,而不是用数据块本身组成的数组来表示桶。 示桶,而不是用数据块本身组成的数组来表示桶。 指针数组能增长,它的长度总是 的幂 的幂, 指针数组能增长,它的长度总是2的幂,因而数组每增长 一次,桶的数目就翻倍。 一次,桶的数目就翻倍。 并非每个桶都有一个数据块; 并非每个桶都有一个数据块;如果某些桶中的所有记录都 可以放在一个块中,那么这些桶可能共享一个块。 可以放在一个块中,那么这些桶可能共享一个块。
线性散列表
正是由于可扩展散列表的一些缺点,我们引入了另一 正是由于可扩展散列表的一些缺点, 种策略:线性散列表,其中桶的增长较为缓慢。 种策略:线性散列表,其中桶的增长较为缓慢。在线 性散列中出现了一些新的要点: 性散列中出现了一些新的要点: 桶数n的选择总是使存储块的平均记录数保持与存储 桶数n的选择总是使存储块的平均记录数保持与存储 块所能容纳的记录总数成一个固定的比例, 块所能容纳的记录总数成一个固定的比例,如80%。 。 由于存储块并不是可以分裂,所以允许有溢出块, 由于存储块并不是可以分裂,所以允许有溢出块,尽 管每个桶的平均溢出块数远小于1。 管每个桶的平均溢出块数远小于
对其进行修正
将提高n,使其等于 ; 将提高 ,使其等于3; 并将i 改为2。 并将 改为 。 考虑把桶0和1改为桶 考虑把桶 和 改为桶00 改为桶 和01,并且增加下一个 , 桶到散列表中, 桶到散列表中,该桶编 号为10。 号为 。 分裂桶00,在分裂时, 分裂桶 ,在分裂时, 键值散列为0000的记录 键值散列为 的记录 保留在00桶中 桶中, 保留在 桶中,因为以 00结尾;键值散列为 结尾; 结尾 1010的记录存入桶 。 的记录存入桶10。 的记录存入桶 如图示: 如图示:
可扩展散列表
这种方法是认为B太小时即将其加倍, 这种方法是认为 太小时即将其加倍,最然是可以动 太小时即将其加倍 态的增加桶的数目,但是也有些自身的缺点: 态的增加桶的数目,但是也有些自身的缺点:
当桶的数组需要翻倍时,要做大量的工作。 当桶的数组需要翻倍时,要做大量的工作。这些工作会阻 碍对数据文件的访问, 碍对数据文件的访问,或是使某些插入看来花费很长的时 间。 当桶数翻倍后,它在主存中可能就装不下了, 当桶数翻倍后,它在主存中可能就装不下了,或者把其他 的一些我们需要保存的数据挤出去。其结果是, 的一些我们需要保存的数据挤出去。其结果是,一个运行 良好的系统可能突然之间每个操作所需的从盘I/O开始大 良好的系统可能突然之间每个操作所需的从盘 开始大 并且出现明显的性能下降。 增,并且出现明显的性能下降。
线性散列表的基本组织结构
例题1. 例题
图1所示为一个 所示为一个n=2的线散 所示为一个 的线散 列表。 列表。并用散列值的一位 来确定记录所属的桶(i=1)。 来确定记录所属的桶 。 并假定散列函数产生四位, 并假定散列函数产生四位, 用将散列函数作用到记录 的查找键上所产生的值来 表示记录。 表示记录。
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小于 我们不需要创建新桶。 我们不需要创建新桶。
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。 最后,就是根据最后两位的值分对桶进行的分裂。 最后,就是根据最后两位的值分对桶进行的分裂。