约瑟夫(Joseph)问题
[问题描述]
约瑟夫(Joseph)问题的一种描述是:编号为 1,2,…,n 的 n 个人按顺时针方向围坐一圈,每人持有一个密码(正整数),一开始任选一个整数作为报数上限 m,从第一人开始按顺时针方向从自 1 开始顺序报数,报到 m 时停止报数。报 m 的人出列,将他的密码作为新的 m 值,从他的顺时针方向上的下一个人开始重新从 1 报数,如此下去,直至所有人全部出列为止,设计一个程序求出出列顺序。
[基本要求]
采用单向循环链表模拟此过程,按照出列的顺序印出各人的编号
[测试数据]
m 的初值为 6;n=7,7 个人的密码依次为:3,1,7,2,4,8,4,正确的出列顺序应为 6,1,4,7,2,3,5。
[实验提示]
单向循环链表的结点类型定义参照如下:
typedef struct LNode
{
int code; //定义整型变量 code 用来存放序号
int key; //定义整型变量 key 用来存放密码
struct LNode *next;
}LNode,*LinkList;
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode
{
int code;//存放序号
int key;//存放密码
struct LNode *next;
}LNode,*LinkList;
void CreatList(LinkList &L,int i)//建立有i个元素的单向循环链表
{
LinkList p,s;
int j;
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL;
p=L;
if(i!=0)
printf("请按提示输入数据元素\n\n");
for(j=0;j<i;j++)
{
s=(LinkList)malloc(sizeof(LNode));
s->code=j+1;
printf("请输入第%d个的密码: ",j+1);
scanf("%d",&s->key);
p->next=s;
p=s;
}
p->next=L->next;
}
void ListDelete(LinkList &L,int i,int &e)//删除链表L中第i个元素
{
LinkList p;
int j;
for(j=0; L && j<i-1;j++)
{
L=L->next;
}
p=L->next;
e=p->key;
L->next=p->next;
printf("出列人的序号为%d,密码为%d\n",p->code,p->key);
free(p);
}
int main()
{
LinkList L;
int m,n,code;
CreatList(L,0);
printf("请输入总人数n:\n");
scanf("%d",&n);
printf("请输入报数上限m:\n");
scanf("%d",&m);
CreatList(L,n);
code=0;
while(L)
{
ListDelete(L,m,code);
m=code;
}
return 0;
}