当前位置:   article > 正文

数据结构(7):查找

数据结构(7):查找

1 查找的基本概念

概念

常见操作

评价指标

平均查找长度!!!!

✖前面表示长度 后边表示个数!

处于的是总共的紫色的个数

总结

2 顺序查找、折半查找、分块查找

2.1 顺序查找

适用于线性表!

正常代码

哨兵!代码

查找效率分析

成功的话是 求的平均值

失败的话就是 查找到0都没有对应相等的,所以就是查找了n+1次!

顺序查找的优化(对有序表)

有序表:查找表中的元素有序存放(递增/递减!)

写出查找判定树 写出失败的那些框!

注意最后的两个n

有查找判别数分析ASL

顺序查找的优化2(被查概率不相等)

把概率大的放前面!

总结

时间复杂度都是o(n)

2.2 折半查找

实现思想

适用于 有序的顺序表!就是 二分法!

mid的值算出来如果是小数 就向下取整!

查找成功

在右边的时候更新时:low = mid+1

在左边的时候 high = mid-1

low = mid+1

这个时候high = low,如果所指和目标相等则查找结束!

查找失败

全面的都一样 到到low=high时,

mid = low = hight 此时mid的小于 目标值 一次low = mid+1

这是会出现low>height的矛盾 所以!算法结束! 

代码实现

这个判断逻辑是按照 元素是升序排列的!降序类似但不一样哦 注意辨别!

查找效率分析【具体计算】

关键词对比!--擦护照效率

折半查找的判定树【时间复杂度】

用到的结论

左子树的结点个数一定小于等于右!!!

右子树比左子树只可能多一个结点!!!!!!

所以这种就不可能存在

折半查找的判定树 一定是平衡二叉树!

树高公式和完全二叉树的计算方法一样

h=\left \lceil log_2(n+1)) \right \rceil向上取整!

 

失败结点的个数等于总结点+1
时间复杂度

总结

思考:

大多时候是高的但不是全部

2.3 分块查找

算法思想

low和high表示这个块的起始位置和结束位置!

例子

查找成功

查找失败

算法过程

在分块内顺序查找!

找在那个块是也可折半查找
eg1 :当目标在索引表关键字里时

eg2:当目标不在索引表关键字里时

最后会出现low>hight的结果折半查找结束,这是目标可能在 low所指的分块内!

low指向的比目标更大!!!!

上一步时low=high;这是如果所指关键字a<目标b: low = mid+1 这是low所指的关键字就比目标大了,所以在这个分块 // 如果所指关键字a>目标b:hight = mid-1  这时hight所指的块都比目标小 所以目标只能在low分块  

综上所述,一定在low分块里!!!

eg3:找不到分块low

特例的查找效率分析(ASL)

1、顺序查找

7有两次:对比10 对比7 然后结束yigongliangc

13有三次: 对比10 对比20 然后进去 对比13 结束 一共3次!

2、折半查找

27:一定不是2!!!远远不够!!!很庞大的工程

查找失败更复杂!!!

通项的查找效率

顺序查找

求ASL最小的时候!!!

什么时候ASL最小呢?当分块有\sqrt{n}个,每个分块有\sqrt{n}个,可以得出此时的ASL等于\sqrt{n}+1

这与顺序查找的ASL相比已经好特别特别多了,

直接所有元素顺序查找ASL=\frac{1+2+3+4+...+n}{n} = \frac{\frac{n(n+1))}{2}}{n} = \frac{n+1}{2} 当n = 10000时平均ASL是5000!

折半查找【有个小印象就可以了!】

总结

思考

插入一个元素8会导致所有的元素向后移动!代价太大 所以可以用链式存储!

数据结构应该怎末设计?因该采取什么样的查找算法 都是需要大家按照现实遇到的需求做下的决定!!!

3 树形查找

3.1 二叉排序树(BST)【缩写注意!】

定义

中序遍历就是 左中右!可以写出递增的序列!

查找代码

普通代码

成功:

失败:

T = T->rchild会等于NULL 这是这个循环就结束了 返回NULL

加入递归代码

两个代码的空间复杂度

递归要使用函数调用栈 需要的大小 是树的高度!

插入

当T为NULL时说明找到了 应该插入的位置!

一定注意这个数BSTree是引用类型的!!!!

构造二叉排序树

删除
1、删除叶子结点

2、只有一个左子树或右子树

删完连起来就行

3、既有左子树又有右子树

!!!详情见 数据结构(5):树和二叉树-CSDN博客 中的6.2

50 的直接后驱是60 这个60肯定是右子树总最小的结点 而且一定没有左子树(因为一旦有左子树说明还有一个比它小!)

让60代替50 然后删除60 这个结点 因为原60 是在最左下的所以没有左子树,回到第二种情况了,删了之后连起来就行!

当有直接前驱也是一样的:直接前驱说明是左子树中最大的,一定没有右子树,替代50后还满足二叉排序树的原则,删原来的30 后 后面右子树的话直接连上即可没有就算了

查找效率分析

查找长度

对比:就意味着一次循环或者递归

查找成功

对比的次数不会超过二叉树的高度!

所以

的效率是最高的

查找失败

失败的时候空时不要对比的,只有和关键字比较的时候 加查找长度!!!!!

总结

3.2 平衡二叉树(AVL!)

上面的排序树的时候 知道越胖胖的效率越高 而平衡二叉树就是胖胖的!!!

平衡二叉树(AVL定义)

左右子树高度差不超过1!!

当保证是平衡二叉树是,二叉排序树的查找效率可以达到

插入

关键是如何插入一个结点 还能保持平衡!

调整的对象是“最小不平衡子树!”

如何调整最小不平衡子树

1、LL

三个子树高度一定全是H

这样才能保证LL插入后A变成 最小 不平衡 子树!why?可以假设:

AR是H+1时 LL插入 A 的左右子树 只差1还是平衡;AR是H-1 A就不平衡了直接

当BR=H+1时 A 直接就是不平衡的;当BR=H-1时,LL插入后 BL和BR相差2 则里插入点最近的不平衡点B就变成了最小不平衡子树 !!不是A了

调整目标

解决方法:右旋

2、RR
解决方法:左旋

12 代码

gf意思就是与前面连起来的那些树!

顺序:爹的左/后 孩子的左/右 孩子变爹!

3、LR
解决办法:左旋+右旋

4、RL
方法:右旋+左旋

汇总

练习:

1、

2、

3、

查找效率
递推公式!!!

得到最少的结点 并且左右节点高度相差1

平均查找长度(ASL)

插入总结

删除

步骤

二叉排序树的删除满足了条件1!!!

例题
eg1 不需要调整

eg2 

检查上面的结点是否因为这个而产生了不平衡的现象!!!

eg3

eg4 不平衡向上传导

eg5 删除时按照二叉排序

直接前驱和后继

前驱:从左孩子的右边一路向下!

删除之后:

删除总结:

3.3 红黑树(RBT)【no代码】(搜搜23年咋考的)

为什莫出现?

都在使用红黑树!!!!

所以重点就是定义、性质、手算插入!

定义

红黑树是二叉排序树!

5个要求

增加父节点指针!

顺口溜:

左<根<右

根叶黑:根节点和叶子结点是黑色的!

不红红:不存在相邻的红色结点!

黑路同:(一条路走到黑)从同一个顶点到任何一个叶子结点的过程中 路过的黑结点的个数相同!

例子:

叶子节点是失败的那种节点

出题思路:

黑高

根节点黑高是2

与“黑高”相关的推论:

满树--黑路通;所以最小的情况就是全黑的满二叉树!

就可以证明下方的性质2:

性质!!!!!!!!!![一定注意这个!]

2、

n个关键字!

红黑树的查找效率不会超过红黑树的高度 所以反映了

时间复杂度

查找

插入!!

AVL(平衡二叉树的插入!)

找到位置---最小平衡子树---旋转--使其重新平衡

策略:

父亲的兄弟就是叔叔!

旋转是一样的!

插入的非根结点染红是为了满足 黑路同 这个特性!

动谁染谁 往相反的方向染!

会破坏的只有“不红红”!!!

。。。。。。

。。。。

最后的结果:

插入总结:

红黑树对于左右子树的要求没有那麽严格!

删除

我真服了啊啊啊啊啊啊啊!没事哒没事哒没事哒!

时间复杂度!O(log_2(n))

 3.4 B树

人如其名......

查找例子1【成功】

“走左边!”的感觉

当叉数比较多的时候!

查找例子2【失败】

如何保证查找效率

策略:

根节点是例外!!!!

策略2:

B树定义【满足两个策略】

高度都相同就是绝对的平衡。。。。

失败的结点还是叫叶子节点!

核心性质!!!!【选择】:

B树高度:

排除叶子节点!

最小高度:

最大高度:

高度越大说明 每个结点半酣的关键字和分叉尽可能的小

下边这个好理解一点哦

总结:

插入的时候根节点全凭运气,所以不一定整整好在那个范围里!

B树的插入:

一直插插插到超过时进行:

在这个基础上插一定插到最底层:

再插插插超过的话:

中间的那个元素插入到父节点里!

再插插插:

提出去的那个元素应该插入父节点的位置是 箭头链的那个位置!

再插插插:

父节点!超过!!

总结插入:

B树删除:

再非终端节点:

最左子树最右下的就是直接前驱,用这个替代!

把删除非终端转换成删除终端!

也可以使用直接后继:

用82顶替77

再删:

删38 之后低于下限了

兄弟够借的时候:

只有这样才能表示才能保证B树的特性不变(就是那个大小顺序!)

再删:

删90的时候

再删:

兄弟不宽裕 就两个人合体 删49

当兄弟没钱的时候总结:

插入和删除总结:

3.5 B+树【概念性的】

和分块查找很类似

保存每一层最大的关键字!

满足的条件

2)当根节点不是叶子的时候,那么他至少有 m/2 向上取整棵 子树!

3)第3个和B树是很不一样的,容易出选择题:再B树中 两个关键字就会有3个分支!而在B+树中分支【子树】树和关键字的个数相同!

4)叶子结点包含所有的关键字!!!还有指向记录的指针

B+树的查找

从根节点逐层向下

必须到最下面才查找结束!!!

但是B树就不用查找到最后一层!!

顺序查找

B树 vs B+树

不要求的内容:

只有放进内存里才有会进行读!

一个一个结点都存储在磁盘里,当这个关键字不存储对应的存储地址时,他的size就更小更方便,那么就会有更多的数据存储在磁盘里!

这就是B+和B最本质的区别!

总结:

4 散列查找

4.1 定义

4.2 处理冲突的方法-拉链法

小优化:

查找

对比关键词的次数才算到查找长度里!

平均查找长度ASL

成功:

失败:

装填因子

装的满不满的指标!

4.3 常见的散列函数【让冲突尽量减小提高查找效率!】

与质数相对的概念式合数!质数的因子只有1和自己

为什么一定要是质数?!

直接定址法:

不连续的话空位就很多

数字分析法:

平方取中法:

用空间换时间的算法

4.4 处理冲突方法2--开放定址法

线性探测法:

就是一个一个向后找直到有空的位置!

注意一个小细节!!!:

查找

同义词和非同义词都有可能发生冲突!!! 68 不是27的同义词但也被扫描了

这里的空位置算作一次比较次数,但是在处理冲突的方法1-拉链法里没有把与空算作一次对比,是因为那里的空位置存储的是一个空指针 不算;这里的空位置可以视为存储的是相同的数据类型的东西,因此算作一次次数!

删除

删除是要特别注意,要不然删了之后空了下次查找的时候就以为没有了,比如这个

解决方法:

删除的元素做一个标记 可以是一个bool型的变量 这样就可以让指针继续向下走了

查找效率分析(ASL):

成功:

就一个一个算.......

失败:

为什么?

同义词和非同义词堆积!

平方探测法

查找也是按照这个散列的序列

非重点小坑【探测到所有位置!】:

伪随机序列法

总结

开放定址法删除结点时要特别注意哦!!!

4.5 处理冲突法3-再散列法

王道上可能是错了

4.6 大总结:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/921845
推荐阅读
相关标签
  

闽ICP备14008679号