C++ 是否有一个内置partial_sort,可以返回排序值的位置

c++ is there a built in partial_sort that returns the location of the sorted values

提问人:unknown 提问时间:12/4/2022 更新时间:12/25/2022 访问量:186

问:

我有一个 N 个元素的列表,想要找到最小(或最大)M 值的位置。 是否有内置函数(沿着 std::sort 或 std::p artial_sort 的思路)可以做到这一点?

C++ 算法 排序 std

评论

1赞 PaulMcKenzie 12/4/2022
如果(非常)大,则值之外的元素,其中堆中的值是值和位置的对。Nstd::make_heapMN
1赞 john 12/4/2022
创建一个并行的索引数组(即 0,1,2,...),然后(部分)对索引数组进行排序(基于索引引用的原始数组中的值)。
1赞 Jerry Coffin 12/4/2022
@john:在这种情况下不需要排序/部分排序。 就足够了——并且通常是线性的,而不是 O(n log n)。std::nth_element
1赞 Jerry Coffin 12/4/2022
您可以按照@john建议创建并行数组,然后用于查找位置中的项目(称为透视)。 还将数组划分为不大于其左侧枢轴的元素和不小于其右侧枢轴的项。存储在并行数组中的索引将告诉您这些元素的位置。std::nth_elementmnth_element
1赞 PaulMcKenzie 12/4/2022
@unknown 由于只有几百个元素,因此将它们全部存储在一个容器中是可以的。另一方面,如果你得到数十万、数百万或源源不断的元素,那么维护一堆 M 个项目将是一个解决方案。堆元素将由找到的数量和位置组成。

答:

1赞 Michaël Roy 12/25/2022 #1

没有内置函数。但是您可以尝试如下操作:

  • 在原始数组中创建迭代器向量。这将比 pair<index、value>s 的向量占用更少的位置,并且可以让您以最快的速度访问原始数据,这是 nth_element() 尽可能高效地运行所必需的。
  • 在向量上调用 std::nth_element()。
  • 通过调用 std::d istance(或减法,对于 c++98)来获取索引。

如:

template <typename Fn>
std::vector<size_t> GetMElementsPositions(const std::vector<int>& v, size_t m,
                                          Fn&& compare) {
    assert(m != 0);
    assert(m <= v.size());

    std::vector<std::vector<int>::const_iterator> w;
    w.reserve(v.size());

    for (auto i = v.begin(); i != v.end(); ++i)
        w.push_back(i);

    std::nth_element(w.begin(), w.begin() + M - 1, w.end(), [&compare](auto& x, auto& y) { return compare(*x, *y); });

    std::vector<size_t> r;
    r.reserve(M);
    for (auto i = w.begin(); i != w.begin() + M; ++i)
        r.push_back(std::distance(v.begin(), *i));

    return r;
}

您还可以跳过 std::d istance()à 部分,并将结果裁剪为大小(如果 M 比原始数据集大小小得多,则复制到较小的数组中。使用迭代器就像使用指针一样简单,而且比使用索引更有效。

你可以在这里找到一个工作原型:https://godbolt.org/z/YjjoanoTb