二分查找算法

本文详细介绍了二分查找算法的原理和步骤,强调了算法要求线性表顺序存储且元素有序。通过示例解释了在升序序列中如何进行查找,包括递归和非递归两种代码实现方式。当目标值等于、小于或大于中间元素时,如何调整搜索范围。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二分查找

原理

二分查找顾名思义,就是把序列分成两半进行查找。

另外,二分查找要求线性表必须使用顺序结构存储,并且容器内部元素排列有序

为了方便,本文的序列都是以升序为例(可有重复元素,返回第一个符合条件的索引值)

假设任意递增有序序列 A,和要查询的值t

首先找到中间值的索引mid,其中l为序列第一个元素的索引,r为最后一个元素的索引。之所以此处不给出 ⌊ ( r + l ) / 2 ⌋ \lfloor(r+l)/2 \rfloor ⌊(r+l)/2 的形式,是因为在编写程序时这种算法可能会溢出。
m i d ( l , r ) = l + ⌊ ( r − l ) / 2 ⌋ mid(l,r) = l + \lfloor(r-l)/2 \rfloor mid(l,r)=l+⌊(rl)/2
然后比较该位置值与所查询值的大小,这样就分成了三种情况:

  • 当值相等时,mid即我们要的索引值
  • 当t小于mid位置的元素时(注意是元素),在左半序列找查,获取左半序列的中间值索引(如下公式),然后重复比较,直到mid位置处的元素为我们所查找的元素。如果直到子序列长度为0都未找到,则说明序列A不存在该元素t,应停止查找。

m i d ( l , m i d ( l , r ) ) mid(l,mid(l,r)) mid(l,mid(l,r))

  • 当t大于mid位置的元素时,在右半序列找查,获取右半序列的中间值索引(如下公式),然后重复比较,直到mid位置处的元素为我们所查找的元素。如果直到子序列长度为0都未找到,则说明序列A不存在该元素t,应停止查找。

m i d ( m i d ( l , r ) + 1 , r ) mid(mid(l,r)+1,r) mid(mid(l,r)+1,r)

现在假设序列A以及要找查元素t的值如下,第一个元素的索引为0,最后一个元素的索引为4
A = { 1 , 2 , 3 , 4 , 5 } ,   t = 2 A = \{1,2,3,4,5\}, \space t=2 A={1,2,3,4,5}, t=2
序列中间元素索引为2,对应元素值为3。

比较t与2的值,有
t < 2 t < 2 t<2
则向左半序列查找,记A的左半序列如下
A l e f t = { 1 , 2 , 3 } A_{left} = \{1,2,3\} Aleft={1,2,3}
再取中间元素的索引为1,比较t与 A l e f t [ 1 ] A_{left}[1] Aleft[1]的值,发现相等,则1即为我们所查询的元素的索引值。

代码实现

代码实现分为递归与非递归两种形式。

递归

/*二分查找,未找到则返回false;找到返回true,并将结果传入index
* arr: 要被查询的有序数组
* l: 查询序列最左的元素的索引
* r: 查询序列最右的元素的索引
* target: 要查询的元素
* index: 返回的结果
 */
bool BinSearch(int arr[], int l, int r, int target, int& index)
{
	if (l >= r)
	{
		if (target == arr[l])
		{
			index = l;
			return true;
		}
		index = -1;
		return false;
	}

	int mid = l + (r - l) / 2;

	if (target > arr[mid])
		return BinSearch(arr, mid + 1, r, target, index);
	else
		return BinSearch(arr, l, mid, target, index);
}

非递归

/*二分查找,未找到则返回false;找到返回true,并将结果传入index
* arr: 要被查询的有序数组
* l: 查询序列最左的元素的索引
* r: 查询序列最右的元素的索引
* target: 要查询的元素
* index: 返回的结果
 */
bool BinSearch(int arr[], int l, int r, int target, int& index)
{
	while (l < r)
	{
		int mid = l + (r - l) / 2;
		if (arr[mid] >= target)
			r = mid;
		else
			l = mid + 1;
	}
	if (arr[l] == target)
	{
		index = l;
		return true;
	}
	else
	{
		index = -1;
		return false;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值