C语言|线性表的查找算法|顺序查找、索引查找


查找算法涉及两个主要问题:一是数据如何组织—— 查找表;而是在查找表上如何查找—— 查找方法。

查找过程中往往是依据数据元素的某个数据项进行 的,这个数据项通常是数据的关键字。可以唯一确定一个数据元素的关键字称为主关键字,不能唯一确定一个数据元素的关键字称为次关键字。常用的查找方法主要有顺序查找索引查找哈希查找

ASL的定义

在进行查找性能的分析时。经常采用平均查找长度(Average Search Length,ASL)来衡量查找算法的性能优劣。
ASL定义为查找过程中,给定值与数据关键字比较次数的期望值。对于具有n个记录的顺序表,查找成功时的平均查找长度(ASL)为

ASL= ∑ i = 1 n \sum_{i=1}^n i=1n P i P_i Pi C i C_i Ci

其中, P i P_i Pi为查找第i个记录的概率; C i C_i Ci为找到第i个记录数据需要比较的次数, C i C_i Ci随查找过程的不同而不同。

顺序查找

依次查找表中的数据,直到找到或者遍历完之后仍未找到为止。

基本思想及查找算法

从表中指定位置(一般为末尾)开始,沿某个方向记录的关键字与给定的关键字的值进行比较,若某个记录的关键字和给定的关键字值相等,则查找成功;反之,若找完整个顺序表仍未找到,则查找失败。

通常情况下,我们可以将表头(第0个位置)设置为岗哨,即对R[0]赋值key,目的是免去查找过程中每次比较关键字都要判断是否到达表头(只需要在R[i]=key时判断i是否等于0),一定程度上减少了查找时间。

顺序表的顺序查找算法如下

typedef int DataType;
typedef int KeyType;//DataType和KeyType可根据使用需求修改

typedef struct SeqList
{
	DataType key;
}SeqList;

int seqsearch(SeqList S[], int n, KeyType key)
{
	int i = n;
	S[0].key = key;
	while (S[i].key != key)i--;
	return i;
}

查找性能

空间复杂度:对于顺序查找,一般只需要一个辅助存储单元空间,因此空间复杂度为O(1);
时间复杂度:平均情况下,需要和顺序表中大约一半的记录进行比较,即比较次数为 n 2 \frac{n}{2} 2n,时间复杂度为O(n)。

若每个记录的查找概率相等,即 P i P_i Pi= 1 n \frac{1}{n} n1
则等概率情况下顺序查找的平均查找长度为

A S L s ASL_s ASLs = ∑ i = 1 n \sum_{i=1}^n i=1n P i P_i Pi C i C_i Ci = 1 2 \frac{1}{2} 21 ∑ i = 1 n \sum_{i=1}^n i=1n (n-i+1) = n + 1 2 \frac{n+1}{2} 2n+1

若考虑查找失败的情况,平均查找长度就是查找成功和不成功的平均查找长度之和。查找不成功时的比较次数为顺序表的长度。假设查找成功和不成功的可能性相同,对每条记录的查找概率也相等,则平均查找长度为

ASL= n + n + 1 2 2 \frac{n+\frac{n+1}{2}}{2} 2n+2n+1 = 3 n + 1 4 \frac{3n+1}{4} 43n+1

索引查找

索引表的构建

  1. 按表中数据的关键字将表分成若干块: R 1 R_1 R1, R 2 R_2 R2,… R L R_L RL,这些块要满足第 R k R_k Rk块中所有关键字<=Rk+1块中所有关键字,k=1,2,…,L-1,称为“分块有序”。也可以满足第Rk块中所有关键字 >=Rk+1块中所有关键字,此时,分块降序排序。
  2. 对每块建立一个索引项,每一个索引项包含两项内容:
    A. 关键字项,为该块中最大关键字值。
    B. 指针项,为该块第一个记录在表中的位置。
  3. 索引表的查找。
    索引表的查找分两步进行:
    (1) 查找目录。将外存上含有索引区的页块调入内存,根据索引表的关键字项查找记录所在块,根据其指针项确定所在块的第一个记录的物理地址。
    (2) 查找数据。将含有该数据的页块调入内存,在这个块内部根据关键字查找记录的详细信息。

索引表的顺序查找算法

typedef int DataType;
typedef int KeyType;//DataType和KeyType可根据使用需求修改

typedef struct IndexType
{
	KeyType key;//关键字项
	int Link;//指针项
}IndexType;

typedef struct SeqList
{
	DataType key;
}SeqList;

int IndexSeqSearch(IndexType Ls[], SeqList S[], int m, int n, KeyType key)
{
	//索引表Ls中顺序查找关键字为key,索引表长度为m
	//顺序表为R,块长为n
	int i = 1;
	while (i <= m && key > Ls[i].key)i++;//块间查找
	if (i > m)return -1;//查找失败
	else
	{
		//块内顺序查找
		int j = Ls[i].Link;
		while (key != S[j].key && j - Ls[i].Link < 2)j++;
		if (key == S[j].key)return j;//成功
		else return -1;//失败
	}
}

查找性能

索引块间和索引块内部都采用顺序查找,则查找的平均查找长度为块间及块内平均查找长度之和,即

ASL = Lb + Lw = 1 b \frac{1}{b} b1 ∑ j = 1 b \sum_{j=1}^b j=1b j + 1 s \frac{1}{s} s1 ∑ i = 1 s \sum_{i=1}^s i=1s i = 1 2 \frac{1}{2} 21 ( m s \frac{m}{s} sm + s) + 1

其中,m为表长,均匀分为b块,每块含有s个记录。

由上可知,索引表顺序查找的时间复杂度不仅和表长m有关,而且和每一块中的记录个数s有关。为了提高查找效率,在m确定的情况下,应选择合适的s。当s取 n \sqrt{n} n 时,ASLbs取最小值 n + 1 \sqrt{n+1} n+1 .

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值