约瑟夫问题
一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
typedef struct list
{
int num; //num表示序号
int passward; //passward表示手中的密码
struct list *next;
}node;
node *creatlist()
{
node *p,*q,*head; //定义结点
int i=1,n;
printf("请输入人数(n):");
scanf("%d",&n);
head=(node *)malloc(sizeof(node)); //创建一个带头结点的链表
head->num=i;
printf("请输入第1个人的密码:");
scanf("%d",&head->passward);
p=head;
for(i=2;i<=n;i++)
{
q=(node *)malloc(sizeof(node));
if(q==0)
return 0;
printf("请输入第%d个人的密码:",i);
scanf("%d",&q->passward);
q->num=i;
p->next=q;
p=q;
} //将新结点插入在链表尾部
p->next=head; //构成循环链表
return head;
}
void josephus(node *I)
{
int i,m;
node *p=I,*q,*s;
printf("请输入报数上限(m):");
scanf("%d",&m);
printf("出列顺序为:\n");
while(p->next!=p)
{
for(i=1;i<m;i++)
{
q=p;
p=p->next;
}
printf("第%d个人出列,所持密码是%d\n",p->num,p->passward);
m=p->passward; //将出列的人的密码作为新的m值
s=p;
q->next=p->next;
p=p->next;
free(s); //释放动态申请的结点空间
}
printf("第%d个人出列,所持密码是%d\n",p->num,p->passward);
}
void main()
{
node *I;
I=creatlist();
josephus(I);
}
运行结果示例: