数据结构 | 查找

文章目录

查找的基本概念

基本概念

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

对查找表的常见操作

在这里插入图片描述

查找算法的评价指标

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

顺序查找

在这里插入图片描述

算法思想

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

算法实现

普通版

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

哨兵版

在这里插入图片描述

  • 当我们要查找某个关键字的时候会把这个关键字放到零号位置的这个地方,也就是所谓的哨兵
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

查找效率分析

在这里插入图片描述

顺序查找算法的优化

对有序表

在这里插入图片描述

  • 上面的树型结构称为查找判定树
用查找判定树分析ASL

在这里插入图片描述

被查概率不相等

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

折半查找

  • 又称为二分查找
    在这里插入图片描述

算法思想

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

代码实现

在这里插入图片描述

查找效率分析

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

折半查找判定树的构造

在这里插入图片描述

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

  • 1个结点

在这里插入图片描述

  • 2个结点

在这里插入图片描述

  • 3个结点

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

  • 4个结点

在这里插入图片描述

  • 5个结点

在这里插入图片描述

  • 6个元素

在这里插入图片描述

  • 7个元素

在这里插入图片描述

  • 8个元素

在这里插入图片描述

  • 9个元素

在这里插入图片描述

  • 10个元素

在这里插入图片描述

  • 11个元素

在这里插入图片描述

  • 12个元素

在这里插入图片描述

  • 13个元素

在这里插入图片描述

  • 14个元素

在这里插入图片描述

  • 15个元素

在这里插入图片描述

  • 16个元素

在这里插入图片描述

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

查找效率

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

拓展思考

在这里插入图片描述

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

分块查找

  • 又称为索引顺序查找
    在这里插入图片描述

算法思想

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

在这里插入图片描述

用折半查找查索引

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

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

在这里插入图片描述

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

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

拓展思考

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

二叉排序树BST

在这里插入图片描述

二叉排序树的定义

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

二叉排序树的查找

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

二叉排序树的插入

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

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

二叉排序树的构造

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

二叉排序树的删除

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

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

查找效率分析

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

平衡二叉树AVL

在这里插入图片描述

平衡二叉树的定义

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

平衡二叉树的插入

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

  • 我们把最小的不平衡子树恢复平衡之后,其他的祖先结点的平衡因子也都恢复了原来正常值

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

调整最小不平衡子树

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

LL

在这里插入图片描述

  • 如果A的右子树AR高度不是H而是H+1,则在B左子树BL插入新结点之后A的平衡因子为1,仍是平衡的,不会出现不平衡的情况
  • 如果A的右子树AR的高度为H-1,那么A本来就是不平衡的,也明显不对,我们此时要探讨的是插入新结点之后才导致不平衡的这样一种情况
  • 如果B右子树BR的高度为H-1,那么插入新结点之后B的平衡因子为2,B变成了最小不平衡子树,但是我们这里设定的是A是最小不平衡子树来探讨的
  • 所以这里假设所有的子树高度为H方便我们讨论不平衡的情况

在这里插入图片描述

RR

在这里插入图片描述

  • 和上述描述的情况一样,如果AL、BL、BR这三部分的子树的高度不是H的话就无法满足在RR插入新结点之后A变成最小不平衡子树这个条件

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

LR

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

RL

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

查找效率分析

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

  • 高度为h的平衡二叉树它的节点数最少的一种情况应该是一个根结点,加一个左子树高度为h-1并且我们要保证它的结点数最小,然后右子树可以让它高度为h-2并且也要保证它的结点数最少,所以就有了递推关系:nh = nh-1 + nh-2

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

平衡二叉树的删除

对比平衡二叉树的插入&删除

在这里插入图片描述

平衡二叉树的删除

在这里插入图片描述

  • 是不是忘了二叉排序树是怎么删除结点的?哈哈哈看看下面的导图回忆下吧
    在这里插入图片描述
AVL树删除操作——例1

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

  • 此时没有找到最小的不平衡子树,说明刚刚的删除结点的操作并没有导致其任何一个祖先出现不平衡的现象,搞定
AVL树删除操作——例2

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

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

AVL树删除操作——例3

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

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

在这里插入图片描述

AVL树删除操作——例4

在这里插入图片描述

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

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

在这里插入图片描述

AVL树删除操作——例5

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

在这里插入图片描述

AVL树删除操作——例6

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

  • 事实上我们选择哪一个结点作为其个子最高的孙子都是没问题的

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

红黑树RBT

在这里插入图片描述

为什么要发明红黑树

  • 红黑树RBT和BST、AVL都是一个家族的树,都是用于查找的二叉树

在这里插入图片描述

  • 既然AVL树的查找、插入、删除操作的时间复杂度已经在O(log2n)这个数量级,而且红黑树的查找、插入、删除操作也没有比AVL树更优秀,都是O(log2n)这个数量级,那为什么还要发明红黑树呢?

在这里插入图片描述

  • 在AVL中每当我们删除或者插入一个新结点之后很有可能会破坏平衡二叉树“平衡”的特性,需要频繁调整树的形态
  • 而红黑树RBT在插入/删除的很多时候都不会破坏“红黑”的特性,无需频繁调整树的形态,即便需要调整一般也都可以在常数级的时间内完成

红黑树大概会怎么考???

在这里插入图片描述

红黑树的定义

在这里插入图片描述

实例:一棵红黑树

在这里插入图片描述

练习:是否符合红黑树要求?

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

一种可能的出题思路

在这里插入图片描述

补充概念:结点的“黑高”

在这里插入图片描述

红黑树的性质

在这里插入图片描述

  • 性质1可以和④和⑤推算而来,因为首先从根结点出发到达任意一个叶结点所经过的黑结点数量都是相同的,但是在这条路上又要求不红红,也就是说在根节点到叶结点的这条路上,不可能连续的出现两个红色的结点,这些红色的结点只有可能穿插在各个黑结点中间,并且根叶黑,首尾两端都是黑结点,假设每条路径都有n个黑结点,那么最少有0个红结点,最多只有n-1个红结点,因为路径最长的境况肯定是红节点把每一个黑结点之间的空隙都填满了
  • 基于性质1我们也可以得出这样的结论:在红黑树当中,任何一个结点的左子树和右子树的高度之差不会超过两倍;这相比于AVL高度之差不超过1的特性来说不那么容易被破坏,所以红黑树的红黑特性不太容易被破坏,但是平衡二叉树的特性很容易被破坏,每一次的破坏都得进行平衡的调整,这也就是红黑树的插入和删除比平衡二叉树更高效的原因

红黑树的查找

在这里插入图片描述

  • 和二叉排序树以及平衡二叉树的查找是相同的

红黑树的插入

回忆:AVL的插入

在这里插入图片描述

RBT的插入

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

  • 20是根节点,我们要保证“根叶黑”,所以根节点统一都是黑色
  • 从根节点出发,10比20更小,所以应该往左走,只要新插入的结点不是根节点就统一把它们涂红,这么做的原因是为了保证“黑路同”这个特性,如果新插入的结点是黑色就会导致左边黑路的长度比右边黑路的长度长,破坏了红黑树的特性
  • 所以我们插入节点时会优先把它涂成红色,因为红节点不会增加黑路的长度
  • 染色染的是刚刚发生调换处理的两个结点——红变黑黑变红

在这里插入图片描述

在这里插入图片描述

  • 我们可以看到插入新结点的时候一定是破坏了红黑树”不红红“这个特性,因为其它三个特性不可能被这个新插入的红节点破坏

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

在这里插入图片描述

在这里插入图片描述

  • 新结点不是根,所有的非根结点我们只需要关注其有没有引发”不红红“即可

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

红黑树练习方法——快乐小网站

在这里插入图片描述

与“黑高”相关的推论

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

红黑树的删除

在这里插入图片描述

B树

回忆:二叉查找树BST

在这里插入图片描述

  • 二叉查找树无非就是用一个关键字把一个我们有可能搜索到我们目标关键字的这个范围(数域范围)分割成了两份

5叉查找树

在这里插入图片描述

5叉查找树如何查找

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

如何保证查找效率

在这里插入图片描述

  • 为什么根节点可以搞特殊???
  • 因为我们不能保证根节点有那么多个结点支撑它有那么多个分叉

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

B树

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

在这里插入图片描述

  • 多路:任何一个结点可能会有多个分叉出现,我们可能会从多条路往下查找
  • 平衡:对于每个节点来说它的任何一个子树的高度是相同的,即任何一个结点都是平衡的(绝对平衡)
  • 不是终端结点的根节点至少要有2棵子树,是为了保证绝对平衡
  • 叶子结点也就是失败结点,本质上就是一个null空指针,出现在同一层上是因为我们要求所有的结点都绝对平衡,因此所有的叶子结点一定都是同时出现在最下面这一层的

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

B树的高度

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

  • n个关键字的B树必有n+1个叶子节点
  • Why?因为B树当中的这n个关键字相当于是在(-∞,+∞)这个区间内插入了n个关键字,所以这n+1个关键字会把整个数值区间把它切分为n+1个部分,那这n+1个部分其实就对应了n+1种失败的情况,所有的失败情况都会体现在我们的叶子结点中,所以失败结点也肯定是n+1个

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

B树的插入和删除

B树的插入

在这里插入图片描述

在这里插入图片描述

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

  • 注意这里我们每次新插入的元素一定是要插入最底层的结点当中的

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

  • 如果90插在上面一层那么就意味着我们的失败结点就不是同一层了,不满足B树的特性

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

  • 如果一个关键字,它因为分裂需要把它提到父结点当中,那么我们应该把这个关键字放到它所属的结点的这条指针所对应的这个点右边的位置
  • 这么做可以保证我们这棵树依然保持B树的特性
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

B树的删除

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

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

  • 相当于把非终端结点的删除操作转换成了对终端结点的删除操作

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

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

B+树

对比:分块查找

在这里插入图片描述

B+树

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

  • 为什么非叶根结点至少要有两棵子树呢?

在这里插入图片描述

B+树的查找

在这里插入图片描述

  • B+树无无论查找的成功与否,最终都一定要走到最下面的一层结点
  • 因为在B+树中如果我们只是在分支结点中找到我们想要找到的那个关键字,我们的查找还是没有结束的,因为关键字代表的这个记录的实际信息到底存放在哪我们只有找到最下面一层叶子结点之后才可以找到这个记录对应的数据

在这里插入图片描述

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

  • B+树除了从根节点开始逐层开始往下查找之外,我们也可以通过保存的指针p进行顺序查找

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

对比:B树的查找

  • B+树无无论查找的成功与否,最终都一定要走到最下面的一层结点,因为上一层的分支节点信息一不能真实地反应出某一个关键字是否存在,二是我们只有找到最下面这一层的叶子结点之后才可以找到某一个关键字实际对应的这个记录它的存放位置
  • 因为在B+树中如果我们只是在分支结点中找到我们想要找到的那个关键字,我们的查找还是没有结束的,因为关键字代表的这个记录的实际信息到底存放在哪我们只有找到最下面一层叶子结点之后才可以找到这个记录对应的数据
  • 但是在B树的查找中我们有可能查找成功,停留在任何一层,因为如果查找到了我们就可以确定这个关键字是存在的,这要理解B树和B+树的本质区别(m叉排序树和多级分块查找)

B+树 v.s. B树

关键字和子树的对应情况

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

关键字数

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

关键字是否重复

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

结点

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

小拓展

  • B+树里边这些一个一个的结点其实是存放在我们的磁盘里边的,也就是外存当中,操作系统对磁盘的读写一般是以磁盘块为单位的,所以一般来说B+树的一个节点就会对应存放在某一个磁盘块当中,所有的结点都是存放在不同的磁盘块里面的
  • 因此我们对B+树的查找其实是这样的过程,我们要从根节点开始查找,系统在背后做的事情是会找到这个根节点它到底是存放在哪一个磁盘块当中,然后会把磁盘块读到内存当中,只有读到内存里计算机才可以处理查询对应的数据,读取完之后我们就可以确定我们要找的关键字应该要到哪一个分支上去查找,接下来系统会把对应的分块相关的数据再一次读入内存,然后计算机就可以开始查询这些分块里边的数据,我们可以知道再往下的一层叶子节点到底存放在磁盘当中的什么位置,所以接下来操作系统会把对应的这一块给读入内存,然后就可以找到欲查找的关键字所对应的记录应该是存放在磁盘当中的什么位置,所以接下来只需要在磁盘当中读出这个记录相关的数据信息就可以
  • 对于B+树的查找,我们每查找一层结点的时候其实都需要进行一个读磁盘的操作,直到找到最下面一层的叶子节点,对于B树也是一样的,我们每查找一层结点的时候其实都需要进行一个读磁盘的操作,磁盘作为一种慢速设备,计算机读磁盘的操作其开销是很大的,因此就意味着我们的B+树高度越高,整个查找过程中读磁盘的次数也会更多,这会导致我们的查找速度更慢
  • 怎么减少树的高度呢?每一个节点包含的关键字数量越多,就意味着这棵树总的高度就会越低,而且这些一个一个的结点其实是存放在我们的磁盘里边的,而每个磁盘块大小固定,所以我们就要让一个磁盘块中包含尽可能多的关键字的信息,这就是B+树这么设计的原因:B+树中,非叶子结点不含有该关键字对应记录的存储地址,这就意味着这一份记录可以花更少的空间来存储,可以使一个磁盘包含更多的关键字,使得B+树的阶更大,树高更矮,读磁盘次数更少,查找更快

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

散列查找Hash

散列表/哈希表Hash Table

在这里插入图片描述

  • 每个数据元素的关键字和数据元素的实际存储地址之间有一个映射关系

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

处理冲突的方法——拉链法

在这里插入图片描述

散列查找

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

  • 这里我们可以发现,分子的部分其实反应的是我们这个散列表存储了多少的记录/数据元素,而分母刚好等于散列表的长度
  • 装填因子这个参数表示的是一个散列表它到底装得有多满,装填因子越大说明这个散列表装得越满,其大小会直接影响到散列表的查找效率

常见的散列函数

除留余数法

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

  • 为什么p要取质数呢?因为取质数可以让不同关键字的冲突尽可能地少

在这里插入图片描述

直接定址法

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

数字分析法

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

平方取中法

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

  • 相乘的时候中间的几位可能是和我们每一个数码位都是相关的

在这里插入图片描述

  • 冲突太淦了,有没有一种方法能绝对地避免冲突呢?有!空间换时间!

在这里插入图片描述

处理冲突的方法——开放定址法

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

线性探测法

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

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

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

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

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

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

在这里插入图片描述

  • 现在来探讨查找操作

在这里插入图片描述

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

  • 拉链法由于是指针,指针域为null所以我们在查找失败的时候已经到了空指针就不用比较了,但是这里每个位置都是一个数,我们不确定这个数是否相等,所以仍需要一次比较

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

  • 下面我们来探讨删除操作

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

  • 现在来探讨查找效率

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

平方探测法

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

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

  • 现在来探讨查找问题

在这里插入图片描述

  • 非重点小坑:答案在《数论》
    在这里插入图片描述
    在这里插入图片描述
伪随机序列法

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

处理冲突的方法——再散列法

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

拉链法的小优化

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ErizJ

觉得好的话给小弟一点鼓励吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值