【C】折半(二分)查找(转载)

折半查找也称为二分查找,是一种在有序数组中查找某一特定元素的搜索算法。其优点是查找速度快,缺点是所要查找的数据必须在有序序列中。

1、基本思想 假设有一个升序排列的数组arr,在该数组中查找元素key。首先找出该数组中最中间的元素,然后将最中间的元素mid与所要查找的元素key进行比较,如果相等则返回该元素的下标。如果 mid>key ,那么在mid左边的区间去查找key,如果 mid<key ,那么在mid右边的区间中去查找key。重复上述步骤,直到找到元素key为止,假如没有找到,则返回失败。 假设有n个元素,经过第一次查找后,查找区间缩短为 n/2,经过第二次查找后,查找区间缩短为 n/4,……那么经过k次查找后,查找区间变为n/2^k(ps: n除上2的k次方)。不难发现,k其实就是循环次数,那么最终找到元素key时,n/2^k=1(ps: 这里等于1就表示找到了元素key),因此可以得出最坏情况下该算法的时间复杂度为O(log2n)。(ps: log2n表示以2为底,n的对数,关于时间复杂度可参考浅析时间复杂度和空间复杂度)

2、算法实现a.设置初始查找值:left = 0,right = len - 1;b.取中间位置mid = (left & right) + ((left ^ right) >> 1);(ps:求left与right的平均值,可参考求平均值的4种方法)c.比较key与arr[mid]的大小, 若 arr[mid] == key,则表示查找成功,返回该元素在数组arr中的下标mid, 若 arr[mid] > key,则表示查找区间应该更新为mid左半区间,right = mid - 1, 若 arr[mid] < key,则表示查找区间应该更新为mid右半区间,left = mid + 1,d.重复上述步骤,如果还没有找到元素key,则返回失败。

3、源代码

#define _CRT_SECURE_NO_WARNINGS 1
 
/*
* Copyright (c) 2018, code farmer from sust
* All rights reserved.
*
* 文件名称:BinarySearch.c
* 功能:折半查找,又称为二分查找,旨在查找一个排好顺序的数组中的某个元素
*
* 当前版本:V1.0
* 作者:sustzc
* 完成日期:2018年3月28日22:07:28
*/
 
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
 
/*
*	函数名称:BinarySearch
*
*	函数功能:二分查找排好序的数组中的某个元素
*
*	入口参数:pArr, key, len
*
*	出口参数:mid
*
*	返回类型:int
*/
 
int BinarySearch(int * pArr, int key, int len)
{
	int left = 0;
	int right = len - 1;
	int mid = 0;
 
	assert(NULL != pArr);
	
	while (left <= right)
	{
		mid = (left & right) + ((left ^ right) >> 1);
 
		if (pArr[mid] == key)
		{
			return mid;
		}
		else if (pArr[mid] > key)
			{
				right = mid - 1;	
			}
			else
			{
				left = mid + 1;
			}
	}
 
	return -1;
}
 
int main(void)
{
	int arr[] = {1,2,3,4,5,6,7, 8,9,10};
	int key = 7;
	int len = sizeof(arr) / sizeof(int);
	int ret = BinarySearch(arr, key, len);
	
	if (-1 == ret)
	{
		printf("没找到%d!\n", key);
	}
	else
	{
		printf("找到了%d,它的下标是%d\n", key, ret);
	}
 
	return 0;
}

4、输出结果
在这里插入图片描述

若将数组arr中的元素7去掉,再次运行程序。
在这里插入图片描述


本文来自 sustzc 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/sustzc/article/details/79735176?utm_source=copy

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值