在C++编程中,数组旋转指的是将数组中的元素按照指定方向循环移动若干位,比如将数组[1,2,3,4,5]左旋2位后得到[3,4,5,1,2],右旋2位后得到[4,5,1,2,3]。使用指针操作数组可以直接访问内存地址,减少不必要的元素拷贝,提升操作效率。

数组旋转的核心思路
要实现数组旋转,核心是先确定旋转的方向和步数,然后通过指针遍历数组完成元素的位置调整。常见的实现方式有两种,一种是借助临时数组存储需要移动的元素,另一种是通过反转数组的方式实现原地旋转,后者不需要额外开辟大量内存空间,更适合对内存占用有要求的场景。
左旋数组的指针实现
左旋k位指的是将数组前k个元素移动到数组末尾。我们可以通过三次反转的方式实现:先反转前k个元素,再反转剩余的元素,最后反转整个数组。使用指针操作反转逻辑时,只需要通过指针交换对应位置的元素即可。
下面是左旋数组的完整实现代码:
#include <iostream>
using namespace std;
// 反转数组中指定区间的元素,使用指针操作
void reverse(int* start, int* end) {
while (start < end) {
// 交换两个指针指向的元素
int temp = *start;
*start = *end;
*end = temp;
// 指针向中间移动
start++;
end--;
}
}
// 左旋数组k位
void rotateLeft(int* arr, int n, int k) {
// 处理k大于数组长度的情况,取模避免无效旋转
k = k % n;
if (k == 0) {
return;
}
// 反转前k个元素
reverse(arr, arr + k - 1);
// 反转剩余n-k个元素
reverse(arr + k, arr + n - 1);
// 反转整个数组
reverse(arr, arr + n - 1);
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
int n = sizeof(arr) / sizeof(arr[0]);
int k = 2;
// 调用左旋函数
rotateLeft(arr, n, k);
cout << "左旋" << k << "位后的数组:";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
右旋数组的指针实现
右旋k位相当于左旋n-k位,因此我们可以复用左旋的逻辑,只需要调整传入的旋转步数即可。当然也可以直接按照右旋的逻辑实现三次反转:先反转整个数组,再反转前k个元素,最后反转剩余的元素。
下面是右旋数组的实现代码:
#include <iostream>
using namespace std;
// 反转数组区间元素的函数,和左旋复用
void reverse(int* start, int* end) {
while (start < end) {
int temp = *start;
*start = *end;
*end = temp;
start++;
end--;
}
}
// 右旋数组k位
void rotateRight(int* arr, int n, int k) {
k = k % n;
if (k == 0) {
return;
}
// 反转整个数组
reverse(arr, arr + n - 1);
// 反转前k个元素
reverse(arr, arr + k - 1);
// 反转剩余n-k个元素
reverse(arr + k, arr + n - 1);
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
int n = sizeof(arr) / sizeof(arr[0]);
int k = 2;
rotateRight(arr, n, k);
cout << "右旋" << k << "位后的数组:";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
注意事项
- 使用指针操作数组时,要确保指针的访问范围不超过数组的边界,避免出现野指针访问导致的程序崩溃。
- 旋转步数k可能大于数组长度,需要先对k取模,避免无效的重复旋转操作。
- 如果数组元素数量较少,也可以直接通过指针遍历拷贝元素到临时数组,再拷贝回原数组,不过这种方式会额外占用O(n)的内存空间。
通过上述方法,我们可以灵活使用指针实现数组的左旋和右旋操作,理解指针操作数组的逻辑后,也可以根据实际需求调整旋转的实现方式,适配不同的业务场景。