1.问题描述
约瑟夫(Joseph)问题的一种描述是:设编号为1,2,…,n的n(n>0)个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。开始时任选一个整数作为报数上限值m,从一个人开始顺时针自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止。要求设计一个程序模拟此过程,求出出列顺序。
2.设计要求
设计一个程序,以人机交互方式执行,用户指定约瑟夫环游戏的总人数n和初始的报数上限m,然后输入每个人所持有的密码key。模拟约瑟夫环,从头开始报数,直到所有的人出列。系统按照出列顺序给出编号。
3.代码实现
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct Node
{
/*密码,编号,指向下一结点的指针*/
int pwd;
int num;
struct Node *next;
}Node,*LinkList;
//创建一个新的链表
LinkList CreateList(int n,Node *L)
{
LinkList p,s;
int i;
s=L;
//依次创造结点,并输入密码
for(i=1;i<=n;i++)
{
p=(Node*)malloc(sizeof(Node));
p->num=i;
printf("输出第%d个人的密码:",i);
scanf("%d",&p->pwd);
s->next=p;
s=p;
}
L=L->next;
s->next=L;
//返回一个创建好了的单循环链表
return L;
}
//输出信息 ,m是初始密码,n是总人数
void PrintList(int m,int n,Node* L)
{
LinkList p;
//x来保存新的密码
int x,i;
p=L;
printf("\n输出顺序(编号,密码):");
//找到第一个要出局的人
for(i=1;i<m;i++)
p=p->next;
while(n)
{
x=p->next->pwd;//此时密码更新了
//输出编号和所持有的密码
printf("%d(%d) ",p->next->num,x);
//出局
p->next=p->next->next;
for(i=1;i<x;i++)
p=p->next;
n--;
}
}
int main()
{
Node L;
int m,n;
printf("输出总人数:");
scanf("%d",&n);
printf("输入起始密码:");
scanf("%d",&m);
//调用函数,进行输出
CreateList(n,&L);
PrintList(m,n,&L);
}