代码之家  ›  专栏  ›  技术社区  ›  meguli

C++ STL交织两个范围

  •  0
  • meguli  · 技术社区  · 6 年前

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

    假设我有两个范围 [a1, b1), call R1 [a2, b2) call R2 . 现在,假设 std::distance 结果是一样的,比如说 n . 我想写一个算法

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

    这将以这样的方式重新排序元素:一个r2元素后面跟着一个r1元素,通过所有 2n 元素。取决于 swap ,它也应该重新排序,因为R1的一个元素后跟R2的一个元素。

    我用一个额外的存储器和两个for循环来完成这项工作。这个解决方案很简单。如果我尝试的时间再长一点,我可能还会想出一个就地解决方案。但我想要的是,通过从STL中汇编算法来实现这一点。如何使用STL解决这个问题?如果解决方案已经到位,那就更好了,但是只要我们使用STL的算法,我也愿意使用额外的存储。

    编辑:不应更改给定范围内元素的排列。换句话说,这应该是 stable_interleave . 这就是为什么我找不到用 std::merge .

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

    1 回复  |  直到 6 年前
        1
  •  1
  •   user4581301    6 年前

    我的使用技巧 std::merge 可能失败。我没有足够的创造力去理解为什么有人会写 merge 所以它可以,但它违反了 Compare 正如下面的评论所指出的,所以有人可以。

    无论如何, 合并 是一种过度杀伤力的解决方案。隐藏额外工作的代码行更少,因为 合并 它的用途比我们这里要复杂得多。

    例子:

    #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 为此付费,调用方应按输入参数的顺序进行调用。