C ++ STL交错两个范围

时间:2018-11-16 05:54:09

标签: c++ stl

我做了一些事情来实现两个范围的交织。这是问题所在。

说我有两个范围[a1, b1), call R1[a2, b2) call R2。现在,假设他们的std::distance结果相同,例如n。我想写一个算法

std::interleave(a1, b1, a2, b2, bool swap)

这将对元素进行重新排序,使得R2的一个元素将通过所有2n元素跟随在R1的元素之后。根据{{​​1}}的值,还应该重新排序,因为R1的一个元素后跟R2的一个元素。

我使用了一个额外的存储和两个for循环来做到这一点。这个解决方案很简单。如果再尝试一点,我也可以提出就地解决方案。但是我想要的是,我想通过从STL组装算法来实现这一目标。您如何使用STL解决此问题?如果就地解决方案会更好,但是只要我们使用STL中的算法,我也愿意使用其他存储。

编辑:在给定范围内的元素排列不应更改。换句话说,实际上应该类似于swap。这就是为什么我无法提出使用stable_interleave的东西的原因。

应用:一种应用是将视频和图像格式从平面转换为非平面或半平面。

1 个答案:

答案 0 :(得分:1)

我使用std::merge的建议可能会失败。我没有足够的创造力去看为什么有人会写merge来写,但是却违反了下面评论中指出的Compare的要求,所以有人可以写。

无论如何,merge是一个过大的解决方案。由于merge的预期用途比我们在这里要完成的工作更为复杂,因此隐藏额外工作量的代码行更少。

示例:

#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
#include <list>
#include <deque>

template<typename IN1,
         typename IN2,
         typename OUT>
inline OUT interleave(IN1 it1,
                      IN1 end1,
                      IN2 it2,
                      IN2 end2,
                      OUT out)
{
    // interleave until at least one container is done
    while (it1 != end1 && it2 != end2) 
    {
        // insert from container 1
        *out = *it1;
        out++;
        it1++;
        // insert from container 2
        *out = *it2;
        out++;
        it2++;
    }
    if (it1 != end1) // check and finish container 1
    {
        return std::copy (it1, end1, out);
    }
    else if (it2 != end2)// check and finish container 2
    {
        return std::copy (it2, end2, out);
    }
    return out; // both done
}

int main()
{
    // fill the containers  with numbers
    std::vector<int> in1 = {1,3,5,7,9};
    std::list<int> in2 = {8,6,4,2};

    // construct output container of sufficient size.
    // Could also use empty container and *_inserter
    std::deque<int> out(in1.size() + in2.size());

    // Container-agnostic. reads from vector and list and stores in deque
    interleave(in1.begin(), in1.end(),
               in2.begin(), in2.end(),
               out.begin());
    for (int val: out)
    {
        std::cout << val << ' ';
    }
}

注意:调用者应该在输入参数的顺序颠倒的情况下进行调用,而不是使用交换输入顺序的选项并使所有interleave的用户为此付费。