数组元素循环右移问题实验 数据结构

一个数组A中存有N(N>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(M≥0)个位置,即将A中的数据由(A0A1…AN-1)变换为(AN-M…AN-1A0A1…AN-M-1)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法

要求

1、输入说明:第1行输入N(1≤N≤100)、M(M≥0);第2行输入N个整数。

2、输出说明:输出循环右移M位以后的整数序列。

3、测试用例:

序号

输入

输出

说明

1

6 2
1 2 3 4 5 6

5 6 1 2 3 4

一般情况

2

6 8

1 2 3 4 5 6

5 6 1 2 3 4

M>N的情况

3

3 6

11 23 56

11 23 56

M>N且正好是N的倍数

4

1 0
8

8

边界测试,最小的N和M

5

令N为100,M为99

输入数据略

边界测试,最大的N和M

四、实验分析

1、问题分析

输入的N个整数可以放在一个一维数组中。最容易想到的,也是简单的思路是循环右移一位的操作重复进行M次即可,但这种做法的数据移动次数大约是M*N次。下面“方法一”实验参考代码实现了这种简单思想。

为了减少数据的移动次数,第二种方法是通过三次倒序来巧妙地实现。为简单起见,不妨设0≤M<N(否则先进行M%=N运算即可),先把(A0A1…AN-1)倒序变成(AN-1AN-2…A1A0),再把它的前M个元素(AN-1AN-2…AN-M)倒序成(AN-M…AN-1),然后把N-M个元素(AN-M-1AN-M-2…A1A0)倒序成(A0A1…AN-M-1)。这样,整个数组就成了(AN-M…AN-1 A0A1…AN-M-1),这就是我们想要的结果。这种做法每个数据参与2次交换(倒序),所以如果一对数的交换需要3次数据移动的话,总共数据移动次数大约是3N次。下面“方法二”实验参考代码实现了这种思想。

事实上,还可以有移动次数更少的算法,实验思考题中给出了提示。

2、实现要点

M可以处理成小于N的数,以减少移动次数。当M>N时,可以用M%N代替M,效果相同,但在方法一情况下移动次数大约是(M%N)*(N+1)次。

方法一:采用循环控制结构。该方法比较简单,只需要“循环右移一位的操作重复进行M次”,先定义一个函数进行“每个元素循环右移一位的操作”,然后这个函数被重复调用M次。

方法二:采用用异或运算交换数据。该方法比较巧妙,通过三次逆转数组的部分数据就可以实现。程序中定义了一个带参数的宏Swap(a,b),用连续三次异或运算交换a与b。当然读者也可以通过引入中间变量,通过三次赋值运算实现两个数据的交换。

#include <stdio.h>

#define MAXN 100

void Shift(int Array[ ],int N);

int main( )

{

  int Number[MAXN],N,M;

  int i;

  scanf("%d%d",&N,&M);

  for(i=0;i<N;i++)

scanf("%d",&Number[i]);

  M%=N; /*当M大于等于N时转化成等价的小于N的数*/

  for(i=0;i<M;i++)

Shift(Number,N );         /*N个元素循环位移1位*/

  for(i=0;i<N-1;i++)          /*打印输出*/

printf("%d", Number[i]);

printf("%d\n", Number[N-1]);

  return 0;

}

void Shift(int Array[ ],int N)

{

  int i ,ArrayEnd;

  ArrayEnd=Array[N-1];

  for (i=N-1;i>0;i--)            /*N个元素循环位移1位*/

    Array[i]=Array[i-1];

  Array[0]= ArrayEnd;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值