目录
1.二分查找介绍
二分查找(Binary search)也称折半查找,是一种效率较高的查找方法。但是,二分查找的直接条件是很高的,要求线性表中的记录必须按关键码有序,并且必须采用顺序存储。
PS:因为讲的比较通俗和简单,我的实力不允许用更好的方法去实现,所以本文更适合新手观看 ,勿喷。
2.二分查找原理
今天我们用一个简单例子来看看二分查找算法的原理:
1.我们设置一个1到10查找区间:left = 1; right = 10;
2. 若查找区间[left, right]不存在,则查找失败;否则转到步骤3;
3.取中间位mid = (left + right) /2; 然后比较 targrt 与 arr[mid], 有以下三种情况:
3.1 若 target < arr[mid],则right = mid - 1; 查找在左半区间进行;
3.2 若 target > arr[mid],则left = mid + 1; 查找在右半区间进行;
3.3 若 target = arr[mid],则查找成功,返回mid值;
3.思路
那么接下来,我们用一个简单的问题来实现二分查找这个算法:
我们设定一个元素为十个大小的数组,然后给这个数组赋上{1,2,3,4,5,6,7,8,9,10}。
假设我们要从中找出7这个元素,那我们应该怎么去找呢,我想很多人会用遍历数组下标来解决这个问题,这时候其实用二分查找会更快更方便。
一次折半过程:
1.首先我们要确定被查找的范围
2.确定被查找范围的左右下标
3.根据左右下标确定中间元素的下标
4.然后用中间元素和要找的元素进行比较
(1)> 找到了就结束
(2)> 没有找到,就根据大小关系确定新的查找范围(折半)
由此可知这个过程是一个循环,每折半一次就循环一次。那么我们是怎么折半的呢?
1.我们知道首次被查找的范围下标在0~9之间,所以左右下标分别为:left = 0 ; right = 9
然后我们用 (left + right) / 2 得到中间元素mid的下标,所以(0+9) /2 = 4.
2.4就是中间元素的下标,对应的元素是5,然后我们和要找的元素7进行比较,发现比7小那么我们就可以把下次查找的下标范围定在5~9(5 = mid + 1) 之间,由此类推我们再次查找
3.(5+9) /2 = 7 对应的元素是8,比7大,由于是升序,所以下标7右边可以排除
4.得到新的范围5~6(6 = mid -1), (5+6) /2 = 5 对应元素是6 ,比7小,现在我们只剩下下标6这个范围
(就算剩下一个值也算一个范围) 所以(6 + 6) /2 = 6 对应元素是7。我们终于在这一次找到了我们想要的元素,我们一共花了四次找到了我们想要的元素,如果在最后一次这种情况还没有找到我们想要的元素的话就是找不到了。
4.代码实现
#include <stdio.h>
int mian()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//升序的数组
//在数组中查找k
int k = 0;
scanf("%d", &k);
int sz = sizeof(arr) / sizeof(arr[0]);
int left = 0;
int right = sz - 1;
while (left <= right)
{
int mid = (left + right) / 2;
if (arr[mid] == k)
{
printf("找到了,下标是:%d\n", mid);
break;
}
else if (arr[mid] < k)
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
if (left > right)
printf("找不到\n");
return 0;
}
运行结果如下:
代码解析:
1.首先我们创立一个升序数组arr[],定义变量K作为我们要找的元素
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//升序的数组
int k = 0;
scanf("%d", &k);
2.我们要用sizeof来计算数组的长度,用数组长度-1然后就可以得到right下标的长度
int sz = sizeof(arr) / sizeof(arr[0]);
int left = 0;
int right = sz - 1;
3.因为我们查找是一个重复的步骤,所以我们这里用一个while循环,只要条件left小于等于right我们就一直进入循环,用mid = (left + right) / 2求中间元素的下标,再嵌套if循环,如果中间元素的下标等于我们要找的元素k就打印找到了然后跳出循环,如果小于元素k 就把中间元素的下标加1,否则减1.
while (left <= right)
{
int mid = (left + right) / 2;
if (arr[mid] == k)
{
printf("找到了,下标是:%d\n", mid);
break;
}
else if (arr[mid] < k)
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
4.我们可以用左下标的值小于右下标的值来作为打印没有找到我们想要元素的条件,也就是 left > right的情况
if (left > right)
printf("找不到目标值\n");
5.总结
总的来说,二分查找最重要的就是区间的赋值和循环条件,是否满足有序,区间赋值left 和 right 的关系决定了循环能不能继续,要同时满足三个条件才能用好这个算法。
如果大家觉得好的话可以点个免费的赞吗,有不好的地方欢迎大家前来指正,谢谢大家!
希望我们可以共勉一起进步
完