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。

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

思路:

其中包含一些對連結串列的基本操作,新增,輸出,刪除等。

程式碼: 

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

typedef struct _node{
	int xuhao;
	int mima;
	struct _node *next; 
}Node;//定義結點的結構體型別 

typedef struct _list{
	Node *head;
	Node *tail;
	Node *mark;
	Node *smark;
}List;//自定義指向連結串列的一些指標 

void add(List *pList,int x,int m);
void print(List *pList);
void shanchu(List *pList,int x);
void printw(List *pList);

int main(int argc,const char*argv[])
{
	int m,n;
	scanf("%d %d",&m,&n);
	int a[n+1];
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	List list;
	list.head=NULL;
	for(int i=1;i<=n;i++)//構造結點個數為n的連結串列 
	{
		add(&list,i,a[i]);
	}
	//printw(&list); //檢查連結串列是否新增正確 
	int number=n;//連結串列中結點的個數,用作迴圈的終止條件 
	list.mark=list.head;
	while(number>0)
	{
		int yushu=m%number;//取模運算,找到要輸出的結點的位置 
		for(int i=yushu;i>1;i--)//迴圈使mark指向所要操作的結點 
		{
			if(list.mark->next)
			{
				list.mark=list.mark->next;
		    }
			else
			{
				list.mark=list.head;
			}
		}
        list.smark=list.mark;
		m=list.mark->mima;
		number--;//每次重置m,number減一 
		print(&list); 
		if(list.mark->next){
			list.mark=list.mark->next;
		}else{
			list.mark=list.head;
		}
		shanchu(&list,list.smark->xuhao);
		//printw(&list);//檢驗輸出每次刪除之後的連結串列是否正確 
	}
	return 0;
}

void add(List *pList,int x,int m)//新增單個結點到連結串列中 
{
	 Node *p=(Node *)(malloc)(sizeof(Node));
	 p->xuhao=x;
	 p->mima=m;
	 if(pList->head){
	 	pList->tail->next=p;
	 	pList->tail=p;
	 }else{
	 	pList->head=p;
	 	pList->tail=p;
	 }
	 p->next=NULL;
}

void print(List *pList)//輸出引數中pList所指的mark所指的序號 
{
	printf("%d\t",pList->mark->xuhao);
}

void shanchu(List *pList,int x)//刪除單個結點 
{
	Node *p=pList->head;
	Node *q;
	while(p->xuhao!=x&&p)
	{
		q=p;
		p=p->next;
	}
	if(p==pList->head){      //當刪除的結點是head所指向的第一個結點時 
		pList->head=p->next;
	}else
	{
		q->next=p->next;
    }
	free(p);
}

void printw(List *pList)//輸出整個連結串列 
{
	Node *p=pList->head;
	while(p)
	{
		printf("%d\t",p->mima);
		p=p->next;
	}
	printf("\n");
}