约瑟夫问题简述:著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数到3,循环直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,于是,他将朋友与自己安排在第16个与第31个位置,于是最后自杀只剩下他们两人,便逃过了这场死亡游戏。
josephus.c
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define ERROR -1
typedef int ElemType; //声明元素类型
typedef struct Node
{
ElemType data;
struct Node * next;
} Node;
typedef struct Node *LinkList;
int InitializeList(LinkList);
int TraverseList(LinkList L);
/*使用循环链表,求解约瑟夫问题*/
int main(int argc,char *argv[])
{
printf("********Main*********************************\n");
Node L;
L.next=&L;
InitializeList(&L); //初始化循环链表
TraverseList(&L); //求解约瑟夫问题
exit(0);
}
int InitializeList(LinkList L)
{
LinkList p,current;
current=L;
int i;
for(i=0;i<41;i++) //初始化41个结点
{
p=(LinkList)malloc(sizeof(Node));
p->data=i+1;
p->next=L;
current->next=p;
current=p;
}
}
int TraverseList(LinkList L)
{
LinkList p=L,tmp;
int i=1;
while(p->next!=p) //自己指向了自己,说明循环链表除了空的头结点外,就只剩一个结点了。
{
if(i%3==0) //数到3,这个人就要被咔嚓掉了
{
printf("%d,",p->next->data);
tmp=p->next;
p->next=p->next->next;
free(tmp);
}
else
{
p=p->next;
}
i++;
if(p->next==L) //循环链表的头,是个空节点,所以要跳过它。
{
p->next=L->next;
}
}
printf("%d,\n",p->data); //把最后一个结点的值输出,即最后一个幸存者
free(p);
return TRUE;
}