个人原创,转载请注明出处,谢谢!
一、代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAXN 10000000
int x[MAXN];
int rotdist, n;
int gcd(int i, int j)
{ int t;
while (i != 0) {
if (j >= i)
j -= i;
else {
t = i; i = j; j = t;
}
}
return j;
}
void jugglerot(int rotdist, int n)
{
int cycles, i, j, k, t;
cycles = gcd(rotdist, n);
for (i = 0; i < cycles; i++) {
/* move i-th values of blocks */
t = x[i];
j = i;
for (;;) {
/*利用取余操作,使移动过程调头,这里是难点,见后面的示意图*/
/*等价于k = (j + rotdist ) % n*/
k = j + rotdist;
if (k >= n)
k -= n;
if (k == i)
break;
x[j] = x[k];
j = k;
}
x[j] = t;
}
}
void initx()
{
int i;
for (i = 0; i < n; i++)
x[i] = i;
}
void printx()
{ int i;
for (i = 0; i < n; i++)
printf(" %d", x[i]);
printf("/n");
}
int main(void)
{
while (scanf("%d %d ", &n, &rotdist) != EOF) {
initx();
jugglerot(rotdist, n);
printx();
}
return 0;
}
二、代码注解
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAXN 10000000
int x[MAXN];
int rotdist, n;
/*
*计算最大公约数函数
*求i和j的最大公约数,比如5和3的最大公约数为1,8和6的最大
*公约数是2。
*/
int gcd (int i, int j)
{ int t;
while (i != 0) {
if (j >= i)
j -= i;
else {
t = i; i = j; j = t;
}
}
return j;
}
/*
移位方式实现旋转: abcdefg => defgabc
就像坐在一列凳子上的人(abcdefg),我们要求坐在最前面的三个人(abc)坐到最后面去,其他人依次往前坐三个位子(defg_ _ _),腾出最后的三个位子,然后原来前面的三个人坐进去(defg abc)即可。
本算法的结果和上面的结果类似,但实现过程有所不同,难点在于我们并不知道每次要转移几个元素(rotdist是个变量),所以我们不可能先申请另一个固定的数组去临时装载要移动的元素(当然如果内存足够的大也可以,但这不在本例研究的范畴内),要使用一个临时变量来实现多元素的移动是本例的难点,也是亮点
* input: n, rotdist, x[] = {a,b,c,d,e,f}(示例)
* output: x[]
* constrain: {a,b,c,d,e,f } è {d,e,f,a,b,c}, 使用尽可能少的额外内存
*/
void jugglerot (int rotdist, int n)
{
int cycles, i, j, k, t;
/*对于有公约数的现象,一轮可能并不能移完,比如abcdef, 要将ab移动到cdef的后面,则需要两轮,第一轮移动a以及与之相关的c,c,第二轮移动b以及与之相关的d,f,所以使用最大公约数方法计算需要移动几轮
*/
cycles = gcd(rotdist, n);
for (i = 0; i < cycles; i++) {
/* move i-th values of blocks */
t = x[i];
j = i;
for ( ; ; ) {
k = j + rotdist;
if (k >= n)
k -= n;
if (k == i)
break;
x[j] = x[k];
j = k;
}
x[j] = t;
}
}
/*
* 初始化前n个元素
*/
void initx()
{
int i;
for (i = 0; i < n; i++)
x[i] = i;
}
/*
*打印前n个元素
*/
void printx()
{ int i;
for (i = 0; i < n; i++)
printf(" %d", x[i]);
printf("/n");
}
int main(void)
{
while (scanf("%d %d ", &n, &rotdist) != EOF) {
initx();
printx();/*打印出旋转前的各元素*/
jugglerot(rotdist, n);
printx();/*打印出旋转后的各元素*/
}
return 0;
}
附图:
即实现了从:abc defg =>defg abc