数组元素循环右移问题

来源:互联网 发布:程序员常去的网站 编辑:程序博客网 时间:2024/06/05 05:32

一、 实验目的

  (1)熟练使用循环语句。

  (2)熟练理解和掌握顺序存储与数据处理算法的关系。

二、 实验内容

一个数组A中存有NN>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

  说明:

  边界测试,最小的NM

  [5]

  输入:

  100 99

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

输出:

  2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 1

  说明:

  边界测试,最大的NM

四、 实验数据记录

一般情况:

 

M>N情况:

 

M>NMN的倍数:

 

边界测试最小N,M:

 

边界测试 最大N,M(利用file操作读入1~100个数):

 

五、 实验结果分析

#include<stdio.h>

#include<malloc.h>

#include<stdlib.h>

#include<conio.h>

#define MAXSIZE 100

typedef struct{

int data[MAXSIZE];

int last;

}list;

list *L;

int N,M;

list *Create()

{

int temp,j=0;

L = (list *)malloc(sizeof(list));

L -> last = -1;

printf("输入N 和M :\n");

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

printf("输入数据:\n");

for(int j=0;j<N;j++)

{

scanf("%d",&temp);

L->data[j] = temp;

L->last++;

}

return L;

}

//这个函数用于最后输入1~100个数字,采用file操作

/*

*// 从文件中读入数据存到L.dara[]中

* printf("利用file操作从data.dat文件中读入1~100:\n");

* FILE *file = NULL;

* if((file=fopen("data.dat","r")) == NULL)

* {

* printf("Can not open the file!\n");

* exit(0);

* }else{

* for(int n=0;n<N;n++)

* {

* fscanf(file,"%d",&temp);

* L->data[n] = temp;

* }

* }

*/

void sort(list *L,int n,int m)   // 对数组进行m次或者m%n次的排序

{

int temp;

for(int i=0;i<m;i++)

{

temp = L->data[n-1];//将最后一个数赋值给temp

for(int j=n-2;j>=0;j--)

{

L->data[j+1] = L->data[j]; //节点后移

}

L->data[0] = temp; //将最后一个值放到第一个位置

}

}

int check(list *L)

{

if((L->last) >= N)

{

printf("over flow\n");

return 0;

}

if((N<=100) && (M<=100))

{

if(N > M) //一般情况n>m  进一步划分当m>n/2时候可以倒置

{

sort(L,N,M);

return 1;

}

else if(N == M)    //相等

{

return 1;

}

else //M > N情况

{

int m = M % N; //进行取余

sort(L,N,m);

return 1;

}

}

return 0;

}

void output(list *L)//输出结果

{

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

{

printf("%d\t",L->data[i]);

}

printf("\n");

}

int main()    // 主函数

{

L = Create();

if(check(L) == 1)

{

output(L);

}else{

printf("error!");

}

system("pause");

return 0;

}

    对于移动操作函数可以进一步优化,即当N/2 < M < N时候,可以改变数组移动的方向,原来是节点后移,可以改成节点前移,次数为N-M次。

六、 回答问题

  实验思考题:

  (1)如果修改题目要求,允许使用另外一个大小为M(假设N>M>0)的数组,则如何提高程序效率?

答:先将数组的最后M个元素放入temp[M]中,然后对剩余的每一个元素移动M个位置,L->data[N-1] = L->data[N-M-1].

  (2)不改动题目的任何限定,能否设计一个移动次数不超过2M的方法?

答:用MN取余数,temp = M%N,然后分析temp

    0 < temp < N/2 :节点后移;

    N/2 < temp <N :节点前移N - temp次数;

0 0
原创粉丝点击