1. 程式人生 > >約瑟夫問題(單向迴圈連結串列應用例項)

約瑟夫問題(單向迴圈連結串列應用例項)

據說著名猶太曆史學家 Josephus有過以下的故事:在羅馬人佔領喬塔帕特後,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下一個重新報數,直到所有人都自殺身亡為止。然而Josephus 和他的朋友並不想遵從。首先從一個人開始,越過k-2個人(因為第一個人已經被越過),並殺掉第k個人。接著,再越過k-1個人,並殺掉第k個人。這個過程沿著圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續活著。問題是,給定了和,一開始要站在什麼地方才能避免被處決?Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置

,於是逃過了這場死亡遊戲。

根據上面的問題我們分析出可以通過單向迴圈連結串列解決:

#include "StdAfx.h"
#include <stdio.h>
#include <stdlib.h>

typedef struct node{
	int data;
	struct node* next;
}node;

node* create(int n){
	node* head=(node*)malloc(sizeof(node));
	if(!head)
		return NULL;
	node* pTemp=head;
	for(int i=0;i<n;i++){
		node* p=(node*)malloc(sizeof(node));
		if(!p)
			return NULL;
		p->data=i+1;
		p->next=pTemp->next;
		pTemp->next=p;
		pTemp=p;
	}
	pTemp->next=head->next;//構造一個迴圈連結串列
	pTemp=head;
	head=head->next;//得到第一個
	free(pTemp);
	return head;//最後得到第一個結點
}

int main(){
	//約瑟夫問題
	int n=41;
	int m=3;//第三個人就會被選出
	node* head=create(n);//建立41個迴圈連結串列
	node* p=head;
	m%=n;//取餘數
	while(p!=p->next){//如果只剩下一個則自己指向自己
		for(int i=1;i<m-1;i++){
			p=p->next;
		}
		node* pTemp=p->next;
		printf("%d ",pTemp->data);//打印出來
		p->next=pTemp->next;
		free(pTemp);
		p=p->next;
	}
	printf("%d ",p->data);//打印出來
	return 0;
}