繁体   English   中英

C++ std::lower_bound 和 std::set::lower_bound 的区别?

[英]C++ Difference between std::lower_bound and std::set::lower_bound?

最近,在处理 C++ 编程问题时,我遇到了一些有趣的事情。 我的算法使用了一个非常大的集合,并且会多次使用 std::lower_bound 。 然而,在提交我的解决方案后,与我在纸上做的数学证明我的代码足够快相反,它最终太慢了。 代码如下所示:

using namespace std;

set<int> s;
int x;

//code code code

set<int>::iterator it = lower_bound(s.begin(),s.end(),x);

但是,在从朋友那里得到使用 set::lower_bound 的提示后,所讨论的算法的运行速度比以前快了 waaaaaaaay,并且按照我的数学计算。 更改后的二分查找:

set<int>::iterator it = s.lower_bound(x);

我的问题是这两者有什么区别? 为什么一个工作得比另一个快得多? 难道lower_bound 不应该是一个复杂度为O(log2(n)) 的二分查找函数吗? 在我的代码中,它最终比这慢得多。

std::set通常被实现为一个自平衡树,其中包含一些类似列表的结构。 知道这个结构, std::set::lower_bound将遍历树,知道树结构的属性。 这其中的每一步都意味着遵循左子分支或右子分支。

std::lower_bound需要对数据运行类似于二进制搜索的东西。 但是,由于std::set::iterator是双向的,因此速度要慢得多,需要在检查元素之间进行大量增量。 因此,元素之间所做的工作更加激烈。 在这种情况下,算法将检查 A 和 B 中间的元素,然后调整 A 或 B 之一,找到它们中间的元素,然后重复。

阅读std::lower_bound的 API 后

在非随机访问迭代器上,迭代器前进平均会产生 N 中的额外线性复杂度。

而且我认为 STL 集使用的是非随机访问迭代器,因此如果在 STL 集上使用,它不会进行 O(log N) 二进制搜索

std::lower_bound是一种通用的二分搜索算法,适用于大多数 STL 容器。 set::lower_bound旨在与std::set因此它利用了std::set的独特属性。

由于std::set通常被实现为一棵红黑树,因此可以想象std::lower_bound遍历所有节点,而set::lower_bound只是向下遍历树。

std::lower_bound始终保证O(log n)比较,如果传递RandomAccessIterator ,则仅保证O(log n)时间,而不仅仅是不提供恒定时间std::advanceForwardIterator

同一算法的std::set::lower_bound实现能够使用结构的内部细节来避免这个问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM