BinarySearch二分查找算法 C语言

3 篇文章 0 订阅
3 篇文章 0 订阅

假设有一个人要我们猜0-99之间的一个数,那么最好的方法就是从0-99的中间数49开始猜。
如果要猜的数小于49,就猜24(0-48的中间数);如果要猜的数大于49,就猜74(50-99的中间数)。
重复这个过程来缩小猜测的范围,直到猜出正确的数字。二分查找的工作方法就是如此。

基本概念:
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。
首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,
如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,
如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。
重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

算法要求:
1.必须采用顺序存储结构。
2.必须按关键字大小有序排列。

二分查找法查找的数列,是一个有序集合。首先找到这个有序集合的最中间的元素。然后判断,
这个元素比需要找的元素大,接下来会在左边区域继续查找;反之,这个元素比要找的元素小,
则在右边区域进行查找。重复以上查找,直到找到这个查找的元素或者对数据集无法再分割为止。

二分查找法可以应用于任何类型的数据,只要将这些数据按照规律进行排序即可。

二分查找的接口定义:
int binary_search(int key, int arr[], int n);
返回值:若查找成功,返回目标的索引值;查找失败,返回-1。
描述:二分查找法,key是传递的要查找的元素,arr[]为已经输入的元素数组,n为数组元素的个数。
复杂度:O(lgN),N为要查找的元素个数。

二分查找法的实现:
二分查找法本质上就是不停的对有序数列进行分割,并检查区域中的中间元素。
有序数列放在arr[]中,需要查找的元素为key,n为数组的元素个数。

实现二分查找法,可以通过定义数列的左右边界值为变量left和right,用这两个变量来控制一个循环进行查找。
1.先将left设置为0,right设置为n-1,每次循环,设置left和right之间的中间值为mid。
2.如果位于mid的元素大小比key要小,将左边索引值left移动至mid后的一个元素位置上,即下一次循环要搜索的区域是当前区域的下半区。
3.如果位于mid的元素大小比key要大,将右边索引值left移动至mid前的一个元素位置上,即下一次循环要搜索的区域是当前区域的上半区。
4.随着不断循环搜索,左索引left从左向右移,右索引right从右向左移。
5.只要在mid这个位置找到了我们要找的数key,查找立即停止,并返回我们要的值;如果没有找到,left和right将重合。

 

注:图来源于博客园的IDreamo

 

C代码:

#include <stdlib.h>

/*二分查找函数binary_search*/
/*传参需要查找的元素key,输入的数组arr,输入的数组长度n*/
int binary_search(int key, int arr[], int n) {
	/*声明变量,左边界值left,右边界值right, 
	  中间值mid,用于记录查找次数count,用于记录查找成功次数count1*/
	int left, right, mid, count=0, count1=0;
	/*左边界值从最左边下标为0的位置开始*/
	left = 0;
	/*右边界值从数组长度减1的位置开始,也就是最右边*/
	right = n - 1;
	/*在查找范围不为0的情况下,执行循环语句*/
	while(left < right) {
		count++;					//记录查找的次数 
		mid = (left + right) / 2;	//计算中间值的下标 
		if (key < arr[mid]) {		//如果要查找的元素小于中间值 
			right = mid - 1;		//确定左子表的范围 
		}
		else if (key > arr[mid]) {	//如果要查找的元素大于中间值 
			left = mid + 1;			//确定右子表的范围 
		}
		/*如果要查找的元素等于中间值元素*/
		else if (key = arr[mid]) {
			printf("查找成功!\n 查找了%d次,arr[%d]=%d", count, mid, key);
			count1++;	//记录查找成功的次数 
			break;
		}
	}
	/*如果一次都没有查找成功*/
	if (count1 = 0) 
		printf("查找失败!");
	return 0;
}

/*主函数*/ 
int main() {
	/*声明用于键盘输入的变量i,用于查找
 	  的元素key,数组arr,数组长度n*/
	int i, key, arr[100], n;
	printf("请输入数组的长度:\n");
	scanf("%d", &n);
	printf("请输入数组的元素:\n");
	for (i=0;i<n;i++) {
	scanf("%d", &arr[i]);
	}
	printf("请输入你要查找的元素:\n");
	scanf("%d", &key);
	/*调用二分查找函数*/
	binary_search(key, arr, n);
	printf("查找完毕!\n");
	return 0;
}

 

运行结果:

请输入数组的长度:
8
请输入数组的元素:
1 2 3 4 5 6 7 8
请输入你要查找的元素:
2
查找成功!
 查找了2次,arr[1]=2查找完毕!

 

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值