算法三:二分查找

程序或算法的时间复杂度

我们为何要考虑二分查找呢,那是因为在面对很大的数据时它能有效的减少程序运行耗费的时间
在这里插入图片描述在这里插入图片描述

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;
} 

后续我会根据题型的价值把更多典例添加到该算法栏目中。如果有什么好的题目也可以推荐我哦,评论区欢迎各位。

如果喜欢我的文章,请记得三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持,下期更精彩!!!

发布了40 篇原创文章 · 获赞 7 · 访问量 3094

猜你喜欢

转载自blog.csdn.net/qq_44631615/article/details/104856038