二分查找法及变种(c++代码实现)

查找问题是计算机中非常重要的基础问题,本篇主要针对二分搜索树进行深入的探讨。首先我们从最简单的二分查找法开始介绍。

二分查找法

对于有序数列,才能使用二分查找法(先排序!)

[分析]

例如,在有序数组中查找元素a

首先,找到数组的中间元素v
在这里插入图片描述
由于数组的有序性,所以元素v把数组分为了两个部分
在这里插入图片描述
通过比较待查找元素a和中间元素v的关系,缩短查找范围。
若a==v 返回v
若a>v 则在>v中查找
若a<v 则在<v中查找

以此类推找到待查找元素。

[代码实现]

迭代:

template<typename T>
int binarySearch(T arr[], int n, T target){
	//在arr[l,...,r]中查找
	int l = 0;
	int r = n-1;
	while(l<=r){
		int mid = (l+r)/2;//l+(r-l)/2可解决溢出问题
		if(arr[mid] == target)
			return mid;
		else if(arr[mid]>target)
			r = mid - 1;//查找区间arr[l,...,mid-1]
		else
			l = mid + 1;//查找区间arr[mid+1,...,r]
	}
	return -1;//没有找到待查找元素
}

递归:

template<typename T>
int binarySearch(T arr[], int l, int r, int target){
	if(l>r)
		return -1;
	int mid = (l+r)/2;
	if(arr[mid] == target)
		return mid;
	else if(arr[mid]>target)
		return binarySearch(arr,l,mid-1,target);
	else
		return binarySearch(arr,mid+1,r,target);
}

[二分查找法的变种]

[floor]-地板

二分查找法, 在有序数组arr中, 查找target
如果找到target, 返回第一个target相应的索引index
在这里插入图片描述
如果没有找到target, 返回比target小的最大值相应的索引, 如果这个最大值有多个, 返回最大索引
在这里插入图片描述ng)
如果这个target比整个数组的最小元素值还要小, 则不存在这个target的floor值, 返回-1

[floor-代码实现]
template<typename T>
int floor(T arr[], int n, int target){
	int l = -1, r = n-1;
	//寻找比target小的最大值得索引
	while(l<r){
		int mid = l+(r-l+1)/2;//向上取整防止进入死循环
		if(arr[mid]>=target)
			r = mid - 1;
		else
			l = mid;
	}
	assert(l == r)
	if(l+1<n && arr[l+1] == target)
		return l+1;//找到target元素,返回第一个target元素位置,及l+1
	else
		return l;//否则返回比target小的最大值相应的索引,也就是l本身
}
		

[ceil]-天花板

二分查找法, 在有序数组arr中, 查找target
如果找到target, 返回最后一个target相应的索引index
在这里插入图片描述
如果没有找到target, 返回比target大的最小值相应的索引, 如果这个最小值有多个, 返回最小的索引
在这里插入图片描述
// 如果这个target比整个数组的最大元素值还要大, 则不存在这个target的ceil值, 返回整个数组元素个数n

[ceil-代码实现]
template<typename T>
int ceil(T arr[], int n, int target){
	int l = 0, r = n;
	//寻找比target大的最小值得索引
	while(l<r){
		int mid = l+(r-l)/2;//向下取整防止进入死循环
		if(arr[mid]<=target)
			l = mid +1;
		else
			r = mid;
	}
	assert(l == r)
	if(r-1>=0 && arr[r-1] == target)
		return r-1;//找到target元素,返回最后一个target元素位置,及r-1
	else
		return r;//否则返回比target大的最小值相应的索引,也就是r本身
}

[upper_bound]-上界

upper_bound
即在一个有序数组arr中, 寻找大于target的元素的第一个索引
在这里插入图片描述
如果存在, 则返回相应的索引index
否则, 返回arr的元素个数 n

[upper_bound-代码实现]
template<typename T>
int upper_bound(T arr[], int n, int target){
	int l = 0, r = n;
	while(l!=r){
		int mid = l+(r-l)/2;
		if(arr[mid]<=target)
			l = mid + 1;
		else 
			r = mid;
	}
	return l;
}

[lower_bound]-下界

lower_bound
即在一个有序数组arr中, 寻找大于等于target的元素的第一个索引
在这里插入图片描述
如果存在, 则返回相应的索引index
否则, 返回arr的元素个数 n

[lower_bound-代码实现]
template<typename T>
int lower_bound(T arr[], int n, int target){
	int l = 0, r = n;
	while(l!=r){
		int mid = l+(r-l)/2;
		if(arr[mid]<target)
			l = mid + 1;
		else 
			r = mid;
	}
	return l;
}

想说得话

本期主要整理了二分查找法和二分查找法得相关变种问题,下期正式进入二分搜索树。大家加油~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值