C语言 线性表的查找(顺序查找、折半查找)

前言

在计算机科学中,查找问题是经常遇到的一个问题。顺序查找和折半查找是两种非常基础的查找算法,也是大多数其他高效查找算法的基础。了解它们的原理、优缺点及应用场景,对于我们深入理解各种排序和查找算法有很大帮助。


顺序表的储存结构

typedef struct {
	int* array;//储存空间基地址
	int lenght;//当前长度
}SQList;

顺序查找

顺序查找(Sequential Search)也被称为线性查找,它的基本思想是从数据结构的起点开始,循环遍历每个元素直到目标值或整个数据结构被遍历完毕。如果找到了目标值返回下标,否则返回不存在的标识(通常使用-1)。它既可以用于有序表中的无序查找,也可以用于无序表中的有序查找。

以下是算法实现:

int Sequential_Search(SQList* L, int e) {
	for (int i = 0; i < L->lenght; i++) {
		if (L->array[i] == e) {
			return i;//找到目标值,返回下标
		}
	}
	return -1;//没有找到目标值,返回-1
}

还有一种是设置监视哨,可以免去查找过程中每一步都有检测整个表是否查找完毕。以下是在表尾设置监视哨的算法:

int Sequential_Search(SQList* L, int e) {
	int i;
	L->array[L->lenght] = e;
	for (i =0; L->array[i] != e; i++);
	return i==L->lenght? -1:i;
}

顺序查找的时间复杂度为O(n),其中n为待查找元素的个数。由于需要遍历整个数据结构,它在大型数据集上的效率不高,但对于小型数据集或数据有序性较低的情况,它仍然是一个简单而有效的方法。 


折半查找

折半查找(Binary Search)又称二分查找,它是针对有序数据结构的查找算法。它的基本思想是将待查区间的两端分别记录下来,然后计算出中点位置。与目标值进行比较大小,如果等于中点位置上的值,则查找结束;否则根据大小关系继续在左半部分或右半部分进行二分查找,直到最后找到目标值或确定该值不存在于待查区间。

折半查找算法_kittimzhe的博客-CSDN博客

在实现二分查找时,通常区间定义、循环结束条件和中值溢出是需要特别注意的,这里给出一些具体的解决方案:

1.区间定义:采用左闭右闭区间或者左闭右开区间。在左闭右闭区间中,数组索引的起始值和结束值都包含在搜索区间中;而在左闭右开区间中,开始值包含在搜索区间中,但结束值不在其中。

2.循环结束条件:当待搜索区间为空时,可以结束循环。具体判断方法如下:

  • 在左闭右闭区间[left,right]中,判断left <= right是否成立。
  • 在左闭右开区间中[left,right),判断left < right是否成立。

3.中值溢出:当left和right都是int,两个值的初始值都超过int限定大小的一半,那么left+right就会发生溢出,所以应该用left+(right-left)/2来防止求中值时候的溢出。

根据以上三点,可以在代码中清晰地定义搜索区间,并避免进入死循环。

int Binary_Search(SQList* L, int e) {
	//查找目标值e
	int left, right, mid;
	left = 0;
	right = L->lenght - 1;
	while (left <= right) {
		mid = (left + right) / 2;
		if (L->array[mid] == e) {
			return mid;//返回目标值所在数组下标
		}
		else if (L->array[mid] > e) {
			right = mid - 1;//继续查找左半区
		}
		else {
			left = mid + 1;//继续查找右半区
		}
	}
	return -1;//没有找到目标值,返回-1
}

 还可以通过递归实现:

int Binary_Search(SQList* L, int left, int right, int e) {
	//查找目标值e
	if (left > right)	return -1;//没有找到目标值,返回-1
	int mid = (left + right) / 2;
	if (L->array[mid] == e)  return mid;//返回目标值所在数组下标
	//递归查找左半区或右半区
	return L->array[mid] > e ? Binary_Search(L, left, mid - 1, e) : Binary_Search(L, mid + 1, right, e);
}

折半查找的时间复杂度为O(log n),其中n为待查元素的个数。由于是将待查区间不断对半划分直到找到目标元素或者区间为空,因此当数据集非常大时它是一种高效而实用的查找算法。


总结 

顺序查找和折半查找作为查找问题中的基础算法,在各自适合的场景中具备着一定的优势和局限性。当数据规模较大时,折半查找的时间复杂度的表现更佳;而对于较小数据规模和无序数据,使用顺序查找可能是更好的选择。同时,我们还可以通过在二叉搜索树和哈希表等其他数据结构上应用查找技术来解决不同的查找问题。因此,我们在日常编程中,应该根据实际情况选择基于不同算法的查找策略,以获得更好的效率与体验。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
顺序表是一种线性表,可以使用数组来实现顺序查找折半查找是两种常见的查找算法。 以下是用c语言实现顺序表的顺序查找折半查找的示例代码: ```c #include <stdio.h> #define MAX_SIZE 100 typedef struct { int data[MAX_SIZE]; int length; } SeqList; // 初始化顺序表 void initList(SeqList* list) { list->length = 0; } // 向顺序表中插入元素 void insert(SeqList* list, int value) { if (list->length == MAX_SIZE) { printf("List is full.\n"); return; } list->data[list->length++] = value; } // 顺序查找 int seqSearch(SeqList* list, int value) { for (int i = 0; i < list->length; i++) { if (list->data[i] == value) { return i; } } return -1; } // 折半查找 int binarySearch(SeqList* list, int value) { int low = 0, high = list->length - 1, mid; while (low <= high) { mid = (low + high) / 2; if (list->data[mid] == value) { return mid; } else if (list->data[mid] > value) { high = mid - 1; } else { low = mid + 1; } } return -1; } int main() { SeqList list; initList(&list); insert(&list, 1); insert(&list, 3); insert(&list, 5); insert(&list, 7); insert(&list, 9); int index = seqSearch(&list, 5); if (index != -1) { printf("Found at index %d.\n", index); } else { printf("Not found.\n"); } index = binarySearch(&list, 5); if (index != -1) { printf("Found at index %d.\n", index); } else { printf("Not found.\n"); } return 0; } ``` 在上面的示例代码中,我们定义了一个SeqList结构体来表示顺序表,包含一个数组和一个长度属性。我们使用initList函数来初始化顺序表,使用insert函数来向顺序表中插入元素。顺序查找使用seqSearch函数来实现折半查找使用binarySearch函数来实现

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Indifferent-

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

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

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

打赏作者

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

抵扣说明:

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

余额充值