本质:数学中的二分法(提前说好,本人小白,欢迎大家来吐槽)
前言
现在有这样的一个问题:如果我们要在一个升序的数组中找到某一个数,该怎么找?
一、找数字的普通算法?
#include<stdio.h>
int main()
{
int arr[] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
int left = 0;//该数组的左下标.
int sz = sizeof(arr) / sizeof(arr[0]);//计算数组长度.
int right = sz - 1;//该数组的右下标.
int n = 0;
printf("请输入你要查找的数字:");
scanf("%d", &n);
for (left = 0; left <= right; left++)
{
if (arr[left] == n)
{
printf("找到了\n");
break;
}
}
if (left > right)//当left=right时还是没有找到这个数则证明这个数不在数组中,而且此时left-1=right.
{
printf("找不到\n");
}
return 0;
}
//这样做虽然可以满足要求,但会将所有的数字进行一个比较,如果数组较大,那么就会显得很啰嗦
//然而我们一般是要查找很庞大的数据中的某个数据,那么以上的这种算法就显得非常低效.
二、二分查找
原理:
如果我们要在一大堆有序的数据中找其中的某一个数,我们是不是可以联想到用数学中的二分法来做呢?
事实上,所谓的“二分查找法”实际上就是数学中的“二分法”.
图解如下
若用普通的查找方法,我们一共要查找7次,但是若是使用二分查找的方法我们只需要查找4次,想象一下每查找一次,会少去一半的数据,那将会是多么的高效,不知大家发现没有,这其实是一个循环。
那我们所找的数字若是不在数组内那该会是什么样子的结果呢?如下所示
由以上的图解我们可以写出如下代码
#include<stdio.h>
int main()
{
int arr[] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
int L = 0;
int n = 0;
printf("请输入你要查找的数字:");
scanf("%d", &n);
int sz = sizeof(arr) / sizeof(arr[0]);
int R = sz - 1;
int M = 0;
while (L <=R)
{
M = (L + R) / 2;
if (arr[M] < n)
{
L = M + 1;
}
if (arr[M]>n)
{
R = M - 1;
}
if (arr[M] == n)
{
printf("找到了,该数字的下标为:%d\n", M);
break;
}
}
if (L>R)
{
printf("找不到\n");
}
return 0;
}
总结
其实若遇到一个不太会的算法,我们完全可以用画图和调试功能来去理解它.
我们要学会透过现象看本质,其实生活中无非就三种结构:分支、循环、选择.