【C语言】C语言实现二分查找(折半查找)

一、前言

在一个有序排列的数组中,想要查找到特定数字(k),通常最容易想到的是一个个数组元素查找,但这种方法只适合于数组元素少,特定数字位置比较靠前的数组。如果有大量的数字等待查找,就要寻找更为快速的方法了。下面详细介绍一种C语言常见的查找方法--二分查找。


二、实现思路

【C语言】C语言实现二分查找(折半查找)_第1张图片

 三、实现代码

mian主函数内实现: 

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int k = 7;//要查找的数字
	int left = 0;//数组最左边起始位置下标
	int right = sz - 1;//数组长度-1=最右边位置下标
	int mid = 0;//相加得到的中间元素下标
	while (left<=right)
	{
		mid = (left + right) / 2;
		if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else if(arr[mid] > k)
		{
			right = mid - 1;
		}
		else
		{
			printf("找到了,下标为:%d\n", mid);
			break;
		}
	}
	if (left > right)
	{
		printf("找不到了\n");
	}
}

自定义binary_search函数实现:(注意:函数名要见名知意)

int binary_search(int arr[], int sz, int k)
{
	int left = 0;
	int right = sz - 1;
	int mid = 0;
	while (left <= right)
	{
		mid = (left + right) / 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[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int k = 7;
	int ret = binary_search(arr, sz, k);
	if (ret == -1)
	{
		printf("找不到\n");
	}
	else
	{
		printf("找到了,下标为%d", ret);
	}
	return 0;
}

代码分析:

  • binary_search()需传递三个函数参数:数组名,数组长度,要查找的数字
  • 如果找到了,返回查找数字的下标位置
  • 如果没有找到,返回-1(数组元素的下标是从0开始的)

运行结果:

【C语言】C语言实现二分查找(折半查找)_第2张图片


四、错误代码示范

int binary_search(int arr[], int k)
{
	int left = 0;
	//错误代码:
	int sz = sizeof(arr) / sizeof(arr[0]);//1
	int right = sz - 1;
	int mid = 0;
	while (left <= right)
	{
		mid = (left + right) / 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[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 7;

	int ret = binary_search(arr, k);
	if (ret == -1)
	{
		printf("找不到\n");
	}
	else
	{
		printf("找到了,下标为%d", ret);
	}
	return 0;
}

代码分析:

  • 数组arr传参,实际上传递的不是数组本身,而是数组首元素的地址
  • 通常用指针变量来存放地址
  • 32位平台上指针的大小是4个字节,64位平台上指针的大小是8个字节
  • sizeof(arr)/sizeof(arr[0]);计算的是指针/指针-->4/4=1
  • binary_search()函数的第一个参数也可以是int* arr

思考:为什么参数传递的是int arr[]或者int* arr而不是int arr[10]?

  • 因为传递过去的是数组首元素的地址,为什么要指定大小呢?
  • []内指定大小是要开辟一个数组吗?数组都还没有传递过来,为什么要开辟数组?
  • 所以,指定大小没有意义,可以不写。

结论:

  • 如果函数内部需要参数部分传递某一个数组的元素个数,一定是在函数外部求出该数组的元素个数,再以实参的方式传递给形参。

五、封装函数和导入静态库(了解)

 步骤:

  • 在该项目工程下新建一个头文件,命名为binary_search.h
  • 在该项目工程下新建一个源文件,命名为binary_search.c
  • 将函数声明放到binary_search.h,函数具体实现放入binary_search.c
  • 右击项目工程-->属性-->常规-->配置类型-->静态库(.lib)
  • ctrl + F7 编译代码 ctrl + F5 运行代码
  • 在项目工程保存文件下找到Debug文件夹,点击Debug文件夹,找到生成的binary_search.lib
  • 新建一个项目工程命名为demo
  • 复制binary_search.h和生成的binary_search.lib两个文件到demo工程文件下的demo文件夹下
  • 打开demo项目,手动添加头文件binary_search.h
  • #pragma comment(lib,"binary_search.lib")放在main主函数之前
  • ctrl + F5 运行代码 得到"找到了,下标为6"的打印结果

应用场景:

  • 假设自己写出了二分查找的代码,客户A想买这份代码,但是你又想同时卖给客户B。
  • 于是只把binary_search.h和binary_search.lib两个文件卖给了客户A
  • 二分查找的具体代码还保存在binary_search.c中,也就是说并没有向这两个客户提供源代码
  • 客户只能调用这个函数但函数内部如何实现的一无所知

你可能感兴趣的:(C语言再识,c语言,后端,排序算法)