在没有循环的情况下在C ++中移位数组元

时间:2016-11-26 10:48:37

标签: python c++ arrays list

有没有办法在不使用任何循环的情况下在C ++中移动数组元素,如下面的Python代码,只需通过操作列表索引来移动列表的元素

def rotate(lst, n):
  n = n % len(lst)
  return lst[n:] + lst[:n]

> rotate([1,2,3,4,5], 1)  # rotate forward
[2, 3, 4, 5, 1]

1 个答案:

答案 0 :(得分:0)

C ++标准算法也适用于数组,因此您只需使用std::rotatestd::rotate_copy

功能'但是,在Python示例中,接口比旋转要复杂一些。作为第二个参数,您必须提供一个迭代器,该元素将成为结果数组中的第一个元素

对于数组{ 1, 2, 3, 4, 5 }和一个元素的正向旋转,这将是第二个元素(" 2")。通过向数组的第一个元素(例如array.begin() + 1)添加1,假设您使用std::arrayarray + 1(如果它)&#,您将获得该元素的迭代器39;原始阵列。

#include <iostream>
#include <algorithm>
#include <array>

int main()
{
    std::array<int, 5> array = { 1, 2, 3, 4, 5 };
    std::rotate(
        array.begin(),
        array.begin() + 1,
        array.end()
    );    

    for (auto&& element : array)
    {
        std::cout << element << "\n";
    }
}

如果您想要Python代码中的接口,那么您可以将std::rotate包装在您自己的函数中并提供int参数。这也是一个很好的机会,通过创建一个可以与任何合适的容器一起使用的通用函数,使整个事物更可重用:

#include <iostream>
#include <algorithm>
#include <array>
#include <vector>
#include <list>

template <class Container>
void rotate(Container& container, int n)
{
    using std::begin;
    using std::end;

    auto new_begin = begin(container);
    std::advance(new_begin, n);

    std::rotate(
        begin(container),
        new_begin,
        end(container)
    );    
}

int main()
{
    std::array<int, 5> array = { 1, 2, 3, 4, 5 };
    rotate(array, 1);

    std::vector<int> vector = { 1, 2, 3, 4, 5 };
    rotate(vector, 3);

    std::list<int> list = { 1, 2, 3, 4, 5 };
    rotate(list, 2);

    int raw_array[] = { 1, 2, 3, 4, 5 };
    rotate(raw_array, 3);

    // test output goes here...
}

请注意std::beginstd::end如何确保原始数组(使用 begin + N 语法)和容器类(使用 c.begin())两者都支持+ N 语法),std::advance使函数适用于具有非随机访问迭代器的容器,如std::list(必须重复递增迭代器以使其超过一个元素)。

顺便说一句,如果你想支持大于或等于容器大小的n个参数,那么你可以使用C ++ 17函数std::size或者只是创建你的拥有。也许使用assert来捕捉意外的否定论点:

assert(n >= 0);
using std::size;
n = n % size(container);