考研数据结构-查找

本文介绍了查找表的概念,包括静态查找和动态查找的定义。静态查找主要涉及查找和检索操作,而动态查找则包括插入和删除操作。顺序查找是最基本的查找方法,适用于未排序的线性表,而二分查找则利用了数据的有序性,提高了查找效率。文章还提供了两种查找算法的代码实现,并对比了它们的时间复杂度。

一、查找的定义

无论是静态查找还是动态查找,都要有查找的对象,也就是包含很多同类型数据的“表”,这个“表”可以理解为一个由同类型数据元素组成的一个“集合”,该集合可以用各种容器来存储,例如数组、链表、树等,我们统称这些存储数据的数据结构为——查找表。可见,查找表有时是我们传统意义的表,有时候是很复杂的一种结构。

二、静态查找和动态查找

1、静态查找

静态查找就是我们平时概念中的查找,是“真正的查找”。之所以说静态查找是真正的查找,因为在静态查找过程中仅仅是执行“查找”的操作,即:(1)查看某特定的关键字是否在表中(判断性查找);(2)检索某特定关键字数据元素的各种属性(检索性查找)。这两种操作都只是获取已经存在的一个表中的数据信息,不对表的数据元素和结构进行任何改变,这就是所谓的静态查找。

2、动态查找

看到上面静态查找的概念,动态查找就很好理解了,个人总觉得动态查找不像是“查找”,更像是一个对表进行“创建、扩充、修改、删除”的过程。动态查找的过程中对表的操作会多两个动作:(1)首先也有一个“判断性查找”的过程,如果某特定的关键字在表中不存在,则按照一定的规则将其插入表中;(2)如果已经存在,则可以对其执行删除操作。动态查找的过程虽然只是多了“插入”和“删除”的操作,但是在对具体的表执行这两种操作时,往往并不是那么简单。

哪种查找对应各自查找表,如有序表可以为静态查找表,也可以为动态查找表。依查找方式决定。

三、几种静态查找

1、顺序查找

       顺序查找是一种最基本、直接的查找方法。它从线性表的一端开始,向另一端逐个取出数据元素的关键字,并与要找的关键字K进行比较,以判定是否存在要找的数据元素。

       以数组存储为例,设数据元素从下标为1的数组单元到下标为Last的单元存放。为了简化算法,使得从后向前查找失败时,不必判断表是否检查完毕,可以在查找开始前,作为哨兵将要查找的关键字K存入下标为0的数组单元。这样,即使原表1~Last单元中没有关键字为K的记录,算法再多一次查找下标为0的单元,也会找到元素而终止,而此时返回数组下标值0表明查找失败。

代码:

Position SequentialSearch(List Tbl, ElementType K)
{
	// 在顺序存储的表Tbl中查找关键字为K的数据元素,使用“哨兵”
	Position i;
	
	Tbl->Data[0] = K; // 建立哨兵
	for(i = Tbl->Last ; Tbl->Data[i] != K ; i --);
	return i; // 查找成功返回数据元素所在单元下标;查找不成功返回0
}

2、二分查找

顺序查找算法的时间复杂度是线性的。而当线性表中数据元素是按大小排列存放时,可以设计一种更高效率的新算法---二分查找。二分查找也称为折半查找,是针对线性表中数据的存放是有序的这一特性,而采用的一种有效方法。

代码:

const int N = 1e5 + 10;

typedef int ElementType;
typedef int Position;
#define NotFound -1

typedef struct LNode *PtrToLNode;
struct LNode // 节点表示的东西 
{
	int Data[N]; // 数据 
	Position Last; // 位置
};
typedef PtrToLNode List;


// 二分查找的非递归实现
Position BinarySearch(List L, ElementType X)
{
	// 在顺序表L中查找关键字为X的数据元素
	Position Left, Right, Mid;
	
	Left = 1;
	Right = L->Last;
	while(Left <= Right)
	{
		Mid = (Left + Right) / 2;
		if(L->Data[Mid] > X)  Right = Mid - 1;
		else if(L->Data[Mid] < X)  Left = Mid + 1;
		else  return Mid;
	}
	return NotFound;
}

        与顺序查找算法不同,我们不必通过在0单元增加哨兵来判断查找是否成功,而是通过判断是否还有合理的剩余查找范围。因此,其实可以将表中元素从0单元开始存起,那么查找失败时算法返回的NotFound就应该是一个负数(-1)。

         算法时间复杂度分析:当线性表中没有所要查找的元素时,算法复杂度达到最大。设经过k步,查找范围从n减小到1。因为每步查找范围时上一步的二分之一,可得到关系n / 2^k = 1,即k=

logn。由此可以得到结论:二分查找算法具有对数的时间复杂度O(log n)。

         至此,我们已知道顺序查找和二分查找都属于静态查找方法,所谓静态是指数据一旦建立起来就基本不添加新的数据元素,也不删除原有的数据元素。因此用数组存放数据并通过下标访问数据元素既方便又高效。但当数据集变化频繁,采用链式存储时,这种基于有序性的二分查找策略就不适用了,但基于二分查找思路的动态结构方法二叉查找树是可以的。

 

 

   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

21RGHLY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值