约瑟夫问题:有n个人围坐成圈,以1…n编号。从编号为k的人开始按照顺时针方向从1开始报数,报到m者出圈;然后他的下一个人继续从1开始报数,报到m者出圈,……, 如此下去,直到所有人都出列,求出列的次序。 显然,n个人构成线性表,按照顺时针方向每个元素都有唯一的前趋和后继, 利用循环链表进行存储是最自然的方式。求出列次序的过程可以简单描述为:
(1)、建立不带头结点的循环链表,每个结点代表约瑟夫环中的一个人;
(2)、在循环链表中查找第s个结点,记p为指向该结点的指针,而pre为该结点的 前驱结点;
(3)、从p所指向的结点开始计数查找第m个结点,输出该结点的元素值;
(4)、删除该结点,同时以该结点的后继结点指针记为p,重复步骤(2),直到循环链表为空。
C语言代码如下:
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int data;
struct node *next;
}LNode,*LinkList;
LinkList CreateList(LinkList L)//尾插法建立循环链表
{
LNode *r,*head,*s;//r为尾指针
int n,i;
L=(LinkList)malloc(sizeof(LNode));
L->data=1;
head=L;r=L;
head->next=r->next=NULL;
printf("请问共有几人参与游戏?\n");
scanf("%d",&n);
for(i=2;i<=n;i++)
{
s=(LinkList)malloc(sizeof(LNode));
s->data=i;
r->next=s;
r=s;
}
r->next=head;//首尾相连
return head;
}
void Joseph(LinkList L)
{
int num,m,i;
LinkList p,pre;
p=L;pre=p;p=p->next;
printf("请问从第几个人开始?\n");
scanf("%d",&num);
printf("请问报到那个数字出列?\n");
scanf("%d",&m);
for(i=2;i<num;i++)
{
pre=p;
p=p->next;
}
while(p->next!=p)
{
for(i=1;i<m;i++)
{
pre=p;p=p->next;
}
printf("%d",p->data);
pre->next=p->next;
free(p);
p=pre->next;
}
printf("%d",p->data);
free(p);
}
int main()
{
LinkList List,link;
link=CreateList(List);
Joseph(link);
return 0;
}


381

被折叠的 条评论
为什么被折叠?



