C语言 二分查找:高效搜索有序数组

一.引入

我买了一件衣服,你好奇问我多少钱,我说不超过300元,你会怎么猜呢?你会1,2,3,4...这样猜吗?显然并不会;⼀般大家都会猜中间的数字,⽐如:150,然后看是大了还是小了,再接着猜...... 这样通过每次缩小一半的查找范围 来寻找最终的值,就是二分查找 ,也叫折半查找

有序的数组中查找某个数就可以用二分查找(折半查找)

二分查找是一种非常高效的算法,相比于线性查找的 O(n) 时间复杂度,二分查找的时间复杂度为 O(log n) ,在处理大量数据时效率非常高

(对于时间复杂度的介绍见:时间复杂度_o(n)-CSDN博客


二. 算法思路

2.1 查找过程演示

下面有一个有序的数组,现在要查找数字 "7"

数组:1 2 3 4 5 6 7 8 9 10

下标:0 1 2 3 4 5 6 7 8 9

查找过程如下:

**1.**下标 (0+9) / 2 = 4,对应数字 5 < 7,将下标范围缩小至 5~9

**2.**下标 (5+9) / 2 = 7,对应数字 8 > 7,将下标范围缩小至 5~6

**3.**下标 (5+6) / 2 = 5,对应数字 6 < 7,将下标范围缩小至 6

**4.**下标 6 对应要查找的数字 7,查找成功

2.2 逻辑化思路

1. 找出数组的中间元素 <--- 计算出中间元素 mid 的下标 <--- 定义左右下标 (left、right) ,取中值

2. 比较中间元素与要查找元素 k 的大小,若 mid > k ,则更新 right = mid - 1 ;若 mid < k ,则更新 left = mid + 1

3. 由于每次查找的过程是重复的,因此我们将查找的过程放到一个 while 循环里面;循环条件是 left <= right

4. 查找的结果有两种:查找成功 or 未查询到,因此我们设置一个标志变量 flag = 0; ,若查找成功,就将 flag = 1 ;循环结束后只要判断 flag 是否为 1,即可知道查找成功与否

以上就是二分查找的整体思路,下面让我们来写代码吧


三. 代码演示

3.1 初代码

cpp 复制代码
#include <stdio.h>

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 0;
	scanf("%d", &k);//输入要查找的数字
	int sz = sizeof(arr) / sizeof(arr[0]);
	//定义左右下标及中间元素下标
	int left = 0;
	int right = sz - 1;
	int mid = 0;
	int flag = 0;//标志变量,0未查询到,1查找成功

	while (left <= right)
	{
		mid = (left + right) / 2;
		if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else if (arr[mid] > k)
		{
			right = mid - 1;
		}
		else
		{
			//查找成功,跳出循环
			flag = 1;
			break;
		}
	}

	if (flag == 1)
	{
		printf("查找成功,下标为%d\n", mid);
	}
	else
	{
		printf("查找失败\n");
	}

	return 0;
}

3.2 优化点---计算平均值

当数字非常大时,left + right 很有可能越界,导致算得的中间值 mid 出错,因此我们换一种求平均值的方法: int mid = left + (right - left) / 2; 。因为输入的 left、right 没有越界,而 left + (right - left) / 2 < right,所以就避免了越界这一问题

3.3 优化代码

cpp 复制代码
#include <stdio.h>

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 0;
	scanf("%d", &k);//输入要查找的数字
	int sz = sizeof(arr) / sizeof(arr[0]);
	//定义左右下标及中间元素下标
	int left = 0;
	int right = sz - 1;
	int mid = 0;
	int flag = 0;//标志变量,0未查询到,1查找成功

	while (left <= right)
	{
		//mid = (left + right) / 2;
		mid = left + (right - left) / 2;//优化处
		if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else if (arr[mid] > k)
		{
			right = mid - 1;
		}
		else
		{
			//查找成功,跳出循环
			flag = 1;
			break;
		}
	}

	if (flag == 1)
	{
		printf("查找成功,下标为%d\n", mid);
	}
	else
	{
		printf("查找失败\n");
	}

	return 0;
}

结语

通过本文你将对二分查找有一个更好的了解,代码就是这样在不断地改进中优化的,有任何问题或建议欢迎留言讨论~

相关推荐
kaikaile19953 分钟前
能量算子的MATLAB实现与详细算法
人工智能·算法·matlab
tankeven6 分钟前
HJ175 小红的整数配对
c++·算法
Aaron158811 分钟前
数字波束合成DBF与模拟波束合成ABF对比浅析
大数据·人工智能·算法·硬件架构·硬件工程·信息与通信·信号处理
成都易yisdong13 分钟前
实现三北方向转换计算器(集成 WMM2025 地磁模型)
开发语言·windows·算法·c#·visual studio
汀、人工智能13 分钟前
[特殊字符] 第91课:课程表
数据结构·算法·数据库架构·图论·bfs·课程表
wfbcg25 分钟前
每日算法练习:LeetCode 36. 有效的数独 ✅
算法·leetcode·职场和发展
jolimark1 小时前
C语言标准与编译器,新手该看哪些?
c语言·开发工具·环境搭建·编译器·新手指南
智者知已应修善业1 小时前
【51单片机非精准计时2个外部中断启停】2023-5-29
c++·经验分享·笔记·算法·51单片机
QQ676580081 小时前
基于YOLO26算法的智慧农业橙子图像识别 橙子采摘识别 水果采摘识别 高清采摘过程图像识别 YOLO+voc个数据集第10410期
算法·yolo·橙子采摘·水果采摘识别·高清采摘过程图像识别
潇洒畅想1 小时前
1.2 希腊字母速查表 + 公式阅读实战
java·人工智能·python·算法·rust·云计算