题目一:278.约瑟夫环
上机报告
题目:编写一个和约瑟夫环相关的程序
一、需求分析
1.本演示程序中,需要完成的输入输出全部为整型数,随机数m>0,要求输入第一行为人的个数及初始密码,第二行表示每个人的密码。输出也为一串整型数。编写此题并不需要构建新的数据类型。
2.程序运行只需要在编译器或者cmd界面按照要求输入即可得到输出。
3.程序的命令包括:
1)n,m的输入 2)表示人初始编号的数组a[]的输入 3)按照循环依次输出每次出圈的密码 4)return 0 结束
4.测试数据
(1)输入:
7 20
3 1 7 2 4 8 4
输出:6 1 4 7 2 3 5
二、概要设计
为实现上述程序功能,我们用数组表示所有人的初始编号。
1.所有人的初始编号设为a[100],题目中没有给出最大限制人数,因此我们先开一个大一些的数组。
2.本程序比较简单,只有主程序一个模块。
int main()
{
//初始化数据设置
scanf("%d %d",&n,&m);
scanf("%d ",&a[i]); //两个输入语句
while()
{
//循环语句
}
return 0;
}
三、详细设计
1.初始数据设置
int a[100]; //表示所有人持有的密码
int n,m; //n,m表示人的个数和初始密码数
int i; //循环数
int number; //当前报的号,用于和每个人的密码相比较
int x; //记录初始人数
2.核心循环语句(解析在代码段中)
while(x>0) //循环语句的判断条件:圈中还有人
{
for(i=1;i<=n;i++)
{
if(a[i]!=0)
{
number++; //循环到的人编号不为0,给报号加1
}
if(number == m)
{
m = a[i]; //储存当前人的密码,用于下一次循环
a[i] = 0; //将报到的人编号置0
number = 0; //将计数清0
x--; //圈中人报到一个就减少一个
printf("%d ",i); //输出当前人的密码号
}
}
}
3.完整的代码展示:
#include <stdio.h>
int main()
{
int a[100],n,m,i,number,x;
number = 0;
scanf("%d %d",&n,&m);
x = n;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
while(x>0)
{
for(i=1;i<=n;i++)
{
if(a[i]!=0)
{
number++;
}
if(number == m)
{
m = a[i];
a[i] = 0;
number = 0;
x--;
printf("%d ",i);
}
}
}
return 0;
}
四、调试分析
1.本题和部分约瑟夫环不同,需要在每次人出圈后更改下一次出圈的密码,一开始我没注意到这点,按照惯性思维,导致错误,好在及时发现,但是前面几次没有将m = a[i]放到正确的位置,导致只有一个输出程序就停止,纠正后完成程序编写。
2.本题比较容易,没有过多的数据结构的单独编写,使用数组很快的解决了此题,如果使用链表则需要额外编写结构定义。
3.算法的时空分析
1)两条输入语句时间复杂度分别为O(1),O(n),循环while语句中嵌套了for循环,时间复杂度为O(n^2)。
五、用户手册
1.打开程序运行,根据要求输入,按Enter得到输出结果。
六、测试结果
七、附录
源程序文件名清单:
278约瑟夫环.cpp