【数据结构】查找1——线性表的查找(顺序查找、折半查找、分块查找)


查找的基本概念

  • 查找定义:

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

  • 查找表:

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

  • 关键字:

用来标识一个数据元素(或记录)的某个数据项的值。
主关键字:可唯一地标识一个记录的关键字是主关键字;
次关键字:反之,用以识别若干记录的关键字是次关键字。

  • 查找成功与否:

查找成功:若查找表中存在这样一个记录, 查找结果给出整个记录的信息,或指示该记录在查找表中的位置;
查找不成功:查找结果给出"空记录”或"空指针”。

  • 查找表可分为两类:

① 静态查找表:仅作"查询"(检索)操作的查找表。
② 动态查找表:作“插入"和"删除”操作的查找表。
有时在查询之后,还需要将"查询”结果为“不在查找表中”的数据元素插入到查找表中;或者从查找表中删除其“查询”结果为"在查我表中”的数据元素,此类表为动态查找表。

  • 查找算法的评价指标:

关键字的平均比较次数,也称平均查找长度ASL
在这里插入图片描述
n:记录的个数。
pi:查找第i个记录的概率(通常认为pi =1/n )。
ci:找到第i个记录所需的比较次数。

线性表的查找

顺序查找(线性查找)

顺序查找算法

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

数据元素类型定义:

typedef struct{
	KeyType key;//关键字域
	......//其他域
}ElemType;

在这里插入图片描述

顺序表定义:

typedef struct{//顺序表结构类型定义
	ElemType *R;//表基址
	int length;//表长
}SSTable;//Sequential Search Table

SSTable ST;//定义顺序表ST

查找算法:

int Search_Seq(SSTable ST,keyType key){//若成功返回其位置信息,否则返回0
	for(i=ST.length;i>=1;--i)//这里是从后往前找
		if(ST.R[i].key==key)
			return i;
	return 0;
}


//其他形式:
一、
int Search_Seq(SSTable ST,KeyType key){
	for(i=ST.length;ST.R[i].key!=key;--i)
		if(i<=0)
			break;
	if(i>0)
		return i;
	else 
		return 0;
}
二、
int Search_Seq(SSTable ST,KeyType key){
	for(i=ST.length;ST.R[i].key!=key&&i>0;--i);
	if(i>0)
		return i;
	else
		return 0;
}

//每执行一次循环都要进行两次比较。

改进查找算法:
把待查关键字key存入表头( "哨兵”、监视哨”),从后往前逐个比较,可免去查找过程中每一步都要检测是否查找完毕,加快速度。
如果后面没有匹配的,查找到第0个是key,则返回0。
在这里插入图片描述

int Search_Seq(SSTable ST,KeyType key){
	ST.R[0].key=key;
	for(i=ST.length;ST.R[i].key!=key;--i);
	return i;
}

当ST.length较大时,此改进能使进行一次查找所需的平均时间几乎减少一半。

顺序查找算法分析

在这里插入图片描述
比较次数与key位置有关:
查找第i个元素,需要比较n-i+1次;
查找失败,需比较n+1次。

上图查找成功时的平均查找长度:
假定每个元素的查找概率相等
ASL=(1+2+ … +11)/11=(11+1)/2=6

  • 复杂度分析:

时间复杂度:O(n)
查找成功时的平均查找长度,设表中各记录查找概率相等,平均查找长度ASL(n)=(1+2+ … +n)/n=(n+1)/2
空间复杂度:一个哨兵辅助空间O(1)

  • 提高查找效率:

1、记录的查找概率不相等时如何提高查找效率?
查找表存储记录原则——按查找概率高低存储:
① 查找概率越高,比较次数越少;
② 查找概率越低,比较次数较多。
2、记录的查找概率无法测定时如何提高查找效率?
方法——按查找概率动态调整记录顺序:
① 在每个记录中设一个访问频度域;
② 始终保持记录按非递增有序的次序排列;
③ 每次查找后均将刚查到的记录直接移至表头。

  • 顺序查找的特点:

优点:算法简单,逻辑次序无要求,且不同存储结构均适用。
缺点:平均查找长度ASL太长,时间效率太低。

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

折半查找:每次有序的将待查记录所在区间缩小一半。

在这里插入图片描述
查找过程:
mid=(low+high)/2
key<mid则:high=mid-1
key>mid则:low=mid+1
key==mid,找到
high<low,结束

折半查找算法

非递归算法
【算法思想】
设表长为n,low、high和mid分别指向待查元素所在区间的上界、下界和中点,key为给定的要查找的值:
初始时,令low=1,high=n,mid=⌊(low+high)/2⌋(若是整数则向下取整)
让k与mid指向的记录比较:
若key==R[mid].key,查找成功
若key<R[mid].key,则high=mid-1
若key>R[mid].key,则low=mid+1
重复上述操作,直到low>high时,查找失败

int Search_Bin(SSTable ST,KeyType Key){//在顺序查找表ST上查找key
	low=1;//置区间初值
	high=ST.length;
	while(low<=high)
		mid=(low+high)/2;
		if(ST.R[mid].key==key)
			return mid;//找到待查元素
		else if(key<ST.R[mid].key)//缩小查找区间
			high=mid-1;//继续在前半区间进行查询
		else
			low=mid+1;//继续在后半区间进行查找
	return 0;//顺序表中不存在待查元素
}

递归算法

int Search_Bin(SSTable ST,keyType key,int low,int high){//在顺序查找表ST上查找key
	if(low>high)
		return 0;//查找不到时返回0
	mid=(low+high)/2;
	if(key==ST.elem[mid].key)
		return mid;
	else if(key<ST.elem[mid].key)
		return Search_Bin(ST,key,low,mid-1);//递归,在前半区间进行查找
	else
		return Search_Bin(ST,key,mid+1,high);//递归,在后半区间进行查找
}

折半查找算法分析

折半查找的性能分析——判定树
在这里插入图片描述
在这里插入图片描述
圆形:是内结点,代表查找成功的情况。
矩形:是外结点,代表查找不成功的情况

查找成功:
比较次数=路径上的结点数
比较次数=结点的层数
比较次数≤树的深度=⌊log2n⌋+1
查找不成功:
比较次数=路径上的内部结点数

上图成功时的平均查找长度:
假定每个元素的查找概率相等
ASL=1/11*(11 +22 +43+44 )=33/11=3

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

设表长n=2h-1,则h=log2(n+1) (此时,判定树为深度=h的满二叉树),且表中每个记录的查找概率相等:Pi= 1/n。
在这里插入图片描述

  • 折半查找的特点:

优点:效率比顺序查找高。
缺点:只适用于有序表,且限于顺序存储结构(对线性链表无效)。

分块查找

分块查找

分块查找又称索引顺序表的查找
条件:
1、将表分成几块,且表或者有序,或者分块有序;
若i<j,则第j块中所有记录的关键字均大于第i块中的最大关键字
2、建立"索引表"(每个结点含有最大关键字域和指向本
块第一个结点的指针,且按关键字有序)

在这里插入图片描述
索引表是有序的;
块内元素是无序的。

查找过程:
先确定待查记录所在块(顺序或折半查找),
再在块内查找(顺序查找)。

分块查找性能分析

在这里插入图片描述

分块查找优缺点:
优点:插入和删除比较容易,无需进行大量移动。
缺点:要增加一个索引表的存储空间并对初始索引表进行排序运算。
适用情况:如果线性表既要快速查找又经常动态变化,则可采用分块查找。

三种查找算法的比较

在这里插入图片描述


  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值