我喜欢在普通数组上使用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.
std::lower_bound
表现得更好std::find
,因为它实现了二进制搜索算法。如果数组很大,说最多10个元素,std :: find可以表现得更好吗?在幕后std :: lower_bound调用std :: advance和std :: distance ..可能我也可以保存这些调用吗?非常感谢
AFG
答案 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::advance
和std::distance
基本上没有任何开销 - 任何一半有能力的C ++编译器都会内联所有内容,它们将变成指针加法和减法。
答案 2 :(得分:6)
lower_bound
和find
返回的迭代器之间存在一个显着差异。如果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或等于数组的大小。
希望它能回答你的问题。