您的位置:首页 > 其它

约瑟夫环

2016-03-12 10:09 169 查看

要求:约瑟夫环的一种描述为:序号为1,2,...,n的n个人按顺时针方向围坐一圈,每个人持有一个密码(正整数),开始时任选一个数作为报数上限m,从第一个人开始顺时针自1开始顺序报数,报到m时停止报数,报的m的人出列,将他的密码作为新的m值,从他开始在顺时针方向的下一个人开始重新从1报数,如此下去,直至所有人全部出列,请设计一个程序,求出出列顺序。

如:当m的初始值为20,n=7,7个人的密码依次为:3,1,7,2,4,8,4,出列的顺序为6,1,4,7,2,3,5.

思路:因为n个人围坐一圈,所以可以很自然的想到用单向循环链表作为存储结构来模拟此过程,然后按一定的条件删除某个结点,将该结点打印出来。

基于此思路代码如下:
# include<stdio.h>
# include<stdlib.h>
# include<windows.h>
typedef struct people
{
int order;
int password;
int nextorder;
struct people * pnext;
}p,*linklist;
void main()
{
int n,m;
printf("请输入人的个数n\n");
scanf("%d",&n);
int count =0;
int i=1;
linklist phead=(linklist)malloc(sizeof(p));
linklist ptail=phead;
while(count!=n)//构建约瑟夫环
{

linklist pnew=(linklist)malloc(sizeof(p));
pnew->order=i;
pnew->nextorder=i;
printf("请输入该人的密码\n");
scanf("%d",&pnew->password);
ptail->pnext=pnew;
pnew->pnext=NULL;
ptail=pnew;
i++;
count++;
}
ptail->pnext=phead;
printf("请输入报数上限值m\n");
scanf("%d",&m);
linklist ptemp=phead;
linklist pre;
//	linklist ptemp=phead->pnext;
int k=0;
while(ptemp->pnext!=ptemp)//模拟出列过程
{
pre=ptemp;
ptemp=ptemp->pnext;
if(ptemp==phead)
{
pre=ptemp;
ptemp=ptemp->pnext;
}
k++;
if(k==m)
{
printf("%d ",ptemp->order);
m=ptemp->password;
pre->pnext=ptemp->pnext;
//linklist p=ptemp;
free(ptemp);
//ptemp=pre->pnext;不能这样写,因为头结点phead中无数据,如果是最后一个元素删除了则加1后ptemp到了phead,
//k=1;			   而phead中无数据所以多算了一步
ptemp=pre;
k=0;
}

}
}
程序运行结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: