【问题标题】:Shift array elements in C++ without loop在没有循环的 C++ 中移动数组元素
【发布时间】:2016-11-26 10:48:36
【问题描述】:

有没有一种方法可以在 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]

【问题讨论】:

标签: python c++ arrays list


【解决方案1】:

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 如何确保原始数组(使用它们的 begin + N 语法)和容器类(使用它们的 c.begin() + N em> 语法)都受支持,并且std::advance 使该函数适用于具有非随机访问迭代器的容器,例如std::list(您必须重复递增迭代器以将它们推进多个元素)。


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

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

【讨论】:

    猜你喜欢
    • 2012-08-25
    • 2020-09-22
    • 1970-01-01
    • 2023-03-14
    • 2017-02-28
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多