std::map::upper_bound 与 std::upper_bound 性能
Posted
技术标签:
【中文标题】std::map::upper_bound 与 std::upper_bound 性能【英文标题】:std::map::upper_bound vs std::upper_bound performance 【发布时间】:2020-01-18 09:53:05 【问题描述】:在一些 CP 比赛中(这很重要),我使用了 2 个版本的 upper_bound 在我的 std::map
中找到上限:
算法上限(1):
auto itr = std::upper_bound(s.begin(),s.end(), somenumber);
if(itr == s.end() || *itr > somenumber2)
//dosth
else
//dosth2
std::map::upper_bound (2):
auto itr = s.upper_bound(somenumber);
if(itr == s.end() || *itr > somenumber2)
//dosth
else
//dosth2
如果我手动输入少量输入,这两个版本都可以使用。但是当涉及到~500.000
时,输入 (1) 超过了时间限制 (4 seconds
) 但 (2) 在0.5/4.0 second
中完成了工作。
我查看了文档 algorithm/upper_bound 和 map/upper_bound 并且都具有 O(c log(n))
复杂性(我认为在这两种情况下 c
应该是相似的。所以问题是 - 是什么导致了这种差异?
【问题讨论】:
【参考方案1】:cppreference page for std::upper_bound
表示完成的比较次数是对数,但它也继续:
但是,对于非 LegacyRandomAccessIterators,迭代器增量的数量是线性的。
std::map
没有随机访问迭代器,因此std::upper_bound
将允许由于增量而在迭代器距离上具有线性时间复杂度,而std::map::upper_bound
需要在容器大小上具有对数时间复杂度.
【讨论】:
我已经读过 - 我认为由于 map::upper_bound 中的对数时间存在一些 std::upper_bound 的专业化地图。好的,现在很清楚并理解为什么在std::map
中存在特殊版本的upper_bound 并且算法upper_bound 仅在一般情况下有效(没有关于某些STL 结构的任何额外信息)。
@mvxxx 在该实践的标准库中还有其他示例。例如:std::sort
与 std::list::sort
。
@mvxxx 我现在不确定,但可能有一些神秘的原因,使用 std::upper_bound
的 std::map
特定算法在提供 std::map
迭代器时会使实现不合格.
也许是为了某种哲学?来自algorithm
的 std::map::upper_bound
从根节点开始执行树搜索(假设map
实现为红黑树)。这也是map::upper_bound
不接受迭代器对的原因(它总是搜索整个容器)。 std::upper_bound
更通用,这就是它不使用 map::upper_bound
的原因。以上是关于std::map::upper_bound 与 std::upper_bound 性能的主要内容,如果未能解决你的问题,请参考以下文章