程序或算法的时间复杂度
我们为何要考虑二分查找呢,那是因为在面对很大的数据时它能有效的减少程序运行耗费的时间
1.1、标准二分法查找代码
二分查找的前提是给定目标数据应该是单调的,要么按从小到大顺序排,要么按从大到小排,也就是说给定的数组事先要排好序
函数BinarySearch用于查找某个设定的元素,前提是在从小到大排序的数组里查找,size表示数组的里元素的数目,找到则返回元素下标,否则返回0,复杂度为O(log(n))
#include<stdio.h>
int BinarySearch(int a[], int size, int p)
{
int L = 0;
int R = size - 1;
while(L <= R) //数组区间不为空
{
int mid = L + (R - L) / 2;
if(p == a[mid])
return mid;
else if(p < a[mid])
R = mid - 1;
else
L = mid + 1;
}
return 0;
}
int main()
{
int a[10] = {1, 3, 6, 9, 12, 24, 33, 36, 52, 80};
int n;
scanf("%d", &n);
if(BinarySearch(a,10,n) != 0)
printf("Find it!%d is number : %d\n", n, BinarySearch(a,10,n) + 1);
else
printf("No such digit!\n");
return 0;
}
注:为了防止(L + R)过大溢出,这里mid都设为L + (R - L) / 2.
这里还有一个蓝桥杯题目就是需要二分法,可以看此博文蓝桥杯2017第八届C语言B组省赛习题题解——习题I.分巧克力**加深印象
1.2、变式二分法查找代码
写一个函数LowerBound,在包含size个元素的、从小到大排序的int数组a里查找比给定整数p小,下标最大的元素。找到则返回其下标,否则返回-1
详细C代码如下:
#include<stdio.h>
int BinarySearch(int a[], int size, int p)
{
int L = 0;
int R = size - 1;
while(L <= R) //数组区间不为空
{
int mid = L + (R - L) / 2;
if(p == a[mid])
return mid;
else if(p < a[mid])
R = mid - 1;
else
L = mid + 1;
}
return 0;
}
int LowerBound(int a[], int size, int p)
{
int L = 0;
int R = size - 1;
int Pos = -1;
while(L <= R)
{
int mid = L + (R - L) / 2;
if(p < a[mid])
R = mid - 1;
else
{
Pos = mid;
L = mid + 1;
}
}
return Pos;
}
int main()
{
int a[10] = {1, 3, 6, 9, 12, 24, 33, 36, 52, 80};
int n;
scanf("%d", &n);
// if(BinarySearch(a,10,n) != 0)
// printf("Find it!%d is number : %d\n", n, BinarySearch(a,10,n) + 1);
// else
// printf("No such digit!\n");
if(LowerBound(a, 10, n) != -1)
printf("%d's position is %d\n", n, LowerBound(a, 10, n) + 1);
else
printf("%d's position is %d\n", n, LowerBound(a, 10, n));
return 0;
}
2、二分法求方程的根
求下面方程的一个根 : x3 - 5x2 + 10x - 80 = 0
若求出的根是a,则要求|f(a)| <= 10-6
由高数知识可知,函数的倒数大于0,所以函数是单调递增的,因此我们可以选择一个区域[x1, x2],使得f(x1) < 0,f(x2) > 0,这里要注意的是循环终止条件不再是L > R了,而是f(root) < EPS
具体代码演示如下
#include<stdio.h>
#include<math.h>
#define EPS 1e-6
double f(double n)
{
return n * n * n - 5 * n * n + 10 * n - 80;
}
int main()
{
int i;
double L = 0;
double R = 100;
double root = L + (R - L) / 2;
while(fabs(f(root)) > EPS)
{
if(f(root) > 0)
R = root;
else
L = root;
root = L + (R - L) / 2;
}
printf("%lf\n",root);
return 0;
}