DSA之查找(1):线性表的查找

0 知识回顾

在这里插入图片描述

1 查找

1.1 查找的概念

Q: 查找是在哪里找?
A :查找表,查找表没有前驱以及后继的关系。
查找表是由同一类型的数据元素(或记录)构成的集合。由于“集合”中的数据元素之间存在着松散的关系,因此查找表是一种应用灵便的结构。
在这里插入图片描述
Q:怎么查找?
A:根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素或(记录)。

关键字,即用来标识一个数据元素(或记录)的某个数据项的值,有以下几类关键字:

  • 主关键字:可唯一地标识一个记录的关键字是主关键字;
  • 次关键字:反之,用以识别若干记录的关键字是次关键字。

以下为判断查找是否成功
在这里插入图片描述
以下为看查找的目的
在这里插入图片描述
以下为查找的分类
在这里插入图片描述
以下评价查找算法的性能分析
在这里插入图片描述
以下为查找研究的是什么?
在这里插入图片描述

2 线性表的查找

线性表的查找有以下几种方式:

  1. 顺序查找
  2. 折半查找(二分或者对分查找)
  3. 分块查找

2.1 顺序查找

在这里插入图片描述

//数据元素类型定义
typedef struct
{
	KeyType key;//关键字域
	......//其他域
}ElemType;
//
typedef struct
{
	ElemType *R; //表基址
	int length; //表长
}SSTable; //Sequential Search Table
SSTable ST;//定义顺序表

2.1.1 顺序查找算法

在这里插入图片描述
算法的其他形式:
在这里插入图片描述
在这里插入图片描述
问题: 每执行一次循环都要进行两次比较是否能改进?
改进: 把待查关键key存入表头(“俏兵”、”监视哨”),从一后往前逐个比较,可免去查找过程中每一步都变检测是否查我完毕,从而加快速度。

在这里插入图片描述
设置监事岗的,就只需要比较1次。
在这里插入图片描述

最终算法:
在这里插入图片描述
ST.length()较大时,此改进能使进行一次查找所需的平均时间几乎减少一半。注意此时的for循环是空语句,然后直接返回i的下标就行。

比较次数与key位置有关:

  • 查找第个元素,需要比较n-i+1次
  • 查找失败,需比较n+1次(开始的时候就把要查找的值存入起始节点当做哨兵,所以查找失败就从最后一个往回退,即查找n+1次)

2.1.2 顺序查找的性能分析

在这里插入图片描述
顺序查找的性能:

  • 时间复杂度: O ( n ) O(n) O(n),查找成功时的平均查找长度,设表中的各记录查找概率相等。
    A S L s ( n ) = ( 1 + 2 + . . . + n ) / n = ( n + 1 ) / 2 ASL_s(n) = (1+2+...+n) / n = (n+1) / 2 ASLs(n)=(1+2+...+n)/n=(n+1)/2
  • 空间复杂度:一个辅助空间(哨兵)— O ( 1 ) O(1) O(1)
    在这里插入图片描述

2.1.3 顺序查找的特点

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

2.2 折半查找(二分)

就是先排序,排序好后先判断,从中间判断,判断所要找的数与中间的数的大小,所要找的数比中间的数大,则low = mid + 1,只找右半边;所要找的数比中间的数小,则high = mid - 1,只找左半边。结束的条件为high < low。关于mid除下来不是整数,可以使用取整的符号。
在这里插入图片描述

2.2.1 折半查找算法

在这里插入图片描述

非递归实现的形式:

int Search_Binary(SSTable ST, KeyType 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_Binary(SSTable ST, keyType key, int low, int high)
{
	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)//递归,在前半区间进行查找
	{
		Search_Binary(ST, key, low, mid-1);
	}
	else//递归,在后半区间进行查找
	{
		Search_Binary(ST, key, mid+1, high);
	}
}

2.2.2 折半查找的性能分析

在这里插入图片描述

在这里插入图片描述
折半查找的时间复杂度为 O ( l o g n ) O(logn) O(logn)

2.2.3 折半查找的特点

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

2.3 分块查找

按照索引顺序表进行查找。
在这里插入图片描述

2.3.1 分块查找的性能分析

在这里插入图片描述
插入删除比较方便。

2.3.2 分块查找的特点

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

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值