【问题标题】:How to sort a list of unique_ptrs?如何对 unique_ptrs 列表进行排序?
【发布时间】:2023-04-06 09:25:01
【问题描述】:

我正在尝试编写一个创建 Huffman 树的函数(作为创建 Huffman 编码的一部分)。

该函数接收unique_ptrs 到Node 对象的std::vector,其中包含有关字符、其频率以及左右儿子的信息(unique_ptrs 到其他Nodes)。

本质上,我想做的是将所有对象移动到std::list,如果它们的频率大于0,然后对列表进行排序,然后继续使用将构建树的算法(这是这个问题的范围)。

经过多次尝试让它在只能移动的对象上工作后,我已经成功地正确使用了std::copy_if,但我无法对结果进行排序。

在以下代码中,NodePtrstd::unique_ptr<Node> 的别名,NodeVectorstd::vector<NodePtr> 的别名:

HuffmanEncoderDecoder::NodePtr &HuffmanEncoderDecoder::buildPrefixlessTree(NodeVector &frequencies) {
    std::list<NodePtr> sortedFrequencies;

    // Copy to list only if the character appeared at least once
    std::copy_if(std::make_move_iterator(frequencies.begin()), std::make_move_iterator(frequencies.end()),
        sortedFrequencies.begin(), [](NodePtr &&node) { return node->frequency != 0; });

    // Sort the list by ascending order of frequency
    std::sort(sortedFrequencies.begin(), sortedFrequencies.end(), [](const NodePtr &n1, const NodePtr &n2)
    { return n1->frequency <= n2->frequency; });

    // ...
}

我正在使用clang++,它输出以下错误:

error: invalid operands to binary expression ('std::_List_iterator<std::unique_ptr<HuffmanEncoderDecoder::Node,
      std::default_delete<HuffmanEncoderDecoder::Node> > >' and 'std::_List_iterator<std::unique_ptr<HuffmanEncoderDecoder::Node, std::default_delete<HuffmanEncoderDecoder::Node> > >')
      if (__last - __first > int(_S_threshold))
          ~~~~~~ ^ ~~~~~~~

老实说,我什至不确定这是移动语义问题,还是我遗漏的其他问题,因此不胜感激。

【问题讨论】:

    标签: c++ lambda stl move-semantics


    【解决方案1】:

    std::sort 需要随机访问迭代器。您的容器 std::list&lt;NodePtr&gt; sortedFrequencies 不提供随机访问迭代器 - 仅提供双向迭代器。

    std::list 有一个名为sort 的成员函数,它对你有用。见cppReference

    【讨论】:

    • 顺便说一句,您的比较函数可能不提供严格的弱排序:{ return n1-&gt;frequency &lt;= n2-&gt;frequency; } 因为它为同一个对象返回 true 两次(comp(a, a) 应该返回 false
    • 像魅力一样工作!谢谢!你认为对原始向量进行排序,然后才调用copy_if会更有效吗?
    • 不知道 - 你的名单有多大?如果它很小,那么它可能不会产生(可测量的)差异。
    • 它很小。就我而言,我知道我最多可以有 256 个chars,所以频率向量总是这个大小(我使用vector 而不是array,因为我使用std::generate 来初始化每个@ 987654334@ 有自己的字符)。这也是我使用std::copy_if 的原因(不以0 频率复制chars)。但问题更多的是针对一般情况。
    猜你喜欢
    • 2018-10-30
    • 1970-01-01
    • 1970-01-01
    • 2012-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多