約瑟夫環問題
據說著名猶太曆史學家 Josephus有過以下的故事:在羅馬人佔領喬塔帕特後,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下一個重新報數,直到所有人都自殺身亡爲止。然而Josephus 和他的朋友並不想遵從。首先從一個人開始,越過k-2個人(因爲第一個人已經被越過),並殺掉第k個人。接着,再越過k-1個人,並殺掉第k個人。這個過程沿着圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續活着。問題是,給定了和,一開始要站在什麼地方纔能避免被處決?Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。->摘自百度百科
那麼約瑟夫環是怎麼實現的呢,毋庸置疑,循環鏈表
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int data;
struct node* next;
}node;
node *create(int n)
{
node *p=NULL,*head;
head=(node*)malloc(sizeof(node));
p=head;
node *s;
int i=1;
if(n!=0)
{
while(i<=n)
{
s=(node*)malloc(sizeof(node));
s->data=i++;
p->next=s;
p=s;
}
s->next=head->next;
}
free(head);
return s->next;
}
int main(void)
{
int n=41;
int m=3;
int i;
node *p=create(n);
node *temp;
m%=n;
while(p!=p->next)
{
for(i=1;i<m-1;i++)
{
p=p->next;
}
printf("%d->",p->next->data);
temp=p->next;
p->next=temp->next;
free(temp);
p=p->next;
}
printf("%d\n",p->data);
return 0;
}
然後讓我們來看看相似的題
編號爲1~N的N個人按照順時針方向圍坐一圈,每人持有一個密碼(正整數,可以自由輸入),開始人選一個正整數作爲報數上限M,從第一個人按照順時針方向自1開始順序報數,報道M時停止報數,報M的人出列,將他的密碼作爲新的M值,從他順時針方向上的下一個人開始從1報數,如此下去,直至所有人全部出列爲止
以下是代碼
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
typedef struct node
{
int num;
int code;
struct node *next;
}node;
node *create(int n) //創建一個n個數據元素的循環鏈表
{
node *p=NULL,*head;
head=(node*)malloc(sizeof(node)); //創建一個頭節點
p=head; //將p指向頭節點
if(p==NULL) //如果頭節點創建失敗
{
return 0;
}
/*生成一組隨機數存儲密碼的值*/
time_t ts;
srand((unsigned int)time(&ts)); //生成隨機數種子
node *s;
if(n!=0)
{
for(int i=1;i<=n;i++)
{
s=(node*)malloc(sizeof(node)); //生成一個新的節點
s->num=i; //每個節點編號
s->code=rand()%11+1; //隨機生成每個人的密碼
p->next=s; //第一次使頭節點指向s,之後使上一個數據元素指向節點s
p=s; //使p的位置後移
}
s->next=head->next;
free(head);
}
return s->next;
}
int main(void)
{
int n;
int m;
printf("\n--------------------------------------\n");
printf(" 請輸入有幾個人參加遊戲: \n");
scanf("%d",&n);
node *p=create(n); //生成一個循環鏈表
node *temp; //聲明一個臨時變量作爲交換
while(p->next!=p)
{
m=p->code;
m%=n;
for(int i=1;i<m-1;i++)
{
p=p->next; //使p指向出列數據的上一個數據元素
}
printf("%d>>",p->next->num); //打印出列人的編號
temp=p->next;
p->next=temp->next;
free(temp);
p=p->next;
}
printf("%d\n",p->num); //打印最後一個人的編號
return 0;
}
下面是代碼運行情況