合并N在向量c ++中排序

时间:2016-09-20 15:20:27

标签: c++ algorithm sorting

我有一个带有比较运算符的已排序c ++类的向量。我需要一个对象的矢量排序。是否有任何开源算法可以采用矢量列表或矢量矢量并制作一个有序矢量?

对于n = 2,这很好用:

std::vector<Data> dst;
std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));

1 个答案:

答案 0 :(得分:3)

标准库包含merge function,允许合并两个已排序的向量(特别是)。

假设你有 k 序列,总长度 n 。当然,您可以每次合并2个序列,直到只剩下一个序列,但这是known to be worst-case Θ(k2n)

有两种选择:

  • 按贪婪大小合并在此变体中,每次合并两个最短的序列。这[将最坏情况时间缩短为Θ(k log(k) n)

  • 与优先级队列合并this scheme中,优先级队列包含迭代器和序列索引对,当弹出最小元素时,序列中的下一个项目这个指数被推了。这有时间Θ(log(k)n),因为优先级队列每次最多只有 k 项。

以下包含后者的实现(ideone上的完整代码)。 (我怀疑,虽然渐渐地优于前者,但它具有比前者更高的常数。但是,贪婪算法的通用实现(至少对我而言)有点棘手。)

include <vector>
#include <queue>
#include <iostream>


template<
    class InIts, 
    typename OutIt,
    class Cmp=std::less<typename std::iterator_traits<typename InIts::value_type::first_type>::value_type>>
OutIt merge(const InIts &in_its, OutIt out_it, Cmp cmp=Cmp())
{
    using it_t = typename InIts::value_type::first_type;
    using pair_t = std::pair<it_t, std::size_t>;
    auto pair_cmp = [cmp](const pair_t &lhs, const pair_t &rhs) { return !cmp(*lhs.first, *rhs.first); };
    using q_t = std::priority_queue<pair_t, std::vector<pair_t>, decltype(pair_cmp)>;

    std::vector<std::pair<it_t, it_t>> origs{in_its};
    q_t q{pair_cmp};

    for(std::size_t i = 0; i < origs.size(); ++i)
    {   
        auto &p = origs[i];
        if(p.first != p.second)
            q.push(std::make_pair(p.first++, i));
    }

    while(!q.empty()) 
    {
        auto t = q.top();
        *(out_it++) = *t.first;
        const auto i = t.second;
        q.pop();

        auto &p = origs[i];
        if(p.first != p.second)
            q.push(std::make_pair(p.first++, i));
    }

    return out_it;
}

您可以按如下方式使用它:

int main()
{
    using vec_t = std::vector<int>;

    vec_t v0{1, 2, 3}; 
    vec_t v1{2, 3, 4}; 
    vec_t v2{4, 5, 6}; 

    using vec_it_t = vec_t::iterator;

    std::vector<std::pair<vec_it_t, vec_it_t>> its{
        std::make_pair(std::begin(v0), std::end(v0)),
        std::make_pair(std::begin(v1), std::end(v1)),
        std::make_pair(std::begin(v2), std::end(v2))};

    vec_t res;
    merge(its, std::back_inserter(res));
    for(auto &e: res)
        std::cout << e << std::endl;
}