定义一个数组 int a[10]={1,2,3,4,5,6,7,8,9,10};若将它循环右移两次,结果为{9,10,1,2,3,4,5,6,7,8},若将其循环右移12次,结果也为{9,10,1,2,3,4,5,6,7,8},所以移动数组,要考虑一个重要的因素就是移动次数需取余(%)数组长度来避免移动次数过多。
方法一代码如下:
#include<stdio.h>
#define N 10
//n代表元素个数,k代表移动次数,right代表最后一个元素的下标,如果有十个元素,则right值为9
void remove(int a[], int left, int right, int n, int k)
{
//right-left+1代表元素个数,相当于n
k %= (right - left + 1);
//总体思路是不断将最后一个元素保存,右移其它元素,再将最后一个元素放到第一个元素的位置。将上述过程重复k次。
while (k-- != 0)
{
int t = a[right];
for (int j = right; j > left; j--)
{
a[j] = a[j - 1];
}
a[left] = t;
}
}
void print(int a[], int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
int main()
{
int a[N] = { 1,2,3,4,5,6,7,8,9,10 };
printf("旋转前:\n");
print(a, N);
remove(a, 0, 9, N, 15);
printf("旋转15次后:\n");
print(a, N);
return 0;
}
上述代码结果运行如下图:
方法二:
假如将数组循环右移三次,先整体逆置,再将所有数划分为两部分,第一部分为三个数,其余数组成第二部分,然后将两部分分别逆置。
例如int a[10]={1,2,3,4,5,6,7,8,9,10}。右移三次,第一步,先将数组逆置,得到{10,9,8,7,6,5,4,3,2,1},然后将前三个元素以及后七个元素分别逆置得到{8,9,10,1,2,3,4,5,6,7},即也为最终结果。
代码如下:
#include<stdio.h>
#define N 10
//转置所有元素,right代表最后一个元素的下标
void ReverseArray(int ar[], int left, int right)
{
int low = left;
int high = right ;
while (low < high)
{
int tmp = ar[low];
ar[low] = ar[high];
ar[high] = tmp;
low++;
high--;
}
}
//旋转数组
void RotateArray(int ar[], int left, int right, int k)
{
int n = right - left+1;
k %= n;
ReverseArray(ar, left, right); //整体逆置
ReverseArray(ar, left, k-1); //逆置左部分,下标为0,1,2的元素。
ReverseArray(ar, left + k, right); //逆置右部分,下标从3到9的元素。
}
//打印数组
void print(int a[], int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
int main()
{
int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("移动前:\n");
print(a, N);
RotateArray(a, 0, 9, 13);
printf("旋转13次后:\n");
print(a, N);
return 0;
}
代码运行结果如下图: