查找问题是计算机中非常重要的基础问题,本篇主要针对二分搜索树进行深入的探讨。首先我们从最简单的二分查找法开始介绍。
二分查找法
对于有序数列,才能使用二分查找法(先排序!)
[分析]
例如,在有序数组中查找元素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;
}
想说得话
本期主要整理了二分查找法和二分查找法得相关变种问题,下期正式进入二分搜索树。大家加油~