数据结构:第七章学习小结
第七章学习了查找。这一章的内容是基于不同数据结构的查找,每一节之间的内容是平行的,所以这一章按每一节的顺序来整理。
第一节主要认识了在接下来的三节中会用经常被提及的专业词语。接下来是详细的各种查找方法。
一、线性表查找——顺序查找、二分查找、分块查找
为了使接下来的三个查找方法更易于理解和分辨,给出一串数值例子{1,2,4,6,9,15,27}
1、顺序查找
(1)顺序查找的时候是可以不按顺序存储的,那我们假设得到的输入顺序是按题目所给的非降序,现在我们让这个数组非升序排序,从数组a[1]开始存储第一个数,a[0]置空。(为什么呢?1很显然不用移动,所以从2开始,按非升序排序,2应该在1之前,所以我们先将2存到a[0]——再将1移动到2的位置a[2]——再将2放到a[1],这样才算完成一次)。
另一个比较特殊的地方是:可以将关键字存入表头,从后往前比较,这样可以免去查找过程中每一步都检测是否查找完毕,并且可以防止越界。
平均搜索长度ASL(查找概率相同):能够成功找到:ASL(n)=(n+1)/2; 不能够成功找到:ASL(n)=n+1。
(2)二分查找
二分查找的特殊点:输入顺序是有序的!而且要增加low mid high值来辅助,二分查找有递归算法
值得注意的是,low、mid、high的值的变化如下表(假设有n个数)
初始化:low=1, mid=(1+n)/2, high=n 重复下述操作至low>high If k==a[mid].key 查找成功 k<a[mid].key high=mid-1; K>a[mid].key low=mid+1 |
在前提每个被搜索到的概率都相等的情况下ASL=O(log2 N)
尽管ASL相对顺序查找小了很多,二分查找仍有很多局限性:
a.能且只能适用于顺序表查找;
b.只能够针对静态数组;
c.不适用于数据量小的数组(没必要,顺序查找足够用)
d.不适用于太大的数组(因为二分查找只适用于连续的空间的顺序表,但是太大的连续的空间不够存的)
3.分块查找
块间有序、块内无序,比如分成三块
1,4,2| 9,6| 15, 27
适用于既要快速查找,又要动态变化的情况
二、树表的查找(针对动态数据)
1、二叉排序树
左子树非空时,左子树上所有结点值均小于根结点,右子树均大于根结点
时间复杂度O(log2 N);ASL=O(树的高度)
可以用链表存储;
有可能会生成单支树,于是出现了平衡二叉树
2、平衡二叉树
树的高度保持在log2N数量级;左右子树皆为平衡二叉树,左右子树高度差不超过1
因为ASL和树的高度有关,为了降低ASL,就有了多叉树
3、多叉树
每个结点存储的数值更多,子结点更多
4、B树
平衡的多叉树
5、B+树
在第一个叶结点上有个头指针,每个叶子节点都有指针相连,可实现精确查找
三、基于散列表的查找
1、记录在数组中的存储位置p与其关键字key之间存在对应关系:H(key)=p
2、时间复杂度为O(1)
3、但是,会有冲突发生,即两个key有同一个位置,这两个key互为同义词
那么如何构造好的散列函数,使发生的冲突最少?
最常用的是除留余数 ,Hash(key)=key mod t(t最好为大于数据个数的最小质数)
发生冲突之后,如何处理?
开放地址法以及链地址法。
下面详细介绍开放地址法
四、下周学习计划
眼看着马上上就要到周末了,希望在下周开始,每天能够坚持复习一两道前几章的PTA题目!
加上这几周的学习不太侧重个人编写代码的能力,能够复现一下书上的也是一种很好的锻炼。