前言
如果有一组有序的数字,我要找到其中的一个数字,我们该怎样去做呢?一般我们是不是会直接利用循环去一个一个比较,那这样会不会太麻烦,效率太低了。那么今天我们就来学习一种新的方法来解决这个问题。
二分法
如果我们给出1,2,3,4,5,6,7,8,9,10这十个元素,我想要找到其中的元素7,那我们是不是可以先找到这些数的中间位置的数呢,那这样我们是不是就缩小了一半的范围呢?那我们在重复这次操作是不是就能找到一个中间值呢,是不是重复下去让中间值与我们要找的数比较就能找到我们要的数呢?如果我们要找的这个数比中间数要大的话,那么这个数就在中间数的右边找,所以范围直接缩小到6,7,8,9,10,又是相同的操作就能很快找到元素7。这样看起来这个方法不仅没有这么简单,而且还相当的复杂,那是因为这些元素的数量比较少,如果给出10000个元素让我们查找一个呢,那么是不是大家想都不用想就知道哪个方法更快,效率更高了呢。接下来我就给大家展示下具体的操作。
1.将元素全部放入一个数组中,在定义好下标,利用下标进行二分法的查询。
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int left = 0;
int right = 9;
int mid;
2.利用中间值与被查找的值进行大小的比较然后缩小范围。
mid = (left + right) / 2;
if (arr[mid] > 7)
rigth = mid - 1;
else if (arr[mid] < 7)
left = mid + 1;
else
printf("找到了,下标为%d", mid);
3.因为我们要进行多次查找所以我们得加上循环,循环条件为right>left.
while (left < right)
{
mid = (left + right) / 2;
if (arr[mid] > 7)
right = mid - 1;
else if (arr[mid] < 7)
left = mid + 1;
else
{
printf("找到了,下标为%d", mid);
break;
}
}
这里我们要记得找到了这个数就给它加上break,来跳出循环。
接下来让我们看看完整的代码。
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int left = 0;
int right = 9;
int mid;
while (left <= right)
{
mid = (left + right) / 2;
if (arr[mid] > 7)
{
right=mid-1;
}
else if (arr[mid] < 7)
{
left = mid+1;
}
else
{
printf("找到了,下标为%d", mid);
break;
}
}
return 0;
}
接下来让我们看到练习题。
写一个函数,实现一个整形有序数组的二分查找。
int binary_search(int arr[], int k, int sz)
{
int left = 0;
int right = sz - 1;
while (left<=right)
{
//int mid = (left + right) / 2;
int mid = left + (right - left) / 2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 0;
scanf("%d", &k);//输入的是要查找的值
//FindNum();
int sz = sizeof(arr) / sizeof(arr[0]);
int ret = binary_search(arr, k, sz);
if (ret == -1)
{
printf("找不到\n");
}
else
{
printf("找到了,下标是:%d\n", ret);
}
return 0;
}
这里我们sizeof操作符将数组的长度算出来,sizeof算出来的是字节数,int型变量一个元素是四个字节,sizeof(arr)/sizeof(arr[0])算出来的就是元素的个数,所以left下标为0,right就为刚刚求出来的长度sz再减去1(sz-1)。
今天的分享就到这里谢谢大家。