C语言——二分查找(图解)

一.什么是二分查找


二分查找也称折半查找,是在一组有序(升序/降序)的数据中查找
一个元素,它是一种效率较高的查找方法。

因为二分查找每次查找都可以剔除一半的查找范围,所以相比顺序查找每次一个一个元素查找,查找效率提高了很多。

二.二分查找的基本思路

  1. 在有序表中,每次都取中间元素作为比较对象。
  2. 如果中间值与目标元素相等,则查找成功,返回该元素的下标。
  3. 如果中间值大于目标元素,则在中间值的右半区间继续查找。
  4. 如果中间值小于目标元素,则在中间值的左半区间继续查找。
  5. 确定了该元素所在范围外的元素就不需要继续查找了,不断重复以上过程,直至找到目标元素。

三.图解例子

给定一个有序数组 arr = {1,3,5,7,9,10,12,15} 中,求数字9所在数组中的下标

二分查找过程:

(1)定义两个指针 left 和 right ;left 指向首元素的下标,right 指向最后一个元素的下标。 key 为目标元素。即:

在这里插入图片描述

(2)求中间元素的值mid,即:mid = left + (right - left) / 2 得到中间下标 通过中间下标可以访问到中间元素 arr[mid] 。即:
在这里插入图片描述

有些小伙伴会问:求中间值为什么不用 mid = (left + right) / 2 呢?

原因:如果是两个较大的值,相加超过了 int 取值范围(2147483647)就会导致溢出。
(3)使用中间值 arr[mid] 和目标值 key 对比,此时 arr[mid] < key 就证明 arr[mid] 左边的值 和 arr[mid]的值都不需要继续对比了。然后将 left 指针移动到 mid + 1 的位置,查找范围就是 [mid + 1, right] 。即:
在这里插入图片描述
(4)继续对比,发现 arr[mid] > key。证明 arr[mid] 的值 和 arr[mid] 右边的值都不需要对比了。就让 right 指针移动到 mid-1 的位置。即:

在这里插入图片描述


(5)现在 arr[mid] 和 key 相等,然后返回 mid ,查找结束。

下面我们来看一道二分查找的例题,巩固理解

题目:

在一个升序数组中查找指定的数值,找到了就返回下标,找不到就返回-1.

示例一:

输入 : arr = { -1,2,3,4,5,6,7,8,9}, key = 6
输出: 5
解释:6出现在arr中并且下标为5.

示例二:

输入:arr = { -1,2,3,4,5,6,7,8,9}, key = 1
输出:-1
解释:1不存在arr中,所以返回-1

第一步

首先是在一个有序的数组中查找某个元素的,那就需要一个数组来存放一些 int 类型的数据,可以通过题目看到除了输入一个数组 arr
外,还需输入一个目标值 key,还有数组的字符串长度 len,方便我们得到 right下标


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void  main()
{
	int arr[] = { -1,2,3,4,5,6,7,8,9, };
	int len = sizeof(arr) / sizeof(arr[0]);
	int key = 0;
	scanf("%d", &key);
}

第二步

写一个二分查找函数,并且定义两个指针 left 和 right,left 为首元素的下标,right(len - 1) 为最后一个元素的下标。
然后求中间元素的下标 mid ( mid = left + (right - left) / 2) 即:
在这里插入图片描述

int bin_search(int arr[], int len, int key)
{
	int left = 0;
	int right = len - 1;
	int mid = left + (right - left) / 2;
}	
void  main()
{
	int arr[] = { -1,2,3,4,5,6,7,8,9, };
	int len = sizeof(arr) / sizeof(arr[0]);
	int key = 0;
	scanf("%d", &key);
	printf("下标:%d", bin_search(arr, len, key));
}

第三步

使用中间元素和目标值(key)做对比,假如key = 6,那么 中间元素(5) < 目标元素(6),中间元素左半部分的值及中间元素本身也就没有必要继续对比了,此时的查找范围为[mid+1,right],也就是 left = mid + 1,right位置不变,即:
在这里插入图片描述

在这里插入图片描述

如果我们查找的值是小于中间元素的时候呢?
当 目标元素 < 中间元素 时,就代表目标元素在中间元素的左半部分,右指针就需要移动,也就是right = mid - 1,left不需要移动,此时查找范围为:[left,mid-1]。

大于和小于的情况都判断了,还有相等的情况,目标元素 == 中间元素 时,就意味着找到该元素了,直接返回该下标即可。代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int bin_search(int arr[], int len, int key);
void  main()
{
	int arr[] = { -1,2,3,4,5,6,7,8,9, };
	int len = sizeof(arr) / sizeof(arr[0]);
	int key = 0;
	scanf("%d", &key);
	printf("下标:%d", bin_search(arr, len, key));
}
int bin_search(int arr[], int len, int key)
{
	int left = 0;
	int right = len - 1;
		if (arrMid < key)
		{
			left = mid + 1;
		}
		else if (arrMid > key)
		{
			right = mid - 1;
		}
		else return mid;
}

第四步

最后重复执行以上过程,每次都让中间元素和目标元素对比,从而缩小范围,直至查找到,如果没查找到就返回-1
在这里插入图片描述
在这里插入图片描述

最后需要注意的是:
1.在查找元素时 left 和 right下标会越来越近甚至指向同一个下标,过程中 left 始终在 right 的左边(即:left <= right)。
2.如果一直找不到那个元素,两个下标必然会相互交错(即: left > right),这时循环结束。所以循环条件就是:while(left <= right)

最终代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int bin_search(int arr[], int len, int key);
void  main()
{
	int arr[] = { -1,2,3,4,5,6,7,8,9, };
	int len = sizeof(arr) / sizeof(arr[0]);
	int key = 0;
	scanf("%d", &key);
	printf("下标:%d", bin_search(arr, len, key));
}
int bin_search(int arr[], int len, int key)
{
	int left = 0;
	int right = len - 1;
	while (left <= right) 
	{
		int mid = left + (right - left) / 2;
		int arrMid = arr[mid];
		if (arrMid < key)
		{
			left = mid + 1;
		}
		else if (arrMid > key)
		{
			right = mid - 1;
		}
		else return mid;
	}
	return -1;

}

运算结果:
在这里插入图片描述

总结:

二分查找最重要的两个点就是区间的赋值和循环条件。
————————————————————————————————————
关于二分查找的讲解就到这里,如果哪里有问题,欢迎大家在评论区指出~~~
在这里插入图片描述

  • 35
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值