1.首先,我们先来了解一下什么是约瑟夫环问题:
讲一个比较有意思的故事:约瑟夫是犹太军队的一个将军,在反抗罗马的起义中,他所率领的军队被击溃,只剩下残余的部队40余人,他们都是宁死不屈的人,所以不愿投降做叛徒。一群人表决说要死,所以用一种策略来先后杀死所有人。
于是约瑟夫建议:每次由其他两人一起杀死一个人,而被杀的人的先后顺序是由抽签决定的,约瑟夫有预谋地抽到了最后一签,在杀了除了他和剩余那个人之外的最后一人,他劝服了另外一个没死的人投降了罗马。
通俗来说就是:
按照如下规则去杀人:
所有人围成一圈
顺时针报数,每次报到3的人将被杀掉
被杀掉的人将从房间内被移走
然后从被杀掉的下一个人重新报数,继续报3,再清除,直到剩余一人
那么程序实现为:
链表的定义: 定义为编号即可 所以data项为int
typedef struct NODE{
struct NODE *next;
int data;
}Node,*Linklist;
由于是循环,直到最后一个人, 所有可以使用特殊的链表: 循环链表。 当链表中只剩下一个元素后,便认为完事了。 即 L->next = L;
#include <stdio.h>
#include <stdlib.h>
#include "Linklist.h"
void Print_Linklist(Linklist L)
{
Linklist head = L;
printf("List: ");
while(L->next != head)
{
printf("%d ",L->data);
L = L->next;
}
printf("%d ",L->data);
printf("\n");
}
int main()
{
int i;
Linklist L;
Linklist head;
Linklist Out;
L = (Node*)malloc(sizeof(Node));
head = L;
L->data = 1;
L->next = head;
for(i=2;i<=41;i++)
{
L->next=(Node*)malloc(sizeof(Node));
L->next->data = i;
L->next->next = head;
L = L->next;
}
Print_Linklist(head);
L = head;
while(L != L->next)
{
for(i=1;i<2;i++)
{
L = L->next;
}
Out = L->next;
printf("%2d号 ----> 自杀!\n",Out->data);
L ->next = Out->next;
L = L->next;
free(Out);
}
printf("幸存者是:%d",L->data);
return 0;
}