一、问题描述
设有n个人坐在一个圆桌周围,现从第s个人开始报数,数到第m个人出列,然后从出列的下一个人重新开始报数,数到第m个又出列......,如此反复知道所有人都出列为止。Josephus问题是:对于任意给定的n,m,和s,求出按照出列次序得到的n个人员的序列。
代码:
include <stdio.h>
#include<stdlib.h>
#define S() sizeof(struct quene)
typedef struct quene //定义一个结构体
{ int n; //数据域
struct quene *next; //指针域
} QUE;
QUE * fun1(int n); //函数原型说明
int fun2(QUE *p); //函数原型说明
int main() //主函数
{ int m,i,n,j,s;
QUE *p,*p2;
printf("n=");
scanf("%d",&n); //输入总人数
printf("m=");
scanf("%d",&m); //数到m的人出列
printf("i=");
scanf("%d",&i); //从第i个人开始报数
p=fun1(n); //主函数调用函数*fun1(n)
for(j=1;j<i;p=p->next,j++); //将开始报数的人重新设置魏头指针指向的节点
j=1;p2=p;
while((p->next)!=p) //循环直到只剩下一个节点
{ p=p->next;
if(++j==m)
{ j=1;p=p->next; //j变为1是为下一次村换时重新从1开始报数
s=fun2(p2); //主函数调用函数*fun2(p2)
printf("%d ",s);
}
p2=p;
}
printf("%d\n",p->n); //最后输出剩下的唯一一个编号
}
QUE * fun1(int n)
{ QUE *head,*p1,*p2;
int i;
for(i=1;i<=n;i++)
{ p1=(QUE *)malloc(S()); // 链表初始化
if(i==1) head=p1;
else p2->next=p1; //尾插法创建链表
p1->n=i;
p2=p1;
}
p1->next=head; //建立一个循环列表
return head; //p1指针后移
}
int fun2(QUE *p)
{ QUE *p2;
int n;
p2=p->next; //找到目标节点
n=p2->n;
p->next=p2->next; //删除目标节点
free(p2); //释放要删除的节点
return n;
}