二分查找(折半查找)算法教学

二分查找(折半查找)算法教学

使用二分查找的好处

在这里我用日常生活举例.比如询问一台电脑的价格,它的价格区间在**(1, 10000)**之间.我们的第一反映肯定是询问价格是超于5000还是低于5000,这样可以排除一半的错误答案,再以此类推,不断砍半.最终会以小于14次折半找到正确答案(2^14^=16384).比1元,2元,3元这种每次加一的询问不知道好多少(现实应该不会遇到这种人).

二分查找在代码中的逻辑(运算过程)

在数组中实现二分查找必须要能满足一个条件--数组是有序数组 ,像我们的价格一样,从1到10000之间是有序的. 我们假设有这样一个数组 像在日常中询问价格一样,我们需要知道它的价格区间,在这里体现为下标的区间.最左边的下标是0 ,那么右边的下标怎么计算呢?一个个算不成? 肯定不是,这里我给大家推荐一种方法:函数sizeof

sizeof(arr)算出的是数组的大小,也就是一共有多少个字节.int类型是4个字节,这个数组10个元素,那就是40个字节.用数组的总大小40个字节除以数组一个元素的大小4个字节就能知道数组的元素为10个 这下子我们也就知道了最右边的下标为10-1=9(下标是由0开始的,而元素个数是由1开始的). 然后跟上面的举例一样,我们要知道它的中间值,也就是 然后我们每次要将我们要查找的数字k(假设k=6),跟数组的中间值arr[mid]进行比较.当mid=4时,arr[mid]=5,5<6.这个时候我们发现一个比较是无法解决问题的,我们要添加循环.在我们进行第二轮查找时,因为arr[mid]<k,所以我们要改变left的值,将left改为mid+1.right不变. 若arr[mid]>k,我们要改变right的值,将right改为mid-1.left不变. 遇到arr[mid]=k,跳出循环. 即`

c 复制代码
    if (k < arr[mid])
		right = mid - 1;
	else if (k > arr[mid])
		left = mid + 1;
	else
		break;

因为在循环中mid的值一直会改变,所以将mid = (left + right) / 2写到循环里面. 循环的判断条件是left<=right.(要判断物品的价格一定要有个区间,就算这个区间只有一个数)

二分查找实现在主函数内

c 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	//            0,1,2,3,4,5,6,7,8,9
	int sz = sizeof(arr) / sizeof(arr[0]);
	int left = 0, right = sz - 1;
	
	int k = 0, mid =0;
	scanf("%d", &k);
	while (left <= right) {
		mid = (left + right) / 2;
		if (k < arr[mid])
			right = mid - 1;
		else if (k > arr[mid])
			left = mid + 1;
		else
			break;
	}
	if (left <= right)
		printf("找到了,下标是%d\n", mid);
	else
		printf("找不到\n");
	return 0;
}

在自定义函数实现二分查找函数

c 复制代码
int find(int arr[], int sz, int k) {
	int left = 0, right = sz - 1,mid=0;
	while (left <= right) {
		mid = (left + right) / 2;
		if (k < arr[mid])
			right = mid - 1;
		else if (k > arr[mid])
			left = mid + 1;
		else
			return mid;
	}
	return -1;
}
int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	//            0,1,2,3,4,5,6,7,8,9
	int sz = sizeof(arr) / sizeof(arr[0]);
	
	
	int k = 0;
	scanf("%d", &k);

	int ret = find(arr, sz, k);
	if (ret==-1)
		printf("找不到\n");
	else
		printf("找到了,下标是%d\n", ret);
	return 0;
}
c 复制代码
在这里插入代码片

##改进和易错之处 与我们要寻找的元素k相互比较的是数组中的元素,不是中间值mid 2.mid在每次循环中的改变可以写成

c 复制代码
mid = left + (right-left)/2;

这样修改的会让我们的mid更加"耐打".*当我们的left和right都大于int类型最大值的一半或者两者相加大于大于最大值时会导致栈溢出,使得到的mid数据缺失.*这样子可以修改避免二者直接相加.

复制代码
相关推荐
DKPT5 分钟前
数据结构之快速排序、堆排序概念与实现举例
java·数据结构·算法
Hiweir ·18 分钟前
机器翻译之创建Seq2Seq的编码器、解码器
人工智能·pytorch·python·rnn·深度学习·算法·lstm
star数模31 分钟前
2024“华为杯”中国研究生数学建模竞赛(E题)深度剖析_数学建模完整过程+详细思路+代码全解析
python·算法·数学建模
Tak1Na33 分钟前
2024.9.19
算法
sjsjs111 小时前
【数据结构-扫描线】力扣57. 插入区间
数据结构·算法·leetcode
王哈哈嘻嘻噜噜1 小时前
数据结构中线性表的定义和特点
数据结构·算法
一杯茶一道题1 小时前
LeetCode 260. 只出现一次的数字 III
算法·leetcode
MogulNemenis1 小时前
力扣415周赛
java·数据结构·算法·leetcode
Rense11 小时前
常用的基于无线射频( UWB)室内定位技术的原理与算法
算法
zzhnwpu1 小时前
代码随想录算法训练营第三七天| 动态规划:完全背包理论基础 518.零钱兑换II 377. 组合总和 Ⅳ 322. 零钱兑换
算法·leetcode·动态规划