7.1 查找的基本概念
基本概念
查找表不是某一种特定的、指定的数据结构,他只是对于你要执行查找操作的数据结构的统称而已。
常见操作(查找、插入、删除)
查找算法的评价指标
7.2-1 顺序查找
顺序查找的实现
顺序查找的实现(数组0位置使用哨兵)
顺序查找的优化
将查找表的元素有序存放
将被查概率大的放前面
7.2-2 折半查找
折半查找适用于有序的顺序表(不是链表)
折半查找代码实现
查找效率分析
折半查找判定树的构造
下图取mid的上限,上图取mid的下限。
平衡树(Balance Tree,BT) 指的是,任意节点的子树的高度差都小于等于1。
顺序查找不一定比折半查找慢
7.2-3 分块查找
分块查找的算法思想
用折半查找查索引
查找19
19<30, high=mid-1,mid=(low+high)/2
19>mid,low=mid+1
19<mid=20,high=mid-1,此时high<low
上面,在low>high前是low=high=mid,如果key(比如等于19)<mid(比如在这取20),那么low不移动,high往前移动一格。则如果我们查找key需要在low所指的分块中查找。
下面,在low>high前是low=high=mid,如果key(比如等于21)>mid(比如在这取20),那么low往后移动一格,high不移动。则如果我们查找key需要在low所指的分块中查找。
综上所述,若索引表中不包含目标关键字,则折半查找索引表最终停在low>high,要在low所指分块中查找。
查找21
21<30,high=mid-1,mid=low+high
21>mid,low=mid+1,mid=(low+high)/2,此时low=high=mid
21>mid,low=mid+1,如下图
若索引表中不包含目标关键字,则折半查找索引表最终停在low>high,要在low所指分块中查找。
查找效率分析
顺序查找查索引表
折半查找查索引表
若查找表是动态查找表(采用链式存储)(也利于添加删除元素)
7.3-1 二叉排序树
二叉排序树的定义
二叉排序树的查找
二叉排序树的插入
二叉排序树的构造
构建二叉排序树就是不断插入新节点的过程。
二叉排序树的删除
1、如果被删除结点是叶子节点
2、结点只有一棵左子树或右子树
3、若删除的结点既有左子树,又有右子树
用直接后继替代
用直接前驱替代
查找效率分析
7.3-2 平衡二叉树
平衡二叉树的定义
二叉排序树保持平衡可以保证二叉排序树的查找效率可以到达O(log2 n)数量级
在插入新结点后,如何保持平衡?( 调整最小不平衡子树)
调整最小不平衡子树
LL
这里我们假设在进行操作之后A结点是最小的不平衡子树。
只有要求AR、BL、BR都是高度H才能满足 进行操作之后A结点是最小的不平衡子树的假设。
如果AR、BL、BR中有其中某个或某些变换高度为H+1或H-1,则会出现可能不需要操作就是不平衡子树的情况或者操作之后还是平衡子树的情况或者操作之后B结点是最小的不平衡子树的情况。可自行试验验证,由此可知需要假定所有子树的高度都为H。
RR
LL和RR的代码思路
LR
下图不论是 加到BR(即C)的右子树了还是BR(即C)的左子树,进行的操作都是一样的,都是先进行左旋C再右旋C。(后续调整RL同理)
RL
调整最小不平衡子树 小结
填个坑
插入操作前是平衡树,插入后由于“最小不平衡子树”的高度变化了,导致了整个平衡树不平衡,经过调整后,“最小不平衡子树”变得平衡,该“最小不平衡子树”的高度经调整后恢复,也就恢复了整个树的平衡。
一些练习
练习1(RR型)
练习2(RL型)
练习3(LR型)
查找效率分析
假设以nh表示深度为h的平衡树中含有的最少结点数。
深度h=0,没有结点,nh=0,
深度h=1,有一个结点,nh=1,
深度h=2,最少有两个结点,一个根节点,加一个左孩子或一个右孩子,nh=2,
深度为h的平衡树,最少有一个根节点 加 一个深度为h-1的子树 加 一个深度为h-2的子树,n(h-1)和n(h-2)分别表示深度为h-1的平衡树中含有的最少结点数 和 深度为h-2的平衡树中含有的最少结点数。这样n(h-1)+n(h-2)+1正好表示深度为h的平衡树中含有的最少结点数。
7.3-3 平衡二叉树的删除
平衡二叉树的删除 案例
1、删除结点
2.1没找到最小不平衡子树,完结撒花
从被删除节点那一路往上找(或者从调整后仍不平衡的子树那往上找),找到第一棵子树。
2.2 找到最小不平衡子树了
删除的是 55
3、在最小不平衡子树下,找个头最高的儿子孙子(如果个头最高的儿子或孙子有多个,那么任选一个即可)
4、根据孙子的位置,调整平衡
5、如果不平衡向上传导,继续2
未出现不平衡向上传导,结束。
复习 二叉排序树如何删除结点
例1 用后继结点替代
删除结点75,
用后继结点77替代,由于77是叶子节点,可以直接删除。
例2 用前驱结点替代
删除结点75,用前驱结点60替代,因为被删除的结点60只有左子树,用子树替代删除位置即可。
平衡二叉树删除操作时间复杂度
7.3-4 红黑树的定义和性质
为啥要发明红黑树?
红黑树的定义
红黑树是二叉排序树,满足左小于等于根小于等于右的特性。
不存在两个相邻的红结点,但是允许有两个相邻的黑结点。
红黑树的性质
性质1:从根节点到叶结点的最长路径不大于最短路径的2倍。可由④,⑤推出
④不存在两个相邻的红结点(即红结点的父节点和孩子结点均是黑色)
⑤对每个结点,从该节点到任一叶结点的简单路径上,所含黑结点的数目相同。
对于每个结点,从根节点出发到任一叶结点所经过的黑节点数量都是相同的,但是在这条路上,要求不能存在两个相邻的红结点。红色的结点只有可能穿插在黑结点中。路径最长的情况肯定就是红结点穿插在每一个黑结点的中间,路径最短的情况就是只有黑结点。
红黑树的查找
7.3-5 红黑树的插入
该红结点在他爷结点的左孩子的左边,所以是LL.
左根右,根叶黑,黑路同,不红红 四个原则中,左根右,根叶黑是不会被破坏的,由于插入非根节点都先涂成红色,该红结点的插入并不会导致他上方的任何一个结点的黑路变长,所以黑路同 这一原则也不会被违背,只有不红红可能被违背。所以我们插入结点后只须判断不红红就好了。
将爷结点视为新节点,如果红黑树没有被继续破坏,那么被视为新节点的这个爷结点不需要发生变化。
下图由于爷结点30不是根节点,所以不用必须是黑色,该爷结点呈红色并没有破坏红黑树,所以呈红色即可,也保证了黑路同 这一原则。
(这里不是特清楚,应该是将该爷结点视为新结点,又因为该爷结点不是根节点,所以是红色)
上图左、右双旋转指的是:先结点23左旋换到父节点22这个位置,在右旋换到爷结点25这个位置。
下图是将叔父爷染色后,出现了新的“不红红”
下图儿结点23,父节点20,爷结点30
总结
与黑高相关的推论
7.3-6 红黑树的删除
红黑树删除比红黑树插入难的多,
在这先不展开讲解 红黑树的删除操作了。仅先知道以上几点即可。
红黑树22年加入408考纲。
7.4-1 B树
B树的引入
查找目标9,先对比22,小于22沿着22左边的分叉下去,和5进行比较,大于5,和11比较,小于11,从5和11中间的分叉下去,和6比较,大于6,和8比较,大于8,和9比较,等于9,查找成功。
查找目标9,先对比22,大于22沿着22右边的分叉下去,和36进行比较,大于36,和45比较,小于45,从36和45中间的分叉下去,和40比较,大于40,和42比较,小于42,从40和42中间的分叉下去,是null是空,查找失败。
B树的定义(B树可以降低树的高度,提高查询效率)
B树的特性
B树的最小高度、最大高度
最小高度
最大高度(第一种求法)
下图:n个关键字的B树必有n+1个叶子结点,n个关键字相当于在(-∞,∞)中插入了n个关键字,n个关键字会把整个数值区间分割为n+1个部分,这n+1部分就相当于n+1种失败的情况,所有这些有可能出现的失败情况都会体现在叶子结点(失败结点)中,所以失败结点(叶子节点)的个数也是n+1个。
下图这个为何大于等于我暂时不能理解,
最大高度为h的m阶B树的第h+1层共有叶子节点有,n个关键字的B树必有n+1个叶子结点,那么即可认为
得到,因为最大高度才可能是这个,那么实际高度h是小于这个的,从而得出了
最大高度(第二种求法)
B树的高度的范围
总结
7.4-2 B树的插入删除
B树的插入
B树的删除(以下为一个整体、一个例子)
直接删除是终端节点
删除非终端结点
对非终端结点关键字的删除,必然可以转化为对终端结点的删除操作。所以下面我们主要讨论对终端结点的删除。
删除终端结点并低于下限(兄弟够借)
删除终端结点并低于下限(兄弟不够借)
总结
7.4-3 B+树
B+树概念
对于第2条,非叶根节点,以下。
B+树中的查找
多路查找
查找成功
从根节点出发,9小于15,15表示他所指向的一整个分块当中最大的是15,沿15这个分叉下去寻找,和3比较,大于3,指针后移,和9比较,等于9。在B+树中,如果只是在分支结点中,找到我们想要找的关键字,那我们的查找并没有结束,因为9号的实际信息存放在哪,我们只有找到最下层的叶子结点之后才可以找到这个数据,这个信息。所以指针继续往下移,然后从左往右依次检查,对比6,8,9,找到9,通过9这一项保存的指针信息,就能找到9号结点的详细信息。
查找失败
查找7,先和15比较,小于15,沿着指针去下面找,和3比较,7大于3,和9比较,7小于9,沿着指针去下面找,比较6,7大于6,比较8,7小于8,由于此时已经是最下层结点了,所以还没找到7,那么7就是在这里面不存在的。查找失败。
对比B树查找
顺序查找
直接从p指针那开始比较,和1、3、6、8、9分别比较,结点9等于9,在9的位置停下,向下查询记录,获取该结点详细信息。
B+树vsB树
区别1
区别2
区别3
区别4
区别5(有关操作系统,之后再自行查询深入理解)
下图中“B+树的阶”中的阶就是5阶、6阶,每个结点最多有几个关键字的意思。
总结
下图谈到B+树类比于分块查找,我感觉是在分块中,比如在[20,30]这块中查找30,那么比对30知道在这块后,在这块里面还能找到30。
7.5-1 散列查找(上)
哈希表定义
处理冲突的方法(拉链法)
拉链法示例
查找元素举例(查找成功)
查找元素举例(查找失败)
平均查找长度的计算(在拉链法下)
查找成功的平均长度
查找失败的平均长度
查找失败,假定查找失败的关键字映射到任何一个地址的概率都是相同的,总共可能映射到0到12共13个地址,每种可能是1/13.
装填因子越多,散列表装的越满。
常见的几种散列函数
除留余数法
直接定址法
数字分析法
平方取中法
解释一下均小于散列地址所需的位数,比如要存储关键字1000,2000,3000,但是散列地址是从10000到30000,那么关键字1000,2000,3000均是4位,均小于散列地址10000到30000的5位,那么就需要平方来扩大位数。
而中间绿色方框的数字和1200这个关键字的每位都相关。
7.5-2 散列查找(下)
处理冲突的方法(开放定址法)
线性探测法
插入1时发生冲突,经过计算后插入2位置。
下图:H(key)=27%13=1,H0=(1+0)%16=1,H1=(1+1)%16=2,H2=(1+2)%16=3,H3=(1+3)%16=4,
哈希函数 H(key)=key%13值域 [0,12]
冲突处理函数 H=(H(key) + d)%m值域 [0,15]
查找操作
查找成功
查找失败
遇到空位置
查找中遇到空位置(不过这个空位置是删除结点后留出的空位置)
查找效率分析
查找成功ASL
查找失败ASL
平方探测法
查找元素
非重点小坑:散列表长度m必须是一个可以表示成4j+3的素数,才能探测到所有位置