二分查找
什么是二分查找?
二分查找针对的是一个有序的数据集合,每次都通过跟区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为 0。
二分查找的查找速度为 O(logn)
区间大小为n的一组数据,查找次数至多为k次,此时n/(2^k) = 1,因此时间复杂度为O(logn)。
二分查找的非递归实现
int binary_search(int a[], int n , int value)
{
int low = 0;
int high = n - 1;
while (low <= high)
{
int mid = low + (high - low) >> 1;// 等价(low + high)/2
if (low > high)
{
return -1;
}
if (a[mid] = value)
{
return mid;
}
if (a[mid] > low)
{
low = mid + 1;
}
else
{
high = mid - 1;
}
}
return -1;
}
用递归法实现一个简单的二分查找
//递归法实现二分查找
int bsearch(int a[], int n , int value)
{
return binary_search_recrusive(a, 0, n - 1, value);
}
int binary_search_recrusive(int a[] , int low, int high, int value)
{
if (low > high)
{
return -1;
}
int mid = low + (high - low) >> 1;
if (a[mid] == value)
{
return mid;
}
if (a[mid] > a[low])
{
binary_search_recrusive(a, mid + 1, high, value);
}
else
{
binary_search_recrusive(a, low, mid - 1, value);
}
}
二分查找实际应用场景
1、首先,二分查找依赖的是顺序表结构,简单点说就是数组。
2、其次,二分查找针对的是有序数据
3、再次,数据量太小不适合二分查找。数据量小用二分查找和顺序遍历消耗的时间差不多,只有数据量大时才能体现二分查找的优势。
4、最后,数据量太大也不适合二分查找。例如当数据量大小为1GB,此时要求1GB的连续内存,很难满足这个要求。
利用二分查找求一个数的平方根
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
/*求解精度设置*/
#define E 0.000001
double mybsearch(double num)
{
double start = 1.0;
double end = num;
double mid = 0.0;
while(1)
{
mid = (start + end)/2;
if(((mid*mid - num) <= E) && ((mid*mid - num) >= -E))
{
return mid;
}
if ((mid*mid - num) > E)
{
end = mid;
}
else
{
start = mid;
}
}
return 0;
}
int main()
{
double num = 0.0;
/*这里需要注意:double的输入方式*/
scanf("%lf",&num);
printf("\r\n num %lf的平方根是%lf",num,mybsearch(num));
return 0;
}
思路:根据x的值,判断求解值y的取值范围。假设求解值范围min < y < max。若0<x<1,则min=x,max=1;若x=1,则y=1;x>1,则min=1,max=x;在确定了求解范围之后,利用二分法在求解值的范围中取一个中间值middle=(min+max)÷2,判断middle是否是x的平方根?若(middle+0.000001)(middle+0.000001)>x且(middle-0.000001)(middle-0.000001)<x,根据介值定理,可知middle既是求解值;若middlemiddle > x,表示middle>实际求解值,max=middle; 若middlemiddle < x,表示middle<实际求解值,min =middle;之后递归求解!
备注:因为是保留6位小数,所以middle上下浮动0.000001用于介值定理的判断