【问题标题】:What's the time complexity of std::lower_bound with std::set?std::lower_bound 与 std::set 的时间复杂度是多少?
【发布时间】:2013-08-11 09:28:04
【问题描述】:

我知道有std::set::lower_bound,时间复杂度是O(log),我看到std::lower_boundstd::set::lower_bound上运行时比std::set::lower_bound慢得多。

我搜索了一下,发现了这个:

http://en.cppreference.com/w/cpp/algorithm/lower_bound http://en.cppreference.com/w/cpp/iterator/advance

因此很明显,由于std::advance 对于set::iterator 是线性的,所以整个std::lower_bound 占用了O(n)

但是,当我使用它时,它的运行速度比O(n) 快得多(一些朋友也这么说),谁能解释一下原因或告诉我它不是那样的。

【问题讨论】:

    标签: c++ algorithm stl set complexity-theory


    【解决方案1】:

    std::lower_bound() 在非随机访问迭代器上的保证复杂度为O(n)。如果这个算法检测到搜索是在一个有序的关联容器上,它可能会利用树结构的优势,可能会实现更好的复杂性。是否有任何实现这样做,我不知道。

    【讨论】:

    • 根据 25.4.3.1 lower_bound:复杂性:最多 log2 (last − first) + O(1) 比较。
    • @DieterLücking:复杂性总是很难定义……Dietmar Kühl 在这里展示了整体复杂性,而您专门针对比较的数量。因此,你们俩都是对的:在最坏的情况下,迭代次数为 O(N),比较次数为 O(log2(N))。哪个最终主导运行时间取决于具体情况。
    • @Dietmar Kühl “如果这个算法检测到搜索是在一个有序的关联容器上,它可能会利用”你确定吗?因为en.cppreference.com/w/cpp/algorithm/lower_bound 告诉我们对std::set 使用std::set::lower_bound,对std::multiset 使用std::multiset::lower_bound,所以它调用“首选”方式:) std::lower_bound 尝试也是如此猜测数据类型?
    【解决方案2】:

    TL;DR: 每当容器提供与现有算法同名的方法时,它这样做是因为内部实现更快(依赖于容器的属性),因此您应该只使用它。


    问题在于复杂性变化无常:O(N) what ?

    非随机访问迭代器的复杂性保证是:

    • O(N) 次迭代
    • O(log2(N)) 次比较

    取决于迭代或比较是瓶颈,这实际上改变了一切!

    理论上,对于已排序的关联容器,可能希望专门化std::lower_bound 以利用数据已经排序这一事实;但在实践中相对困难。主要问题是没有人知道set 的比较谓词和传递给lower_bound 的比较谓词确实是相同的,因此算法需要假设情况并非如此(除非另有证明)。由于该算法采用 iterators 而不是 ranges/container,因此证明其他情况留给读者作为练习

    【讨论】:

      猜你喜欢
      • 2012-07-31
      • 2011-11-21
      • 1970-01-01
      • 1970-01-01
      • 2015-10-27
      • 1970-01-01
      • 2020-07-15
      • 2014-11-29
      • 2022-10-22
      相关资源
      最近更新 更多