【问题标题】:Sorting the std::list of structures by rule按规则对结构的 std::list 进行排序
【发布时间】:2021-07-15 08:36:27
【问题描述】:

我有一个std::list<struct Data> data。我需要根据rule 规则将datahead 排序。

为此,我使用std::list::sort(Compare comp)

下面的实现有效,但是效率低下。在rule列表中查找元素需要遍历列表,计算距离需要再次遍历列表。

数据还能如何排序?也许使用向量、unordered_map 等?

#include <iostream>
#include <list>
#include <algorithm>

struct Data {
    std::string code;
    std::string text;
    std::string head;
};

int main() {
    struct Data data1{"0010", "it is text1", "head3"};
    struct Data data2{"0025", "it is text2", "head1"};
    struct Data data3{"0065", "it is text3", "head2"};
    struct Data data4{"0011", "it is text4", "head2"};
    
    std::list<struct Data> data = {data1, data2, data3, data4};
    
    std::list<std::string> rule = {"head1", "head2", "head3", "head4"};
    

    data.sort([&rule](const Data& first, const Data& second) {
        auto index_a = std::distance(rule.begin(), std::find(rule.begin(),rule.end(),first.head));
        auto index_b = std::distance(rule.begin(), std::find(rule.begin(),rule.end(),second.head));
        return index_a < index_b;
    });
    
    for (auto &it : data)
        std::cout << it.code << "\t" << it.text << "\t" << it.head << "\n";
    
    return 0;
}

【问题讨论】:

  • 您能否详细说明您在使用该排序方法的效率时遇到的问题?
  • 旁白:std::list&lt;struct Data&gt; 中不需要 struct
  • 因为你需要随机访问列表std::vector 可能会给你更好的性能
  • @UlrichEckhardt,在规则列表中查找元素需要遍历列表,计算距离需要再次遍历列表。
  • 请将其放入问题中,而不是作为评论!

标签: c++ sorting stl stdlist


【解决方案1】:

使用提供随机访问的容器(如vectordequearray)可以很容易地解决此问题。对于这些,计算两个迭代器之间的距离是 O(1) 操作,而不是 O(n) 操作。此外,它们可能会减少内存开销并改善 Big O 表示法未涵盖但仍会影响性能的引用局部性。

要查看的另一部分是 find() 调用,因为这仍然需要在 O(n) 中遍历序列。如果您使用某种字典,例如 mapunordered_map,您甚至可以将其减少到 O(log n) 或 O(1)。

最后,如果您希望订单为“head1”...“head4”并非巧合,您可以简单地委托给less&lt;string&gt;,而不是自己实现。

但是:除非您有实际数字证明此代码是性能关键型应用程序的瓶颈,否则您正在过早地进行优化。此外,所有 Big-O 声明都以“有一个 n_0,因此对于所有 n &gt; n_0 ...”开始,您甚至可能无法到达 n_0

【讨论】:

    【解决方案2】:

    使用std::vectorstd_unordered_map 重写了程序。

    改变了std::list::sortstd::sort函数的速度:

    没有标志-O3:

    • 第一个选项:0.000030 秒
    • 第二个选项:0.000017 秒

    带有标志-O3:

    • 第一个选项:0.000009 秒
    • 第二个选项:0.000009 秒

    两个问题:

    1. 一切都正确吗?

    2. 排序时如何申请set::less&lt;std::string&gt;

       std::vector<struct Data> data = {data1, data2, data3, data4};
      
       std::unordered_map<std::string, unsigned> rule = {
           {"head1", 0},
           {"head2", 1},
           {"head3", 2},
           {"head4", 3}
       };
       std::sort(data.begin(), data.end(),
                 [&rule](const Data& first, const Data& second) {
           int index_f = rule[first.head],
               index_s = rule[second.head];
      
           return index_f < index_s;
       });
      
      
       for (auto &it : data)
           std::cout << it.code << "\t" << it.text << "\t" << it.head << "\n";
      
       return 0;
      

      }

    【讨论】:

      猜你喜欢
      • 2019-08-08
      • 1970-01-01
      • 1970-01-01
      • 2011-01-08
      • 1970-01-01
      • 2015-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多