顺序查找、折半查找、分块查找
目录
一、查找的基本概念
二、顺序查找
一般线性表的顺序查找
有序线性表的顺序查找
三、折半查找
折半查找的算法
判定树
四、分块查找
一、查找的基本概念
- 查找:在数据集合中寻找满足某种条件的数据元素的过程称为查找。查找的结果一般分为两种:一是查找成功,即在数据集合中找到满足条件的数据元素;二是查找失败。
- 查找表(查找结构):用于查找的由同一类型的数据元素(或记录)构成的集合。查找表本质是表中记录之间仅存在"同属一个集合”这个逻辑的集合结构。为此,我们在数据元素之间人为地加上一些关系,以便按照某种规则查找,即用另一种数据结构来表示查找表。
- 对查找表进行的操作一般有四种:①查询某个特定的数据元素是否在查找表中;②检索满足条件的某个特定的数据元素的各自属性; ③在查找表中插入一个数据元素;④在查找表中删除某个数据元素。只作前两种查找操作的查找表为静态查找表;可以作上述四种操作,即在查找过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素的为动态查找表。
- 关键字:数据元素中可以标识元素的某个数据项的值。主关键字可以唯一标识一个记录,次关键字可以识别若干记录。使用基于主关键字的查找,查找结果应该是唯一的。
- 平均查找长度:为确定记录在查找表中的位置,需和给定值进行比较的关键字个数的期望值:
- ASL=
- (Average Search Length),
为表中第i个元素被查找的概率,
是将它查找成功所用的比较次数。一般认为每个数据元素的查找概率相等,即
= 1 / n 。ASL是评价查找算法好坏的重要指标。一般查找成功的可能性比查找不成功的可能性要高地多,但当查找不成功的情形不能忽视时,查找算法的平均查找长度为查找成功时的平均查找长度和查找不成功时的平均查找长度之和。
二、顺序查找
顺序查找:又称线性查找,它对于查找表以链表或数组存储都是适用的。顾名思义,沿着表中的顺序关系扫描每个元素。通常分为对无序线性表的顺序查找和对按关键字有序的线性表的顺序查找。
一般线性表的顺序查找
其基本思想是从线性表的一端开始,逐个比较检查关键字是否满足条件。若查找到满足条件的记录则查找成功,若按顺序查找完整个表还未查找成功则查找失败。下面给出算法代码:
typedef struct{ElemType *elmem;//存储表中记录的数组的基址,0号位置留空int TableLen;//查找表表长 }SSTable;//查找表的数据结构 int Serach_Seq(SSTable ST, ElemType key) {ST.elem[0]=key;//哨兵位置为待查找关键字大小for(int i=ST.TableLen; ST.elem[i]!=key;i--);//从数组尾部往前查找,直到找到符合条件的记录return i;//返回查找到元素的下标,若返回0代表查找失败 }
哨兵位的作用是为了在for循环判断跳出条件时不必比较下标 i 是否越界,提高程序的效率。在直接插入排序中也可以用到哨兵位。
查找表中一共n个元素,对于上述算法查找第 i 个记录,我们需要比较n-i+1次,假设每个记录被查找的概率相同:
查找成功时的ASL=
(n-i+1)=
=
查找失败时的ASL=n+1(使用哨兵位时除了跟表中每个记录比较之外还和哨兵位比较,不使用哨兵位时也要多比较一次判断越界)
对于每个记录被查找概率并不相等的情况,我们令表中记录按查找概率重新排列,使得查找概率较大的记录被查找所比较的次数较小,能够减小平均查找长度。
有序线性表的顺序查找
如果查找表中的记录按关键字大小有序排列时,我们在循环比较时如果发现查找表中剩下的未比较记录已经不可能查找成功时,应直接退出查找,即查找失败。下面给出算法代码:
typedef struct{ElemType *elmem;//存储表中记录的数组的基址,0号位置留空int TableLen;//查找表表长 }SSTable;//查找表的数据结构 int Serach_Seq(SSTable ST, ElemType key) {//有序表中记录大小是从小到大排序的ST.elem[0]=key;//哨兵位置为待查找关键字大小for(int i=ST.TableLen; ST.elem[i]>key;i--);//从数组尾部往前查找,当查找到不比key大的记录时退出if(ST.elem[i]<key) return 0;//判断是找到了退出循环还是再也找不到了退出循环return i;//返回查找到元素的下标,若返回0代表查找失败 }
对于查找成功时的平均查找长度和一般线性表的顺序查找并无不同。
对于查找失败时的平均查找长度有了较大改进,我们按退出循环时已经比较关键字的次数能够划分出n+1个区间,打个比方,假设查找表为{10,20}则我们的失败区间为(- ∞,10)(10,20)(20,∞)这三个区间,可以看到第一个区间的比较次数为1,第2个第3个都为n次,推广到一般情况: ASL=
=
=
+
其中我们假设每个失败区间中关键字被查找的概率相等。
三、折半查找
折半查找:又称二分查找,它仅适用于有序的顺序表。
折半查找的算法
算法思想:首先将给定值key与有序表中间位置记录比较,若相等则查找成功;若不相等,我们只需查找中间元素前半部分的记录或者后半部分的记录即可。如此重复,直到查找成功,或确定表中没有所需查找的记录,则查找不成功。算法如下:
int Serach_Binary(SeqList L, ElemType key) {//有序表中记录大小是从小到大排序的int low=0,high=L.TablenLen-1,mid;while(low<=high){mid=(high+low)/2;//取中间位置if(L.elem[mid]==key)return mid;//查找成功else if((L.elem[mid]<key)low=mid+1;//从后半部分继续查找else high=mid-1;//从前半部分继续查找}return -1;//返回-1代表查找失败 }
因为折半查找需要方便地定位查找区域,所以它要求线性表有随机存储的特性,因此,该方法不适合于链式存储结构。
判定树
折半查找的过程可以用下图所示的二叉树来描述,称为判定树。树中非终端结点都是代表能查找成功的记录,树中叶子结点代表查找不成功的情况。它满足下列条件:
1.查找成功时的比较次数为从该结点到根结点的路径长度与该结点进行的一次比较之和。
2.查找失败时的比较次数为从该结点到根结点的路径长度。
3.若有序序列有n个元素,对应有n个非终端结点和n+1个叶子结点。
4.每个结点的值都大于其左孩子结点的值,小于其右孩子结点的值。
上图这个判定树找中间值的操作是 (low+high)/2,它在有偶数个记录时中间值会落到靠左的位置。所以上图我们在{7,10}中选择了7,并且10成为了7的右孩子结点。
事实上我们可以这样取中间值⌈(low+high)/2⌉,符号内为浮点数,这样它在有偶数个记录时中间值会落到靠右位置,此时判定树如下图:
因此,得到规律:
- 若mid=⌈(low+high)/2⌉时,对于任意一个结点,必有左子树结点数-右子树结点数=0或1.
- 若mid=⌊(low+high)/2⌋时,对于任意一个结点,必有右子树结点数-左子树结点数=0或1.
- 对于给定有序表,其判定树的树形只有两种情况(代码不同),当代码明确时,二分查找的判定树唯一。
用折半查找法查找给定值的比较次数最多为不会超过该二叉树的高度⌊ logn⌋+1(⌊ logn⌋表示不大于X的最大整数)(比较次数为高度是说明非终端结点在最后一层)
当n=2^h-1时,即满二叉树时,查找成功时折半查找的平均查找长度如下:
折半查找的时间复杂度为O(logn),平均情况下比顺序查找效率高。
四、分块查找
分块查找又称索引顺序查找,它吸取了顺序查找和折半查找各自的优点,既有动态结构,又适合快速查找。
分块查找的基本思想:将查找表分为若干块,块长不定,块内可以是无序的,但是块之间是有序的,即前一个块中的最大关键字小于后一个块中的最小关键字。为此我们建立一个索引表包含如下所示信息:
最大关键字 22 48 86 起始地址 1 7 13
分块(索引顺序)查找的过程:
- 在索引表中确定待查记录所在的块,可以按顺序查找或折半查找索引表
- 在块内顺序查找。
分块查找平均查找长度为索引查找和块内查找的平均查找长度之和:
将长度为n的查找表均匀地分为b块,每块有s个记录,在等概率情况下,
对索引表采用顺序查找,则平均查找长度为:
ASL=
+
=
+
=
, 当s=
时,ASL(min)=
+1
对索引表采用折半查找,则平均查找长度为:
ASL=
+
=⌈
⌉+
顺序查找、折半查找、分块查找相关推荐
- 数据结构之查找算法:分块查找
查找算法:分块查找 思维导图: 分块查找的定义: 如何分块: 如何查找: 代码实现: 查找效率: 思考: 思维导图: 分块查找的定义: 如何分块: 例: 如何查找: 1.先查找在哪块 2.然后查找块内 ...
- 索引顺序表查找算法(分块查找)
算法背景 有时候,可能会遇到这样的表:整个表中的元素未必有序,但若划分为若干块后,每一块中的所有元素均小于(或大于)其后面块中的所有元素.我们称这种为分块有序. 对于分块有序表的查找 首先,我们需要先 ...
- 查找算法3——分块查找
分块查找 对给定序列8.13.25.19.22.29.46.38.30.35.50.60.49.57.65.70.89.92.70,设计一个分块查找算法,查找指定的元素. [算法思想] 分块查找也称为 ...
- C语言两种查找方式(分块查找,二分法)
二分法(必须要保证数据是有序排列的): 分块查找(数据有如下特点:块间有序,块内无序): 转载于:https://www.cnblogs.com/zhaihongliangblogger/p/6171 ...
- 设计一个程序,在顺序表中采用分块查找发查找关键字。
#include"iostream" using namespace std; class list{ private:int data[30];int length;int ke ...
- 线性表查找之二分查找(折半、对分查找)
特点: 前提是对有序的一组元素进行查找 每次将待查记录所在区间缩小一半 代码: 不断的缩小范围: #include <iostream> #include <assert.h> ...
- 数据结构之查找-顺序查找,折半查找,分块查找
文章目录 一.顺序查找 1.1 无序表的顺序查找 1.2 有序表的顺序查找 二.折半查找 三.分块查找 一.顺序查找 顺序查找又称线性查找,主要用于在线性表中进行查找. 1.1 无序表的顺序查找 对无 ...
- 408数据结构学习笔记——顺序查找、折半查找、分块查找
目录 1.顺序查找 1.1.顺序查找的概念 1.2.顺序查找的代码 1.3.顺序查找的查找效率 1.4.顺序查找的优化 1.5.顺序表的时间复杂度 2.折半查找 2.1.折半查找的概念 2.2.折半查 ...
- 查找(顺序查找,折半查找,分块查找)
查找 查找是在查询数据过程中必不可少的一个环节,那么如何来进行查找,以及如何进行高效率的查找,就是接下来要解决的问题. 文章目录 查找 查找的概念 顺序查找 顺序查找-算法原理 顺序查找-算法实现 ...
- 索引顺序查找(分块查找)
索引顺序查找又叫分块查找,它是介于顺序查找和折半查找之间的一种查找方法.折半查找虽然具有很好的性能,但其前提条件是线性表顺序存储而且按照关键字排序,这一前提条件在结点数很大且表元素动态变化时难以满足. ...
最新文章
- UNP Chapter 11 - 高级名字与地址转换
- 转:WebApi(一)
- Flask开发系列之Web表单
- Kibana远程代码执行漏洞攻击方法和漏洞原理分析
- 最高201万!华为高薪招应届生!专业是...
- css中属性设置成百分比
- oracle唯一索引能删除吗,Oracle:ora-02429:无法用于删除强制唯一/主键的索引 解决...
- 在程序员眼里,马云 1000 亿的大业败给了王者荣耀 100 个月工资的奖金
- centos php 安装openssl,详解Linux(centos7)下安装OpenSSL安装图文方法
- 客户机操作系统已禁用 cpu_强实时工业互联网虚拟化操作系统Intewell
- Chromecast电视投屏软件
- 【R语言】R语言编程规范
- 大阪第14天——韩寒同学语录
- excel下拉列表数据筛选_从筛选的Excel列表中下拉
- 华为虚拟机服务器怎么使用教程,虚拟机装服务器教程
- Linux系统:我们的征途是星辰大海!
- Javamail使用IMAP同步QQ自定义文件夹问题
- 指定页面模式,避开IE兼容性问题
- revit插件怎么快速自动标高?可以使用有自动标高的revit插件来实现
- php api视频教程,PHP开发APP接口视频教程