目录

查找的基本概念

线性表的查找

顺序查找(线性查找)

折半查找(二分或对分查找)

折半查找的性能分析——判定树

分块查找(索引顺序查找)

分块查找性能分析

三种方法比较


查找的基本概念

查找表是由同一类型的数据元素(或记录)构成的集合。由于“集合”中的数据元素之间存在着松散的关系(即无严格的前驱与后继关系),因此查找表是一种应用灵便的结构。

其中“灵便”是指:我们可以根据需要,将这些数据元素存成线性表或树表等。

  • 什么是查找?

查找就是根据某个给定的值,在查找表中查找一个其关键字等于给定值的数据元素(或记录)。

  • 关键字(用来标识一个数据元素(或记录)的某个数据项的值)

关键字又分为主关键字次关键字

  1. 主关键字:可唯一地标识一个记录的关键字。(如查找张三的语文成绩,那么在成绩表中可以查找到一个唯一确定的值)
  2. 次关键字:用以识别若干记录的关键字。(如查找语文成绩为91分的人,那么就有可能在成绩表中查找到许多个语文成绩为91分的学生。)
  • 如何确定查找是否成功?

若在查找表中存在一个与给定值相等的数据元素(或记录),则为“查找成功”。查找结果给出整个记录的信息,或指示该记录在查找表中的位置;反之,“查找不成功”,查找结果给出“空记录”或“空指针”。

  • 查找的目的
  1. 查询某个“特定”数据元素是否在查找表中。
  2. 检索某个“特定”数据元素的各种属性。(如查找成绩表中张三的各科成绩)
  3. 在查找表中插入一个数据元素。
  4. 在查找表中删除某个数据元素。
  • 查找表的分类
  1. 静态查找表:仅作“查询”(检索)操作的查找表。
  2. 动态查找表:在“查询”完之后,还要作“插入”或“删除”操作的查找表。
  • 怎样评价查找算法?

查找算法的评价指标:平均查找长度(ASL),即关键字的平均比较次数。

ASL=Average Search Length

ASL=        (关键字比较次数的期望值)

n:表中记录的个数

pi:查找第i个记录的概率(通常认为pi= 1/n)

ci:找到第i个记录所需要的比较次数

线性表的查找

顺序查找(线性查找)

应用范围:顺序表或线性链表表示的静态查找表;表内元素之间无序

例如:表ST中有12为元素,其中下标为0的位置不存放元素。  ST.length=11

0 1 2 3 4 5 6 7 8 9 10 11 12
5 9 56 32 74 11 45 30 75 46 25 88

在查找此表时,有两种方法:第一种,从前往后找;第二种,从后往前找。

在顺序表ST中查找值为11的数据元素,查到了,返回6;若在表中查找10,未找到,返回0。

改进:把待查关键字key存入表头(即设立“哨兵”),可以免去查找过程中每一步都要检测是否查找完毕,加快速度。当ST.length较大时,此改进能使进行一次查找所需的平均时间几乎减少一半。

/*数据元素类型定义*/
typedef struct {KeyType key; //关键字域…… ; //其他域
}ElemType;typedef struct { //顺序表结构类型定义ElemType *R;  //表基址int length;  //表长
}SSTable; //Sequential Search Table
SSTable ST; //定义顺序表ST/*算法(设有哨兵)*/
int Search(SSTable ST,KeyType key)
{ST.R[0].key=key;int i;for(i=ST.length;ST.R[i].key!=key;i--);return i;
}

顺序查找的比较次数与key位置有关:

查找第i个元素,需要比较n+1-i次;查找失败,需要比较n+1次。

  • 时间复杂度:O(n)

查找成功时的平均查找长度:设表中各个记录查找效率相等,ASL=(n+1)/2。

  • 空间复杂度:需要一个辅助空间——O(1)

顺序查找的优缺点:

优点:算法简单,逻辑次序无要求,且适用于不同的存储结构。

缺点:ASL太长,时间效率太低。

折半查找(二分或对分查找)

折半查找将每次待查记录所在的区间缩小一半。进行折半查找的要求是顺序表中的记录之间是有序的。(如:递增序列或递减序列)

查找过程:(查找32)

0 1 2 3 4 5 6 7 8 9 10 11 12
5 9 13 32 39 40 45 50 75 79 82 88

|                                         |                                                      |

low                                    mid                                                  high

mid=(low+high)/2; 当key(32)<mid上的值,high移动到mid的前一位:

0 1 2 3 4 5 6 7 8 9 10 11 12
5 9 13 32 39 40 45 50 75 79 82 88

|                                |          |

low                           high      mid

再进行mid=(low+high)/2,mid移动到下标为3的位置:

0 1 2 3 4 5 6 7 8 9 10 11 12
5 9 13 32 39 40 45 50 75 79 82 88

|              |                  |

low         mid             high

此时比较关键字与mid位置上的值,发现key>mid,则low的位置移动到mid的后一位,即low=mid+1:

0 1 2 3 4 5 6 7 8 9 10 11 12
5 9 13 32 39 40 45 50 75 79 82 88

|        |        |

mid    low   high

再进行mid=(low+high)/2,mid的值为4:

0 1 2 3 4 5 6 7 8 9 10 11 12
5 9 13 32 39 40 45 50 75 79 82 88

|         |

low    high

|

mid

此时比较关键字与mid位置上的值,发现他俩相等,即找到。

若查找的是30:此时的mid为4,low为4,high为5, 此时的mid位置上的值与关键字的值仍不相等,并且比mid位置上的值小,则high=mid-1:

0 1 2 3 4 5 6 7 8 9 10 11 12
5 9 13 32 39 40 45 50 75 79 82 88

|         |

high    low

|

mid

此时,high<low,查找结束。

/*非递归算法*/
int Search(SSTable ST,KeyType key){int low,high,mid; low=1;high=ST.length; //设置区间初值while(low<=high){mid=(low+high)/2; //计算mid的值if(ST,R[mid].key==key) return mid; //找到待查找的元素else if(key<ST.R[mid].key) //缩小查找区间high=mid+1; //继续在前半区查找else low=mid+1; //继续在后半区查找}retur 0; //顺序表中未找到待查找的元素
}
/*递归算法*/
int search(SSTable ST,KeyType key,int low,int high)
{if(low>high) return 0; //查找不到时返回0 mid=(low+high)/2;else if(ST.R[mid].key==key) return mid;else if(ST.R[mid].key>key)search(ST,key,low,mid-1); //递归,在前半区进行查找else search(ST,key,mid+1,low); //递归,在后半区进行查找} 

折半查找的性能分析——判定树

0 1 2 3 4 5 6 7 8 9 10 11
5 9 13 32 39 40 45 50 75 79 82

3        4      2       3         4       1        3        4         2        3       4

上面一行数字为查找各位置元素需比较次数。

若查找的是6号位置的元素,则该元素只需要比较1次便可找到,对应在二叉判定树的第一层;

3、9号位置的元素需要比较二次才能找到,对应在二叉判定树的第二层……

上面的表格对应的二叉判定树为:

树中结点内的数字代表表中记录的位置

查找成功:

  • 比较次数=路径上的结点数(从根结点开始)=结点的层数
  • 比较次数<=树的深度:()+1

查找不成功时:比较次数<=()+1

上图二叉判定树对应的查找成功时的平均查找长度:

ASL=(1*1+2*2+3*4+4*4)/11=3

 平均查找长度ASL(成功时):

设表长为n,n=-1,(h表示判定树为深度=h的满二叉树),h=,且表中每个记录的查找概率相等,都为1/n,则:

ASL约等于    (n>50)

折半查找的优缺点:

优点:效率比顺序查找高。

缺点:只适用与有序表,并且是顺序存储结构,对于线性链表无效。若想对表中的元素进行插入或者删除时,需要移动大量的元素。

分块查找(索引顺序查找)

分块查找是在查找时,先确定需要查找的元素所在哪一块,然后进入到那一块区域中进行查找,这样查找也大大缩小了需要查找的范围。

分块查找,又叫索引顺序表的查找

应用分块查找时,需要满足:

  1. 将表分为几块,表中的内容既可以是有序的,也可以是无序的,但是要求分块有序(块与块的排序是有序的):例如,将一个表分为1,2两块,则第2块中的所有记录的关键字的值均大于第1块中的最大关键字的值。
  2. 建立“索引表”(每个结点含有最大关键字域和指向本块第一个结点的指针,且按关键字有序)。

查找过程:先确定待查记录所在块(顺序或者折半查找),再在块内查找(顺序查找;若块内记录也是有序的,也可用折半查找)。

分块查找性能分析:

分块查找的ASL是由两部分构成:

  1. 对索引表查找的ASL
  2. 对块内查找的ASL

索引表是有序的,它的平均查找长度按照二分法来算。

ASL=,n是指线性表中的元素个数,s是指每块内部的元素个数,n/s即块的数目。s/2是在块内的平均查找长度。

 <= ASL <= (n+1)/2   ,分块查找的ASL比二分查找的要大,比顺序查找的要小,且更接近与二分查找的ASL。

分块查找的优缺点:

优点:插入和删除比较容易,无需将元素进行大量的移动。

缺点:要增加一个索引表的存储空间并对初始索引表进行排序运算。

适用情况:适用于线性表既要快速查找又经常动态变化。

三种方法比较

顺序查找 折半查找 分块查找
ASL 最大 最小 中等
表结构 有序表、无序表 有序表 分块有序
存储结构 顺序表、线性链表 顺序表 顺序表、线性链表

欢迎大家的指正。

数据结构之线性表的查找相关推荐

  1. 【数据结构和算法笔记】线性表的查找(平均查找长度,二分法,判定树)

    查找: 给定一个值k,在含有n个元素的表中找出关键字等于k的元素,若找到,则查找成功,否则,查找失败 查找前首先确定(1)存放数据的数据结构是什么(2)元素是否有序 动态查找表:查找的同时做修改操作( ...

  2. 数据结构-线性表的查找

    文章目录 查找(一) 9.1 查找基本概念 9.2 线性表的查找 9.2.1 顺序查找 9.2.2 折半查找 9.2.3 索引存储结构 参考资料 本篇文章用于记录,不适合参考. 查找(一) 9.1 查 ...

  3. 用标准C语言初始化线性表,C语言数据结构-顺序线性表的实现-初始化、销毁、长度、查找、前驱、后继、插入、删除、显示操作...

    1.数据结构-顺序线性表的实现-C语言 #define MAXSIZE 100 //结构体定义 typedef struct { int *elem; //基地址 int length; //结构体当 ...

  4. 数据结构——线性表的查找

    查找 查找的概念 线性表的查找 顺序查找(线性查找) 折半查找(二分或对分查找) 分块查找 查找的概念 主关键字:可唯一地标识一个记录的关键字就是主关键字 次关键字:用以识别若干记录的关键字就是次关键 ...

  5. 数据结构与算法--线性表的查找

    一.查找的基本概念 1) 查找表: 查找表是由同一类型的数据元素(或记录)构成的集合         2) 由于集合中的数据元素之间存在着松散的关系,因此查找表是一种应用灵便的结构 3) 查找: 根据 ...

  6. 【Java数据结构】线性表

    线性表 线性表是最基本.最简单.也是最常用的一种数据结构. 线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而 ...

  7. step3 . day2 数据结构之线性表链表

    今天继续学习数据结构的线性表部分,从基础的顺序表到链表,类比写了一些调用函数,完成了表的增删改查排序等问题. 尤其是链表的排序,费了很大的心思终于捋顺写出来了,小有成就感,而且代码一次通过率越来越高, ...

  8. 数据结构之线性表(附代码)

    数据结构 之 线性表(附代码) 线性表思维导图: 线性表定义(逻辑结构): 一.顺序表 1.顺序表思维导图: 2.顺序表的逻辑结构: 3.顺序表基本操作的功能实现: 1.线性表的静态定义: 2.线性表 ...

  9. 用Java描述数据结构之线性表的链式存储(链表),模拟LinkedList实现

    上一篇介绍了顺序表:用Java描述数据结构之线性表的顺序存储(顺序表),ArrayList及其方法的介绍 上一篇博客中说明了什么是线性表--线性表就是一个个数据元素逻辑上以一对一的相邻关系(但是在物理 ...

最新文章

  1. BZOJ1398: Vijos1382寻找主人 Necklace 字符串最小表示法
  2. Android开发:Android Studio中gradle的代理问题
  3. MsSQL学习第五章---排序和分页
  4. 在阿里云主机的Debian操作系统上安装Docker
  5. mysql 深胡_数据存储之MySQL
  6. Java编程判断一组学生成绩等级
  7. Improving Transferability of Adversarial Examples with Input Diversity论文解读
  8. 『Python』skimage图像处理_旋转图像
  9. 【Thinking In Java】笔记之一 一切都是对象
  10. 鸿蒙系统硬盘分区,硬盘分区2种格式
  11. 电商产品经理的那些图 订单、确认支付、发货、退货、退款、换货...
  12. 算法基础:NP完全问题
  13. C++ rand的用法
  14. 原创【歌词类】雪中吟
  15. [Python嗯~机器学习]---用python3来分析和预测加州房价
  16. 2020阿里云云栖大会奖品活动汇总(持续更新,快收藏)
  17. 小程序获取本地存储数据,然后传参的时候是上次请求的id
  18. win32api 中mouse_event、GetFullPathName(fileName)、.GetLocalTime()、GetSystemDirectory()等函数的用法
  19. C# Math类的常用方法
  20. 宏替换、条件编译、头文件展开

热门文章

  1. 计算机组装在线视频,电脑安装《电脑组装入门教程》(全19集)
  2. 虚拟直播实现流程(多人连麦直播互动为例)
  3. 基于Windows API的VC++串口通信详解
  4. 带你一文解析RCU锁机制原理
  5. asp.net mvc、asp.net url重写 Url Rewrite
  6. WPS表格设定格式简单输入数学单位如平方米、立方米等
  7. android手机QQ尾巴修改(QQ for Pad)
  8. 命令行登录Mysql,远程登录Mysql的方法
  9. 特征值与特征向量的性质
  10. 宝藏APP推荐,一个比一个良心