2016-11-26 56 views
-2

有一种不使用任何循环象下面这只是通过操纵列表索引移阵列元件,而不循环

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] 
+3

['标准::旋转()'](http://en.cppreference.com/w/cpp/algorithm/rotate) –

回答

0

C++标准将这个列表的元素Python代码转移在C++中的数组元素算法也适用于阵列,因此您可以使用std::rotatestd::rotate_copy。但是,函数的接口比Python示例中的旋转稍微复杂一点。您必须提供一个迭代器作为第二个参数,该元素将成为结果数组中的第一个元素

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

#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确保原始阵列(他们开始+ N语法)和容器类(其c.begin()+ N语法)均受支持,并且std::advance使该函数对于具有非随机访问迭代器(如std::list)的容器有效(其中您必须将迭代器重复递增为通过多个元素推进它们)。


顺便说一句,如果你想支持大于或等于容器的大小n参数,那么你可以使用C++ 17功能std::size或刚刚创建自己的。也许使用assert赶上意外负参数:

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