C语言二分查找

前言

二分查找又叫拆半查找,C语言二分查找是一种高效的查找算法,但是只适用于有序的情况,不管是递增的数列,还是递减的数列,前提一定要是有序的数组。

目录

前言

二分查找算法的基本原理:

时间复杂度

接下来将用C语言实例来验证

首先根据二分查找的基本原理,确定下标,如下:

然后根据例子,找到合适的循环条件:

总结:


二分查找算法的基本原理:

(1):前提一定为有序数组。

(2):首先定义出数组的最左边元素的下标,最右边元素的下标和数组下标的中间值。

(3):找出该数组中的中间元素(通过下标来寻找),然后与所找元素进行比较,若中间元素小于所寻找元素,那么中间值加1(此时充当左边的范围下标),右边范围的边界仍是最右边元素的下标,若中间元素小于所寻找元素,那么中间值减1(此时充当右边的范围下标),左边范围的边界仍是最左边元素的下标。

(4):重复此过程,直到找到目标值或搜索区间为空(表示未找到)。

时间复杂度

  • 时间复杂度:O(log n)

  • 空间复杂度:O(1)(迭代版本)
  • 最优情况:O (1)(目标元素恰在中间位置)
  • 最坏情况:O (log n)(n 为数组长度)

接下来将用C语言实例来验证

例子:给出一串数字1~10,来让我们寻找这一串中的数字7,以及找到数字7对应的下标。

首先根据二分查找的基本原理,确定下标,如下:

int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 0;    //想要从数组arr1中寻找的数字
printf("请输入你想找从数组中寻找的数字:");
scanf("%d", &k);
int sz = sizeof(arr1) / sizeof(arr1[0]);
int left = 0;     //左下标
int right = sz - 1;  //右下标
int flag = 0;  //标志

其中 sz 为数组 arr1 中的元素个数,数组的下标是从0开始,最大下标为元素个数减1,刚开始 left 为最左边元素的下标也就是此时 arr1[1] 的下标,right 为最右边元素的下标也就是 arr1[10] 的下标。

然后根据例子,找到合适的循环条件:

不难发现,每当进行一次二分查找,左边范围下标或者右边范围下标会有一个发生变化,通过中间下标所对应的元素与所寻找元素相比较,从而确定哪边范围下标变化。

但从循环开始 左边范围下标 left 就小于 右边范围下标 right ,当随着二分查找的一次次进行,二者 left 和 right 会逐渐的逼近知道相等,达到循环的终止条件。

	int flag = 0;  //标志
	while (left <= right)
	{
		int mid = left + (right - left) / 2; //数组的中间下标
		if (arr1[mid] < k)
		{
			left = mid + 1;
		}
		else if (arr1[mid] > k)
		{
			right = mid - 1;
		}
		else
		{
			flag = 1;
			printf("找到了,下标为%d\n", mid);
			break;
		}
	}
	if (0 == flag)
	{
		printf("找不到\n");
	}

当我们寻找的数字为 7 时,数组中 10 个元素,最左边范围的下标为 0 ,最右边范围的下标为 9,中间下标为 4 ,通过数组中下标为 4 的元素与数字 7 比较,很明显 arr1[4] 为 5 比数字 7 要小,那么最左边范围的下标变成中间下标加 1,最右边范围的下标不变,此时的 left 小于 right 符合循环条件,在进行第二次二分查找,此时的最左边范围的下标为 5 ,中间下标变成了 7 ,通过数组中下标为 7 的元素与数字 7 比较,结果 arr1[7] 要大于数字 7,此时中间下标加1变成右边范围的下标,在进行第三次二分查找,左边范围的下标为5,右边范围的小标为6,中间下标为5,让arr1[5]与数字7进行比较,结果小于数字7。

那么左边下标变成6,右边下标仍为6,在进行一次二分查找,此时找到数字7对应的下标。

完整代码如下:

#include<stdio.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 0; //想要从数组arr1中寻找的数字
	printf("请输入你想找从数组中寻找的数字:");
	scanf("%d", &k);
	int sz = sizeof(arr1) / sizeof(arr1[0]);
	int left = 0;  //左下标
	int right = sz - 1;  //右下标
	int flag = 0;  //标志
	while (left <= right)
	{
		int mid = left + (right - left) / 2; //数组的中间下标
		if (arr1[mid] < k)
		{
			left = mid + 1;
		}
		else if (arr1[mid] > k)
		{
			right = mid - 1;
		}
		else
		{
			flag = 1;
			printf("找到了,下标为%d\n", mid);
			break;
		}
	}
	if (0 == flag)
	{
		printf("找不到\n");
	}
	return 0;
}

总结:

二分查找的效率极高,可以用于处理大量的数据,但是必须为有序的序列,上述情况为单调递增的数组,那么单调递减的数组相应的判断条件相反即可。

评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值