【问题标题】:fast way partially sort objects快速部分排序对象
【发布时间】:2012-04-26 21:20:18
【问题描述】:

我有一个例程,我在其中定义了一堆对象(大约 20 个),称它们为 Jet,它们有一个定义的 <,我用来对它们进行排序。排序后,我取最低的两个。有什么快速的方法来做到这一点?到目前为止我想到的选项:

  1. boost::ptr_vector<Jet>使用内置的.sort(),取前两个,
  2. boost::ptr_list<Jet>,用.sort(),取前两个
  3. 使用上面的列表,但不是排序,而是使用max_element,删除元素,然后再次运行。

我认为使用std::vector<Jet> 是最糟糕的选择,因为:我不需要随机访问;排序将在内存中移动对象;并且在调用push_back(Jet) 时将复制对象。由于需要复制,我还假设std::list<Jet> 会比boost::ptr_list<Jet> 差。我会进一步假设两次使用max_element 会比对整个列表进行排序更快。

我的逻辑合理吗?性能差异会很大吗?还有其他我没有想到的选择吗?

【问题讨论】:

  • 你为什么不测试它并告诉我们? (另外,你的假设可能是错误的,一定要测试一下)
  • 有效问题:因为我在分析方面不是很有经验,而且我认为这里有人可能比我更聪明。

标签: c++ boost-ptr-container


【解决方案1】:

您的一个假设是正确的,因为存储指针而不是对象会更快。

但是,如果您只需要两个最小的元素,则无需对任何内容进行排序。只需取前两个元素,然后遍历 vectorlist 的元素并保留较小的元素。

【讨论】:

    【解决方案2】:

    有一个standard library algorithm 可以做到这一点:

    std::vector<Jet> v;
    // populate v
    std::partial_sort(v.begin(), v.begin() + 2, v.end());
    

    v[0] 现在是最小的元素,v[1] 现在是第二小的元素;其余元素的顺序未指定。 std::vector&lt;&gt; 可以替换为 std::deque&lt;&gt;,因为后者也有随机访问迭代器。

    (请注意,我链接到的页面上提到的复杂性是不正确的;C++11 §25.4.1.3 说复杂性是(last - first) * log(middle - first)。)

    【讨论】:

    • 我喜欢这个答案,但 O(n log(2)) 比 O(n) 更复杂。
    • @Chad:当 K N*log(2) (恰好是~6)。
    • @ildjam (and Chad) 实际上,O(N) 和 O(N log(2)) 是相同的,因为 log(2) 是一个常数。当然,当我们处理一个将 20 视为 N 的大值的问题时,算法复杂性并不是那么重要。如果性能很重要,那么在目标机器上进行分析是唯一能给你一个相关答案的东西。所以,我会从 std::partial_sort 开始(因为它很简单,定义明确,并且已经编写和测试过),看看它是否足够快。
    • @abarnert :关于大 O 符号的非常有效的观点。我只是说给定一个具体的 N,显然越小越好。 :-]
    • 您在误导其他答案(包括我的)。我同意这是一个更好的解决方案,但说它比其他解决方案更复杂是错误的。
    【解决方案3】:

    如果您需要最低的两个对象,您可以创建自己的搜索函数,该函数将在 O(N) 时间内运行。使用排序是 O(N log N) 时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-07
      • 2021-06-15
      • 1970-01-01
      • 2015-06-28
      • 1970-01-01
      • 2016-01-06
      • 1970-01-01
      相关资源
      最近更新 更多