其实我之前写过约瑟夫环的问题,当时还不是特别会。
现在的约瑟夫环是升级版的。
【问题描述】
约瑟夫环问题的描述是:编号为 1,2,…,n 的 n 个人按顺时针方向围坐一
圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限 m,从第
一个人开始按顺时针方向自 1 开始顺序报数,报到 m 时停止报数。报 m 的人出
列,将他的密码作为一个新的 m 值,从他在顺时针方向上的下一个人开始重新从
1 报数,如此下去,直至所有人全部出列为止。请设计一个程序求出列顺序。
【基本要求】
利用单向循环链表存储结构模拟此过程,按照出列顺序打印出各人的编号。
【测试数据】
(1)输入:m 的初值为 20;
n=7; 7 个人的密码依次为 3,1,7,2,4,8,4。
输出:正确的出列顺序为 6,1,4,7,2,3,5。
(2)输入:m 的初值为 20;
n=7;
密码输入依次为 3,1,7,2,4,8。
输出:密码输入有误,请重新输入密码:
密码输入依次为 3,1,7,2,4,8,4 时,
正确的出列顺序为 6,1,4,7,2,3,5。
代码实现:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
#define OK 1
#define FALSE 0
#define ERROR 0
typedef int Status;
typedef int ElemType;
typedef struct YUE
{
ElemType data;
ElemType loa;
struct YUE *next;
}LNode,*LinkList;
Status Create(LinkList &L)//创建
{
L=(LinkList)malloc(sizeof(LNode));
if(!L)
{
printf("申请空间错误!\n");
return ERROR;
}
printf("申请空间成功!\n");
L->next=L;
return OK;
}
LinkList GetElem(LinkList L,int i)
{
LNode *p;
p=L;
int j;
for(j=0;j<i;j++)
{
p=p->next;
}
return p;
}
Status Length(LinkList L)
{
LNode *p;
p=L;
int i=1;
while(p->next!=L)
{
p=p->next;
++i;
}
return i;
}
Status Insert(LinkList &L,int i,ElemType e)
{
if(i<1||i>Length(L)+1)
{
printf("插入位置错误!\n");
return ERROR;
}
if(i==1)
{
L->data=e;
L->loa=i;
L->next=L;
return OK;
}
LNode *p=GetElem(L,i-2);
LNode *s;
s=(LinkList)malloc(sizeof(LNode));
s->loa=i;
s->data=e;
s->next=p->next;
p->next=s;
return OK;
}
Status Ling(LinkList L)
{
int i;
int count=Length(L);
LNode *p=L;
for(i=0;i<Length(L);i++)
{
if(p->data==0)
{
count--;
}
p=p->next;
}
return count;
}
Status Play(LinkList &L,int m)
{
int i;
LNode *p=L;
LNode *q;
LNode *tail;
while(p!=p->next)
{
for(i=1;i<m;i++)
{
tail=p;
p=p->next;
}
printf("%d->",p->loa);
m=p->data;
tail->next=p->next;
q=p;
p=p->next;
free(q);
}
printf("%d",p->loa);
return OK;
}
Status shuchu(LinkList L)
{
LNode *p=L;
int i;
for(i=0;i<Length(L)+1;i++)
{
printf("%d号密码是%d\n",p->loa,p->data);
p=p->next;
}
return OK;
}
Status Clear(LinkList L)
{
LNode *p,*q;
p=L->next;
while(p!=L)
{
q=p->next;
free(p);
p=q;
}
p->next=L;
return OK;
}
int main()
{
LinkList L;
Create(L);
int m;
printf("输入m的初值:\n");
scanf("%d",&m);
getchar();
printf("m的初值是%d\n",m);
int n;
printf("输入人数:\n");
scanf("%d",&n);
getchar();
int i;
ElemType e;
char ch;
int flag;
while(1)
{
flag=0;
printf("输入%d个人的密码:\n",n);
int j;
for(i=1;i<=2*n-1;i++)
{
scanf("%c",&ch);
if(ch=='\n'&&i<2*n-1)
{
flag=1;
break;
}
if(ch<='9'&&ch>='0')
{
j=(i+1)/2;
e=ch-'0';
Insert(L,j,e);
}
}
if(flag==1)
{
printf("密码输入有误,请重新输入密码:\n");
Clear(L);
}
else
{
break;
}
}
printf("%d个人的密码依次是:\n",n);
shuchu(L);
printf("正确的出列顺序为:");
Play(L,m);
return 0;
}