是一个数学的应用问题:
已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
例如:n = 9, k = 1, m = 5
【解答】
出局人的顺序为5, 1, 7, 4, 3, 6, 9, 2, 8。
C语言实现:
#include<stdio.h>
typedef struct
{
int num;
int secret;
struct node *next;
}node,*linklist;
/* 创建链表 */
void creat(linklist head,int n)
{
node *s,*p;
int i,x;
p=head;
for(i=1;i<=n;i++)
{
s=(node *)malloc(sizeof(node)); /* 建立下一个结点,由s指向它*/
s->num=i;
printf("请输入第%d 个人的密码",i);
scanf("%d",&x);
s->secret=x;
p->next=s; /* s 链接到前面的结点 */
p=s;
}
p->next=head; /*建立成循环的链表 */
}
/*删除函数*/
void delete(node *p) /*删除p指向的下一个结点*/
{
node *q=p->next;
p->next=p->next->next;
free(q);
}
/*判断链表是否为空*/
int empty(node *head)
{
if(head->next==head)
return 0; /* 为空 */
else
return 1; /* 不为空 */
}
/* 链表的初始化*/
void initiate(linklist *head)
{
*head=(node *)malloc(sizeof(node));
(*head)->next=NULL;
}
/*约瑟夫环 */
void ring(linklist head,int m)
{
node *pre,*s;
int i;
pre=head; /*pre是s的前驱*/
s=head->next;
while(empty(head)==1) /*判断链表是否为空*/
{
for(i=1;i<m;i++)
{
pre=s;
s=s->next;
if(s==head) /* 要跳过头结点*/
{
pre=s;
s=s->next;
}
}
printf("被叫到的序号是%d ",s->num);
printf("被叫到的密码是%d\n",s->secret);
m=s->secret;
s=s->next;
if(s==head)
s=s->next;
delete(pre);
}
}
void main(void)
{
int n,m;
linklist head;
printf("请输入总人数");
scanf("%d",&n);
printf("请输入初始值");
scanf("%d",&m);
initiate(&head);
creat(head,n);
ring(head,m);
getch();
}