如何将动态数组向右旋转?

时间:2018-03-20 02:32:55

标签: c++

我有一个自定义数组对象。它有两个主要变量:

m_array =指向动态数组的指针。

m_size - 数组的大小。此数组的大小为10。

当我向左旋转时,这很好用:

 std::rotate(m_array + 0, m_array + 1, m_array + m_size);

这相当于:

// simple rotation to the left
std::rotate(v.begin(), v.begin() + 1, v.end());

当我尝试向右旋转时,我遇到了运行时错误。

我需要相当于这个:

// simple rotation to the right
std::rotate(v.rbegin(), v.rbegin() + 1, v.rend());

我试过了:

std::rotate(m_array + m_size, m_array + m_size + 1, m_array + 0);

我收到错误:迭代器范围无效

所以,我认为这是m_size,所以我尝试了这个:

std::rotate(m_array + m_size - 1, m_array + (m_size - 1) + 1, m_array + 0);

我得到同样的错误。

欢迎思考。

我试图遵循的来源: http://en.cppreference.com/w/cpp/algorithm/rotate

2 个答案:

答案 0 :(得分:4)

要进行正确的旋转(借用你的短语),你希望范围是但是数组中的最后一个元素。我将留给您调整此代码以适应可变大小的数组。

#include <algorithm>
#include <iostream>

int main() {
    int data[10] = { 0, 1, 2, 3, 4,
                     5, 6, 7, 8, 9 };
    auto print_all = [&data]() {
        for(auto v: data) {
            std::cout << v << ' ';
        }
        std::cout << '\n';
    };
    print_all();

    // rotate elements to the left
    std::rotate(data, data + 1, data + 10);
    print_all();

    // rotate element to the right, back to the original position
    std::rotate(data, data + 9, data + 10);
    print_all();
    return 0;
}

我的输出如下:

./rotate 
0 1 2 3 4 5 6 7 8 9 
1 2 3 4 5 6 7 8 9 0 
0 1 2 3 4 5 6 7 8 9 

答案 1 :(得分:4)

std::rotate(v.rbegin(), v.rbegin() + 1, v.rend())的作用原因是它使用了反向迭代器。这意味着v.rbegin() + 1实际上是递减数组中的位置并且等于v.begin() + v.size() - 1

使用原始指针算法时,无法获得相同的反向迭代行为。您必须手动将左旋转转换为右旋转。这可以通过翻转围绕阵列中心的旋转位置并执行左旋转来轻松完成。

向左或向右旋转可以归结为将阵列分成2个部分然后交换它们。无论是左旋还是右旋,都决定了划分的位置。对于左侧k的旋转,旋转点位于k mod N。对于右旋转,旋转点位于-k mod N,其中N是阵列的总长度。这将选择您希望位于新旋转数组的索引0的原始数组中的索引。

所以以下右边旋转1,

std::rotate(v.rbegin(), v.rbegin() + 1, v.rend())

等同于以下列方式使用原始指针:

int* p = &v[0];
int n = v.size();
int k = -1;
std::rotate(p, p + mod(k, n), p + n);

其中mod()是模运算(基本上是总是包含正数的%运算符):

int mod(int x, int y) { return ((x % y) + y) % y; }