一、问题描述:约瑟夫问题
一个旅行社要从n个旅客中选出一名旅客,为他提供免费的环球旅行服务。旅行社安排这些旅客围成一个圆圈,从帽子中取出一张纸条,用上面写的正整数m(<n)作为报数值。游戏进行时,从第s个人开始按顺时针方向自1开始顺序报数,报到m时停止报数,报m的人被淘汰出列,然后从他顺时针方向上的下一个人开始重新报数,如此下去,直到圆圈中只剩下一个人,这个最后的幸存者就是游戏的胜利者,将得到免费旅行的奖励。
二、任务要求
(1)用单循环链表解决约瑟夫问题。
(2)用顺序表解决约瑟夫问题。
以上二选一
三、测试数据
输入说明,输入的第一行表示总的旅客数,输入的第二行表示报数值,输入的第三行表示报数人的起始编号。
输入样例:
9
5
1
输出说明,输出这n个人的淘汰顺序
输出样例:
5
1
7
4
3
6
9
2
8
1. 分析问题:
(1)假设有9名旅客,编号为1,2,……,9。从编号为1的这个人开始从1报数,当报到5时的那个人淘汰,接着接下来的那个人开始又从1开始报数,直到最后只剩一个人。
(2)顺序表的存储结构
#define N 100//顺序表可能达到的最大长度
typedef struct{
int data[N];
int length;
}List;
2. 完整代码:
#include <stdio.h>
#include <stdlib.h>
#define N 100//宏定义,顺序表可能达到的最大长度
typedef struct{//定义一个结构体
int data[N];
int length;//当前长度
}List;//结构体类型为List
int printlist(List *l)//构建一个顺序表l
{
int i,m,n,s,j;
scanf("%d%d%d",&n,&m,&s);
for(i=0;i<n;i++)
{
l->data[i]=i+1;//将旅客进行编号
}
i=s-1;
printf("输出%d个人的淘汰顺序:\n");
while(n>1)
{
i=(i+m-1)%n;//通过模运算算出将要淘汰的下标
printf("%d\n",l->data[i]);//输出淘汰的编号
for(j=i+1;j<n;j++)
{
l->data[j-1] = l->data[j];//将后一个数放在淘汰的数对应的位置
}
n--;
if(i==n)
i=0;
}
printf("%d\n",l->data[i]);//输出最后一个淘汰的编号
}
int main()
{
List l;//初始化顺序表l
printlist(&l);//调用函数
}