[数据结构]第七章 查找

第七章 查找

在这里插入图片描述

基本概念

  1. 查看某特定的关键字是否在表中(判断性查找
  2. 检索某特定关键字数据元素的各种属性(检索性查找
  3. 首先也有一个“判断性查找”的过程,如果某特定的关键字在表中不存在,则按照一定的规则将其插入表中
  4. 如果已经存在,则可以对其执行删除操作
  • 静态查找仅仅执行“查找”的操作(上述1、2)
  • 动态查找在"查找操作"的基础上增加插入和删除操作(上述3、4)

线性结构

顺序查找

  • 顺序查找:从表的一端开始,顺序扫描线性表,依次将扫描到的关键字和给定值k相比较,若当前扫描到的关键字与k相等,则查找成功;若扫描结束后,仍未找到关键字等于k的记录,则查找失败。
  • 改进后带哨兵的顺序查找:设置“哨兵”。哨兵就是待查值,将它放在查找方向的尽头处,免去了在查找过程中每一次比较后都要判断查找位置是否越界,从而提高了查找速度。例如如果查找方向是从左到右,则将待查值放在R[n]位置;如果查找方向是从右到左,则将待查值放在R[0]位置。当然前提是最后一个或第一个元素的位置不存放关键字。
    在这里插入图片描述

折半查找

  • 折半查找,也称二分查找:首先使用排序算法对查找表进行排序,保证有序
  • 升序数列为例,比较一个元素与数列中的中间位置的元素的大小。
    1. 如果比中间位置的元素大,则继续在后半部分的数列中进行二分查找
    2. 如果比中间位置的元素小,则在数列的前半部分进行比较
    3. 如果相等,则找到了元素的位置。

例:找出11在表中的位置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
11大于10,low = mid + 1,low>high, 跳出while循环,查找失败,返回-1。

分块查找

  • 分块查找(Blocking Search)又称索引顺序查找,它是一种性能介于顺序查找和二分查找之间的查找方法。
  • 二分查找表由"分块有序"的线性表和索引表组成。
    • "分块有序"的线性表:表R均分为b块,每一块中的关键字不一定有序,但前一块中的最大关键字必须小于后一块中的最小关键字
    • 索引表:抽取各块中的最大关键字及其起始位置构成一个索引表
  • 查找时先确定位于哪一块,折半或者顺序查找索引表;然后再进行块内查找。

在这里插入图片描述

树型结构

二叉排序树(BST树)

  1. 特点
  • 根结点的值大于左子树中任意一个结点的值
  • 根结点的值小于右子树中任意一个结点的值
  • 这一规则适用于二叉查找树中的每一个结点
  1. 优点
查找方法 平均时间复杂度
链表(顺序查找) O(n)
二分查找 O(logn)
二叉排序树 O(logn)

二叉排序树越平衡,越能模拟二分法。

  1. 缺点
    当插入顺序为:按关键字大小递增或者递减时,BST就会退化为链表时,其查询的时间复杂度就会降为O(n)。
    在这里插入图片描述

二叉平衡树(AVL树)

  1. 特点
  • 拥有BST树的所有特点
  • AVL树上任意结点的左、右子树的高度差最大为1
  1. 优点
    矮胖型的树,确保AVL的查找、添加、删除的时间复杂度都是O(logn)
    在这里插入图片描述

B树、B+树

需要了解B树基本概念,以及建立、插入、删除的操作。
仅需要了解B+树的基本概念。

B树

基本概念

B树和AVL树(平衡二叉树) 的差别就是B树属于多叉树(多个子树M阶表示一个B数结点最多有多少个查找路径(即子节点),M=M路,M=2二叉,M=3三叉),又名平衡多路查找树。一个结点存储多个关键字(索引)。

  • 每个结点的值(索引) 都是按递增次序排列存放的,并遵循左小右大原则。
  • 根结点(最上面的那个结点)的子节点个数为 [2, M]。
  • 根结点以外的非叶子结点 的子节点个数 为[ Math.ceil(M/2)M]。 Math.ceil() 为向上取整。
  • 每个 非叶子结点 的值(索引) 个数 = 子节点个数 -1 。最小为 Math.ceil(M/2)-1 最大为 M-1 个。
  • B树的所有叶子结点都位于同一层。

举例:下图是一个3阶B树
在这里插入图片描述

  1. 每个 结点中 的索引值 都是从小到大排序的,遵循左大右小
  2. 根节点的子节点为2([2,3])
  3. 除 根结点 外,所有 非叶子结点 都至少有 M/2 = 1.5 上取整 = 2 个结点([2,3])。
  4. 非叶子结点索引值个数为子节点个数-1 [M/2上取整-1=1,M-1=2]
  5. 所有叶子结点都在同一层中。
  • B树非叶子结点的数据结构:n存结点的关键字的个数,Pi为指向子树根节点的指针,Ki为结点的关键词(子树和父亲树的关键词满足左小右大),关键值就是索引,可以通过key找到相对应的value~
    在这里插入图片描述

  • B树叶子结点:都出现在同一层上,并且不带信息,可以视为外部结点或者类似查找失败判定结点,实际上这些结点不存在,指向这些结点的指针为空
    在这里插入图片描述
    所有叶子节点均在第四层,代表查找失败的位置。

  • B树高度,不算叶子节点那一层,有的教材中算。
    在这里插入图片描述
    在这里插入图片描述

查找

磁盘中找结点,内存中找关键值(顺序或折半)

从上述的 3阶B树 中,查找 结点(索引)值5 的过程:

  1. 第一次读IO,把9的结点读到内存,再与目标数5比较,5是小于9的,因此往9的左边走。
    在这里插入图片描述
  2. 第二次读IO,还是把结点读到内存中,然后比较结点中的2和6与目标值5。发现5是大于2小于6的,因此往中间路径走。
    在这里插入图片描述
  3. 第三次读IO,还是把结点读到内存中,然后发现结点中有5,因此找到目标值。

B数优势:

  1. 数据库查询中,以树存储数据。树有多少层,就意味着要读多少次磁盘IO。所以树的高度越矮,就意味着查询数据时,需要读IO的次数就越少。(众所周知,读IO是一件费事的操作)当数据量大的时候,用AVL树存的话,就算AVL是平衡树,但是也扛不住数据量大。B树的一个结点可以装多个值,读取时,是把整个结点读到内存,然后在内存中,对结点的值进行处理,在内存中处理速度肯定比磁盘快。所以只要树的高度低,IO少,就能够提升查询效率,这是B树的好处之一。

  2. B树的每一个结点都包含key(索引值) 和 value(对应数据),因此访问离根结点近的元素会更快速。(相对于B+树)

插入

在这里插入图片描述
在这里插入图片描述

下面以 5阶B树 为例:[3, 5]

  1. 在空树中插入39,此时根结点只有一个索引值。
    在这里插入图片描述

  2. 继续插入22,97和41,根结点此时有4个索引值。
    在这里插入图片描述

  3. 继续插入53:
    在这里插入图片描述
    此时已经超过了最大允许的索引个数4,即4个。所以以其中心(41)分裂。结果如下图所示:
    在这里插入图片描述

  4. 然后在上图的基础上,再依次插入13,21,40,那么41所在结点的左子结点里的值就为13、21、22、39、40,一共五个,所以会以22为中心进行分裂,结果如下图所示:
    在这里插入图片描述
    分裂的中心22会进位到上一层的结点中。

  5. 再在上图的基础上,插入30,27,33,那么其中有一个结点内的值为27、30、33、39、40,那么就会以33为中心引起一次分裂。
    然后再插入36,35,34,那么就又会有一个结点内的值为34、35、36、39、40,那么就会以36为中心分裂。
    在这里插入图片描述
    然后再插入24、29,如下图所示:
    在这里插入图片描述
    此时拥有24、27、29、30的结点只要再插入一个索引值,就又会发生分裂。

  6. 插入26
    在这里插入图片描述
    插入26后,结点以27为中心分裂,并且27进位到上一层父结点中。
    27进位到父节点后,父节点里的索引值也超过了4个,因此也要分裂,分裂后如下:
    在这里插入图片描述
    在这里插入图片描述

删除

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一直合并到符合B树条件为止

原始状态 五阶b树 子树范围[3, 5] 结点索引值个数[2, 4] 在进行操作时要注意的就是结点索引值个数~
在这里插入图片描述

  1. 在上图的树中,删除21。由于删除21后的结点的索引值个数仍然大于2(Math.ceil( 5/2 ) -1 =2),因此删除结束。
    在这里插入图片描述
  2. 接着删除27。从上图可知,由于27是非叶子结点,所以要删除27的话,需要用27的后继替代它。从上图可以看出,27的后继是28,因此我们用28来替代27,再删除原来的28,如下图:
    在这里插入图片描述
    删除后发现,当前结点(当前结点如上图所示)的索引值个数小于2个,而它的兄弟结点有3个索引值(当前结点还有一个右兄弟,选择右兄弟的话,会出现合并结点的情况,不论选哪一个都可以,只是最后的B树形态会不一样而已),那么就兄弟借一个索引值,注意这里的借并非直接从左兄弟结点处拿一个索引值过来,如果是这样的话,就破坏了B树父节点左子树比根结点小,右子树比根结点大的特性了。借是 把当前结点的父节点的28下移,然后把左兄弟结点的26上移到父节点,删除结束。如下图:
    在这里插入图片描述
  3. 在上述情况接着删除32:如下图
    在这里插入图片描述
    在删除32后,当前结点剩下31,即索引值数目小于2。这时候,它的兄弟结点,也仅仅有2个索引值,兄弟不够借。那只能够让父结点下移一个值(30),并和兄弟结合合并成一个新的结点,如下图:
    在这里插入图片描述
    当前结点的索引值个数不小于2 (Math.ceil( 5/2 ) -1 =2),满足条件,删除结束。
  4. 接着删除 40:删除40后,如下图所示:
    在这里插入图片描述
    当前结点由于索引值小于2,因此需要像父结点借,父结点下移36到当前结点,然后和兄弟结点合并(选择左兄弟或右兄弟都可以,这里我选择了左兄弟),如下图:
    在这里插入图片描述
    但这时候发现,新的当前结点的索引值个数又小于2了,那么只能向其父结点借了,所以其父结点下移33,然后当前结点和其兄弟结点合并,如下图:
    在这里插入图片描述
    删除结束。

B+树

B+树是基于B树的基础提出的。
下图是一棵 4阶B+树
在这里插入图片描述
B+树和B树最大的不同是:

  1. B+树内部有两种结点,一种是索引结点(存索引),一种是叶子结点(存记录)。
  2. B+树的索引结点并不会保存记录,只用于索引,所有的数据保存在B+树的叶子结点中。而B树则是所有结点都会保存数据
  3. B+树的叶子结点都会被连成一条链表。叶子本身按索引值的大小从小到大进行排序。即这条链表是 从小到大的。多了条链表方便范围查找数据
  4. B树的所有索引值是不会重复的,而B+树 非叶子结点的索引值 最终一定会全部出现在 叶子结点中。(n个关键字只有n个子树)

B树查找到最后一层非叶结点不会终止,而会继续查找叶子结点中的关键字。

B树好处:
B树的每一个结点都包含key(索引值) 和 value(对应数据),因此访问离根结点近的元素会更速。(相对于B+树)

B树的不足:

不适用于范围查找(区间查找),如果要找 0~100的索引值,那么B树需要多次从根结点开始逐个查找。

而B+树由于叶子结点都有链表,且链表是以从小到大的顺序排好序的,因此可以直接通过遍历链表实现范围查找

散列结构——散列表

  • 线性表和树表:记录在表中的位置Addr和记录的关键字Key之间不存在确定关系,这类查找方法建立在比较的基础上

  • 散列表:存在确定关系,首先利用散列函数把查找表中的关键字映射成该关键字对应的地址的函数(Hash(Key) = Addr,这里地址可以市数组下标,索引或内存地址),散列表可以根据关键字直接访问数据结构,建立了关键字和存储地址之间的一种直接映射关系。理想情况下查找的时间复杂度为O(1)。

  • 冲突: 散列函数可能会把两个或两个以上的不同关键字映射到同一地址,发生碰撞的不同关键字成为同义词 -->设计好的散列函数减少冲突 设计处理冲突的办法

建立

  1. 直接定址法
    在这里插入图片描述
    a,b为常数

  2. 除数留余法
    在这里插入图片描述
    p为不大于最接近或等于m(散列表长)的质数

  3. 数字分析法
    根据r进制数各个 码位上数字出现的频率,寻找分布均匀的码位

  4. 平方取中法
    关键字平方值中间几位作为散列地址

冲突处理

  • 产生冲突时,为产生冲突的关键字寻找下一个空的Hash地址。
    H i H_i Hi表示处理冲突第i次探测到的散列地址,假设另一个地址 H 1 H_1 H1仍冲突,就继续找,直到不冲突为止。
  1. 开放定址法
    在这里插入图片描述
    在这里插入图片描述

(一)线性探测法:顺序查看表中下一个单元,会产生堆积现象
在这里插入图片描述
(二)平方探测法:有效避免堆积

(三)再散列法,双散列法:
在这里插入图片描述
在这里插入图片描述
(四)伪随机序列法
在这里插入图片描述
2. 拉链法、链接法:把发生冲突的同义词存储在一个线性链表中
在这里插入图片描述

性能分析

查找过程:1. 给定关键值key,查找表中key对应的addr是否有记录,无记录查找失败,有记录key相等则查找成功,否则执行2。 2. 用冲突处理方法寻找下一个addr,并把addr设为地址,转1

在这里插入图片描述
由于冲突存在,散列表查找过程仍是给定值和关键字进行比较的过程
在这里插入图片描述
在这里插入图片描述

性能指标——平均查找长度

分为查找成功和查找失败的情况

时间复杂度:

  • https://blog.csdn.net/qq_43411563/article/details/105302373
  • https://blog.csdn.net/liu891208/article/details/47778415

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44145782/article/details/119332959