std :: lower_bound和std :: find在普通数组上

时间:2012-06-01 15:53:40

标签: c++ algorithm stl find lower-bound

我喜欢在普通数组上使用std::algorithm。现在我有两个疑惑;假设我想使用std::lower_bound如果找不到我作为参数提供的值会发生什么?

int a[] = {1,2,3,4,5,6};
int* f = std::lower_bound(a,a+6,20);

打印* f时的结果是20.

如果我使用std::find,也会发生同样的情况。

int a[] = {1,2,3,4,5,6};
int* f = std::find(a,a+6,20);

打印* f时的结果是20.

  1. 返回值始终是原始参数 什么时候找不到?
  2. 在性能方面std::lower_bound表现得更好std::find,因为它实现了二进制搜索算法。如果数组很大,说最多10个元素,std :: find可以表现得更好吗?在幕后std :: lower_bound调用std :: advance和std :: distance ..可能我也可以保存这些调用吗?
  3. 非常感谢

    AFG

4 个答案:

答案 0 :(得分:16)

  

我的结果是20.(后来编辑为:打印* f时的结果是20。)

不,你得到的结果是a+6。取消调用未定义的行为。它可能打印20,它可能会打印“Shirley MacLaine”,或者它可能会炸毁你的车。

  

当找不到时,返回值是否始终是原始参数?

在您的情况下,返回值始终是 2nd 参数,因为20大于数组中的任何其他值。如果未找到该值,但小于某个现有值,则返回值指向下一个较大的项目。

cppreference.com开始,std :: lower_bound的返回值是“迭代器指向不小于value的第一个元素,如果没有找到这样的元素,则为last。 “

  

在表现方面......

测量它。这里没有其他建议能够经得起您的实际经验证据。

  

在幕后std :: lower_bound调用std :: advance和std :: distance ..可能我也可以保存这些调用吗?

几乎肯定不是。在您的情况下,这些调用几乎肯定会针对单个(或极少数)指令进行优化。

答案 1 :(得分:6)

在您的示例中,您不得取消引用f,因为它等于a+6。无论如何,你有,所以你在UB领域,但我认为值20恰好在数组a之后的堆栈上。

对于足够小的数组,线性搜索可能比二进制搜索更快。 10是“小”,不是“大”。如果你有一个对小数组进行大量搜索的程序,你可以给每个程序计时并查看。

std::advancestd::distance基本上没有任何开销 - 任何一半有能力的C ++编译器都会内联所有内容,它们将变成指针加法和减法。

答案 2 :(得分:6)

lower_boundfind返回的迭代器之间存在一个显着差异。如果lower_bound找不到该项,它将返回应插入项的迭代器以保留排序顺序。如果find找不到该项,它将返回结束迭代器(即第二个参数为find)。在你的例子中,因为你试图在数组的末尾找到一些东西,它们都返回相同的迭代器 - 但这完全是巧合。

答案 3 :(得分:1)

您可以使用以下实现

int a [] = {1,2,3,4,5,6};

int f = lower_bound(a,a + 6,20)-a;

现在,如果数组中存在20,它将返回数组a中元素的索引(使用的是基于0的索引)。如果数组中不存在20,它将返回6,即数组的长度。

在最坏的情况下,要搜索的项目出现在第(n-1)个索引[当n是数组的大小时]。然后f将是n-1。

只有当数组中不存在被搜索的项目时,

才会是n或等于数组的大小。

希望它能回答你的问题。