algorithm头文件下的常用函数 lower_bound(),upper_bound()

l o w e r _ b o u n d ( ) lower\_bound() u p p e r _ b o u n d ( ) upper\_bound() 需要用在一个有序数组或容器中,其复杂度均为 O(log(last - first))。

  • l o w e r _ b o u n d ( f i r s t , l a s t , v a l ) lower\_bound(first, last, val) 用来寻找在数组或容器的 [ f i r s t , l a s t ) [first, last) 范围内第一个值大于等于 val 的元素的位置,如果是数组,则返回该位置的指针;如果是容器,则返回该位置的迭代器。
  • u p p e r b o u n d ( f i r s t , l a s t , v a l ) upper_bound(first, last, val) 用来寻找在数组或容器的 [ f i r s t , l a s t ) [first, last) 范围内第一个值大于 val 的元素的位置,如果是数组,则返回该位置的指针;如果是容器,则返回该位置的选代器。

显然,如果数组或容器中没有需要寻找的元素,则 l o w e r _ b o u n d ( ) lower\_bound() u p p e r _ b o u n d ( ) upper\_bound() 均返回可以插入该元素的位置的指针或迭代器 (即假设存在该元素时,该元素应当在的位置)。

示例如下:

#include <stdio.h>
#include <algorithm>
using namespace std;
int main()
{
	int a[10] = {1, 2, 2, 3, 3, 3, 5, 5, 5, 5}; //注意数组下标从0开始
	//寻找-1
	int* lowerPos = lower_bound(a, a + 10, -1);
	int* upperPos = upper_bound(a, a + 10, -1);
	printf("%d, %d\n", lowerPos - a, upperPos - a);
	
	//寻找1
	lowerPos = lower_bound(a, a + 10, 1);
	upperPos = upper_bound(a, a + 10, 1);
	printf("%d, %d\n", lowerPos - a, upperPos - a);
	
	//寻找3
	lowerPos = lower_bound(a, a + 10, 3);
	upperPos = upper_bound(a, a + 10, 3);
	printf("%d, %d\n", lowerPos - a, upperPos - a) ;
	
	//寻找4
	lowerPos = lower_bound(a, a + 10, 4);
	upperPos = upper_bound(a, a + 10, 4);
	printf("%d, %d\n", lowerPos - a, upperPos - a);
	
	//寻找6
	lowerPos = lower_bound(a, a + 10, 6);
	upperPos = upper_bound(a, a + 10, 6);
	printf("%d, %d\n", lowerPos - a, upperPos - a) ;
	return 0;
}

输出结果:

显然,如果只是想获得欲查元素的下标,就可以不使用临时指针,而直接令返回值减去数组首地址即可

#include <stdio.h>
#include <algorithm>
using namespace std;
int main() 
{
	int a[10] = {1, 2, 2, 3, 3, 3, 5, 5, 5, 5}; 	//注意数组下标从0开始
	//寻找3
	printf("%d, %d\n", lower_bound(a, a+10, 3) - a, upper_bound(a, a+10, 3) - a);
	return 0;
}

输出结果:

【补充】

不得不说说前面的"有序序列",这里的"有序"是对什么有序?你可能已经猜到了,它是对于比较器有序,并且必须是升序!当然比较器默认也是""。(为什么不是降序?这个你可能要去问问写STL的人)

一旦对降序序列使用lower_bound,就会出现神奇的错误,具体原因可以看这篇:点击这里

如果要在一个下降序列里寻找一个小于x的数呢?

所以,同样的,lower_bound和upper_bound也是可以加比较函数cmp的:

lower_bound(a+1, a+1+n, x, cmp);
bool cmp(const int& a, const int& b)
{
	return a > b;
}

当然,你也可以这样:

lower_bound(a+1, a+1+n, x, greater<int>());

这里的greater<int>()就是C++友情提供的方便的大于函数,这样就不用自己动手写一个cmp函数了 (其实就是懒)

【总结】

l o w e r _ b o u n d ( ) lower\_bound() u p p e r _ b o u n d ( ) upper\_bound() 都是利用二分查找的方法在一个排好序的数组中进行查找的。

在从小到大的排序数组中,

  1. l o w e r _ b o u n d ( b e g i n ,   e n d ,   n u m ) lower\_bound(begin,\ end,\ num) :从数组的 b e g i n begin 位置到 e n d 1 end-1 位置二分查找第一个大于或等于 n u m num 的数字,找到返回该数字的地址,不存在则返回 e n d end 。通过返回的地址减去起始地址 b e g i n begin ,得到找到数字在数组中的下标。

  2. u p p e r _ b o u n d ( b e g i n ,   e n d ,   n u m ) upper\_bound(begin,\ end,\ num) :从数组的 b e g i n begin 位置到 e n d 1 end-1 位置二分查找第一个大于 n u m num 的数字,找到返回该数字的地址,不存在则返回 e n d end 。通过返回的地址减去起始地址 b e g i n begin ,得到找到数字在数组中的下标。

在从大到小的排序数组中,重载 l o w e r _ b o u n d ( ) lower\_bound() u p p e r _ b o u n d ( ) upper\_bound()

  1. l o w e r _ b o u n d ( b e g i n ,   e n d ,   n u m ,   g r e a t e r ( ) ) lower\_bound(begin,\ end,\ num,\ greater() ) :从数组的 b e g i n begin 位置到 e n d 1 end-1 位置二分查找第一个小于或等于 n u m num 的数字,找到返回该数字的地址,不存在则返回 e n d end 。通过返回的地址减去起始地址 b e g i n begin ,得到找到数字在数组中的下标。

  2. u p p e r _ b o u n d ( b e g i n ,   e n d ,   n u m ,   g r e a t e r ( ) ) upper\_bound(begin,\ end,\ num,\ greater() ) :从数组的 b e g i n begin 位置到 e n d 1 end-1 位置二分查找第一个小于 n u m num 的数字,找到返回该数字的地址,不存在则返回 e n d end 。通过返回的地址减去起始地址 b e g i n begin ,得到找到数字在数组中的下标。

发布了687 篇原创文章 · 获赞 104 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/qq_42815188/article/details/104081496
今日推荐