数据结构 — 查找III

本文介绍了B+树的基本概念及其在数据库设计中的应用,强调了其非叶结点不存储数据的特点。接着,讨论了散列表的特性,包括其直接访问、冲突解决和常见散列函数。提到了线性探测法和平方探测法等处理冲突的方法,并分析了开放地址法和拉链法的优缺点,以及如何影响查找效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

B+树的基本概念

 

【应用】为数据库设计的一种B树的变形树

 

【定义】

         一个m阶的B+树:

                 1.      每个分支结点至多有m棵子树(子结点)



1.      字和指向该子树的指针,不含有该关键字对应记录的存储地址(B树中结点还存储着对应磁盘页面的地址,便于从B树中找到结点后,从磁盘将该结点信息读入内存

2.      在B+树中,叶结点包含了全部关键字,即在非叶结点中出现的关键字也会出现在叶结点中;而在B树中,叶结点包含的关键字和其他结点包含的关键字是不重复的。(其实这里的叶结点我的理解是终端结点)

 

 

 

 

 

 

 

散列表

 

【特点】根据关键字而直接进行访问的数据结构。通过散列函数

建立关键字和存储地址之间的一种直接映射关系。

         【注】理想情况下,对散列表进行查找的时间复杂度为O(1),即与表中个数无关。但是难免存在要解决冲突的情况即多个key被映射到同一个地址。

 

         冲突:散列函数可能会把两个或连个以上的不同关键字映射到同一地址

         同义词:这些发生碰撞的不同关键字

 

 

 

 

【散列函数】

 

【要求】        

1)  定义域必须包含所有关键字,而值域则依赖于散列表大小或地址范围。(可见允许多对一,毕竟内存资源是很宝贵的。

2)  散列函数计算出来的地址应该等概率,均匀的分布在整个地址空间,从而减少冲突发生。

3)  散列函数应尽量简单,能够在较短时间内计算出任一关键字对应的散列地址。

 

【常用散列函数】

1.      直接地址法

 

直接取关键字的某个线性函数值为散列地址,散列函数为:

                            

【特点】这种计算方法最简单,并且不会产生冲突(线性函数保证了关键字和地址的一一对应,主要是实际中a,b如何取值呢?)。它适合关键字的分布基本连续的

况,若关键字分布不连续,空位较多,将造成空间的浪费。

 

1.      除留取余法

 

这是一种最简单常用的方法。假定散列表长度为m,取一个不大于m但最接近或等于m的质数p,利用一下公式把关键字转换成散列地址。散列函数为:

                                               

【特点】除留取余法关键是选好p,使得每一个关键字通过该函数装换后等概率的(并不要求一一对应,因为取余法的定义注定会有冲突产生)映射到散列空间上的任一地址,从而尽可能的减少冲突。

 

 

 

2.      折叠法

 

将关键字分割成位数相同的几部分(最后一部分可以短一些),然后取这几部分的叠加作为散列地址,这种方法称为折叠法。

 

【特点】 关键字位数很多,而且关键字中每一位数字分布大致均匀,可以采用折叠法得到散列地址。

 

 

【处理冲突】

 

         【引】应该注意到,任何设计出来的散列函数都不可能绝对的避免冲突,为此,必须考虑在发生冲突的时候应该如何进行处理。即为产生冲突的关键字寻找下一个空的hash地址。

 

         假设已经选定散列函数H(key),下面用Hi表示发生冲突后第i次探测到的散列地址。

 

1.      开放地址法

【特点】 指的是可存放新表项的空闲地址既向它的同义词表项开放,又向它的非同义词表项开放(这就导致了空闲地址被争夺,进而引发次带影响)。其数学递推式:



式中,i=1,2…….,k(k < m-1);m表示散列表表长,为增量序列。

 

当选定某一增量序列后,其对应的处理方法是确定的。(也就是说是事先确定好了的

 

1)  线性探测法:

 

【特点】 当=1,2,….m-1(相对递增值),称为线性探测法。                   冲突发生时,顺序查看表中下一个单元(当探测到表尾地址m-1时,下一个探测地址是表首地址(通过递推式中取余来保证)),直到找出一个空闲单元(当表为填满时一定能找到一个空闲单元)或查遍全表

 

【分析】 线性探测法可能使第i个散列地址的同义词存入第i+1个散列地址,这样本应存入第i+1个地址元素就争夺第i+2个散列地址元素的地址…..从而造成大量元素在相邻散列地址上“聚集”(或堆积)起来,大大降低了查找效率。

 

2)  平方探测法

                  

                      【特点】当=,,其中k,m必须是一个可以表示成4k+3的质数 ,又称二次探测法。

 

                            【分析】

                            平方探测法是一种较好的处理冲突的方法,可以避免“堆积”问题,(但还是 会有冲突出现,注意区分冲突聚集)。它的缺点是不能探测到散列表上所有单元,但至少能探测到一半的单元。

 

 


         【开放地址法—总结】

                   在开放地址法情况下,不能随便物理删除表中已有元素,因为若删除元素将会截断  起其他具有相同散列地址元素的查找位置。




如何去删除节点?

         若必须在散列表中删除结点,则不能将被删结点的关键字置为NIL,而应该将其置为特      定的标记DELETED。因此须对查找操作做相应的修改,使之探查到此标记时继续探查下去。同时也要修改插人操作,使其探查到DELETED标记时,将相应的表单元视为一  个空单元,将新结点插入其中。这样做无疑增加了时间开销,并且查找时间不再依赖于   装填因子。同时在执行多次删除后,表面上看散列表很满,实际上有许多位置没有利用。因此需      要定期维护散列表,要把删除标记的元素物理删除(并且把后面的同义词      移到前面来)。


     
因此,当必须对散列表做删除结点的操作时,一般是用拉链法来解决冲突。

 

 

 

2.拉链法

        

         【引】为避免非同义词发生冲突,可以把所有同义词存储在一个线性链表中,这个线性链表由其散列地址唯一标识。

 

         【特点】散列地址为i的同义词链表的头指针存放在散列表的第i个单元,因而查找,   插入,删除操作主要在同义词链中进行。  拉链法适用于经常进行插入和删除的情况。




         

散列查找及性能分析   -----(适合查找)

 

【特点】散列表的查找和构造散列表的过程基本一致。

 

【执行步骤】

        

         初始化:Addr=Hash(key)

1.      检测查找表中地址为Addr的位置上是否有记录,若没有记录,返回查找失败;若有记录,比较它与key的值,若相等,返回查找成功标志,否则执行步骤2;

2.      用给定处理冲突的方法计算“下一个散列地址”,并把addr置为此地址,转入步骤1

 

【性能分析】

         散列表的查找效率取决于三个因素:散列函数,处理冲突的方法和装填因子

 

         装填因子:散列表的装填因子一般记为,定义为一个表的装满程度,即:




散列表的平均查找长度依赖于散列表的填装因子,而不直接依赖于n或m(是二者综合效果),直观来看,越大,表示填装的记录越满,发生冲突的可能性越大,反之则越小。

 

         【小结】

         虽然散列表在关键字与记录的存储位置建立了直接映像,但由于“冲突”的产生,使得散列表的查找过程仍然是一个给定值和关键字比较的过程(要顺着解决冲突的方式查找嘛)。因此,仍需以平均查找长度作为衡量散列表查找效率的度量(理想状态下是O(1),即关键字和地址一一对应


          

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值