查找包括线性表的查找、树表的查找、哈希表的查找
1.查找表的定义
由一组记录组成的表或者文件,每个记录由若干个数据项构成,假设每个记录都有一个唯一能标识该记录的关键字。
内查找和外查找
若整个查找都在内存中进行,就是内查找,如果需要访问到外存的话,就是外查找。
查找的数据组织
-顺序表
-链表
-其他
如果在查找的过程中涉及到表的插入、删除操作,这个称为动态查找表,否则就是静态查找表。查找的性能指示
在于关键字的查找次数,也就是平均查找长度。
平均查找长度,又分为成功查找下的平均查找长度和失败的平均查找长度。
在无序表中查找失败的ASL是n+1,因为在表中尾部(或头部)加入了一个辅助的符合查找条件的“哨兵”,然后从新表的另一头开始查找,此时新表长度为n+1。 原表长度为n,下标范围为0到n-1,如果查找到返回的值为n(头部时为0),即原表中查找失败。此时与新表中的所有元素都比较过,故为n+1。加入“哨容兵”的好处是不需要再考虑判断数组越界的问题,如果不加入“哨兵”,还需考虑数组下标越界问题,比较次数更多。
2.线性表的查找
(1)顺序查找 (2)二分查找 (3)分块查找(基于索引存储结构)
-顺序查找
从左到右,顺序扫描线性表,将关键字和给定的K值比较,就是平常我们使用的暴力法。属于无序的查找算法。
(字写得很难看,忽略忽略…)
不成功的查找次数的话是n+1次,因为会在尾部加哨兵,比较到n的位置时,相等,退出,输出n,说明查找失败。数组下标的范围是0-n-1
-二分查找
要求这个线性表中的记录必须是有序的。
使用low+(high-low)/2是为了避免溢出。
二分查找可以用二叉树来表示,把中间位置设为根,左右区间设为左右子树,这样的树称为比较树或者判断树。(其实就是二叉搜索树)
外部结点是查找失败的点,正好是内部结点+1个。
-索引存储结构和分块查找
索引的存储结构=数据表+索引表
索引表由很多索引项构成,每个索引项由关键字+地址构成。
关键字+地址构成了索引表,索引表底层是由一个数据结构形成的,这个就对应数据库索引那块。用索引号来表示存储地址。
-分块查找
整块是无序的,那么可以分块有序(组成索引表是有序的)。为每一块建立一个索引项,然后组成一个索引表。
四种存储结构
分块查找可以按照最小关键字排序
分块查找介于顺序查找和二分查找之间
3.树表的查找
注意:我下面有写错字,树的结点应该改为节点二字。
以二叉树或者树作为表的组织形式,称为树表,它不仅适用于表的查找,而且适用于表的插入、删除操作,所以是动态查找表。
(1)二叉排序树 (2)平衡二叉树 (3)B树、B+树
-二叉排序树
二叉排序树的查找可以看作是中序遍历的结果(有序表的)查找的过程,和二分查找类似。
一种递归的表示二叉排序树的形式
非递归的写法
二叉排序树的插入
非递归的解法是:
创建二叉排序树的代码
任何结点的插入都是以叶子结点插入的
根结点的最左下的结点是最小值,最右下的结点是最大值。
二叉排序树的删除
(1)如果删除的是叶子结点,那么直接删除结点,并且将父亲结点置为null
(2)被删除的结点的孩子结点只有左子树或者右子树,那么用左子树或者右子树替换它。
(3)被删除的结点既有左子树又有右子树,有两种方式:
一种是在左子树中找关键字最大的元素,替换它
或者在右子树中找最小的结点,替换它。
既没有左右子树的话,直接delete
直接覆盖会有问题。
非递归的删除可以参考以下链接:
二叉搜索树的查找、插入、删除非递归方法
(2)平衡二叉树
如果一个树的左右子树的高度差的绝对值<=1就说明是AVL树,平衡因子是左子树的高度减去右子树的高度。
平衡二叉树的插入
和二叉排序树相似,但是如果不平衡的话,就要进行调整。分为四种调整
这里的调整和红黑树的调整次数不一样,可以参考
红黑树
- LL调整
- RR调整
- LR
- RL调整
通过和斐波拉契数列一样的规律,得出高度为logn
(3)B树、B+树
B树又称为多路查找树,是一种组织和维护外存文件系统非常有效地数据结构。
外部结点时查找失败的点。
至少有1个关键字,叶子结点没有孩子结点
B树地存储结构是链式的
插入结点如果没有空位置,就裂开。
这个B树的插入过程可以参考以下链接
B树的插入、裂开
Question:
1、在B树中每插入一个节点,要先判断该树中是否已有该结点,有的话就不需要新建节点。
2、在B树中插入一个节点,如果裂开的话,树节点网上走,树的高度不变。
现在左边找到一个最大关键字12替换13,然后将12这个节点删掉
在叶子节点删除元素的情况
B+树
所有的叶子结点包含了所有的关键字,用顺序的方式进行链接存储。
有两种查找方法,一种从根节点开始查找,另外一种从叶子节点顺序查找。
3.哈希表的查找
(1)直接定址法
(2)除留取余法
选取质数是因为质数不是大多数元素的构成的基本元素
(3)数字分析法
怎么解决哈希冲突?
开放定址法,找一个空位放进去
通过key来找哈希表的位置
找到对应的位置后,在链表中顺序查找。