1. 程式人生 > >約瑟夫環問題連結串列實現

約瑟夫環問題連結串列實現

問題描述:約瑟夫環問題是,編號為1,2,3,…,n的n個人按順時針方向圍坐一圈,每人持有一個密碼。開始時任選一個正整數作為報數上限值m,從第一個人開始順時針方向自1開始順序報數,報到m時停止報數。報m的人出列,將他的密碼作為新的m值,從他在順時針方向上的下一個人開始重新從1報數,如此下去,直至所有人全部出列為止。

基本要求:利用單鏈表儲存結構模擬此問題,按照出列順序列印各人的編號。

測試資料:M的初值為20,n=7,7個人的密碼依次為3,1,7,2,4,8,4。則首先出列的人是6號,依次正確的出列順序應該為6,1,4,7,2,3,5。

實現提示:要求使用者指定報數上限值,然後讀取每人的密碼。此問題所用迴圈連結串列不需要頭結點。

實現思路:構造一個迴圈連結串列,通過迴圈始終將一個指標指向第m個人的直接前驅,更新密碼m,修改連結串列

#include<stdio.h>
#include<malloc.h> 
#define LEN sizeof(struct Node) 
struct Node
{
	int num;								//編號 
	int code;								//密碼 
	struct Node *next;
};
//建立長度為n單向迴圈連結串列
struct Node *creat(int n)
{
	int i=1;
	struct Node *p,*q,*head;
	p=(struct Node*)malloc(LEN);
	for(i=1;i<=n;i++)
	{
		if(i==1)
			head=p;				//頭指標 
		else
		{
			q=(struct Node*)malloc(LEN);
			p->next=q; 
			p=q;	
		}	
		p->num=i;
		scanf("%d",&p->code);		//依次輸入密碼 
	}
	p->next=head;
	return head;
}
//輸出出列人的編號
void joseph(struct Node *head,int m)
{
	struct Node *p,*q;
	q=head;
	//head的前驅初始化為 q,
	while(q->next!=head)
			q=q->next;
		p=head;					//p指向 head 
	//連結串列中超過一個結點 
	while(p->next!=p)
	{
		//p指向要出列的人,q的後繼指向p 
		for(int i=1;i<m;i++)
		{
			p=p->next;
			q=q->next;
		}
		printf("%d ",p->num);
		m=p->code;
		q->next=p->next;
		p=p->next;
	}
	//連結串列中只剩餘一個結點,輸出 
	if(p->next==p)
		printf("%d ",p->num);
}
int main()
{
	struct Node *head;
	int M,n;
	printf("輸入連結串列長度 n 和 M 的初始值:\n");
	scanf("%d%d",&n,&M);
	printf("依次輸入 %d 個人的密碼:\n",n);
	head=creat(n);				//建立連結串列 
	printf("出列的人依次為:\n");
	joseph(head,M);				//依次輸出出列人員編號 
	return 0;
}