编程珠矶学习笔记(2)--移位旋转

个人原创,转载请注明出处,谢谢!

一、代码

#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;

  

 

/*

*计算最大公约数函数

*ij的最大公约数,比如53的最大公约数为186的最大

*公约数是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;

}

 

附图:

 

第一轮移位

 

第3轮移动

最终结果

即实现了从:abc defg =>defg abc

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值