實戰資料結構(4)_迴圈單連結串列解決約瑟夫問題

YunShell發表於2013-08-24

/************************************************************************/
/* author:  lynnbest	2013.8.24
約瑟夫問題:
	有n個人,編號為1,2,3...n圍成一個圓圈,按照順時針方向從編號為k的人
開始報數,報數為m的人出列,她的下一個人重新開始從1報數,數到m的人出列
如此重複下去,知道所有人都出列,編寫一個演算法,要求輸入n,k,m按照出列的
順序輸出編號
exp:
1,2,3,4,5,6,7一圈	n=8,k=2,m=3
則按照輸出的編號為:4 7 2 6 3 1 5 8
                                                                     */
/************************************************************************/
/************************************************************************/
/* 思路:
1.先建立一個迴圈連結串列
2.查詢到k元素位置
3.查詢到m元素位置
		查詢到後,先記錄下一個節點位置copynode=startnode->next
		然後刪除節點
跳轉到2
4.列印最後一個節點 free()
                                                                     */
/************************************************************************/
#include <stdio.h>
#include <stdlib.h>

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

void josephus(listnode *h,int n,int k,int m);
void printflist(listnode *h);
listnode *CreateCircleList(int n);
void main()
{	
	printf("    約瑟夫問題	\n");
	printf("----by lynnbest ----\n\n");
	int n,k,m;
	printf("輸入n,k,m\n");
	scanf("%d,%d,%d",&n,&k,&m);
	listnode *h=CreateCircleList(n);//建立一個迴圈列表
	printflist(h);
	printf("依次退出的編號為:\n");
	josephus(h,n,k,m);

}

void josephus(listnode *h,int n,int k,int m)
{
	listnode *startnode,*copynode,*pre;
	startnode=h;
	int i;
	//查詢到k位置
	while(k-1)
	{
		startnode=startnode->next;
		k--;
	}
	
	//查詢m位置
	while(startnode->next!=startnode)//當該節點不是最後一個節點
	{	
		
		for(i=1;i<m;i++)
		{
			pre=startnode;
			startnode=startnode->next; //startnode為要刪除的節點 pre為其前驅節點
		}
		copynode=startnode->next;	//備份當前要刪除位置節點的下一個節點
		printf("%3d",startnode->data);
		pre->next=startnode->next;//刪除節點
		free(startnode);
		startnode=copynode;
	}	
	printf("%4d\n",startnode->data);
	free(startnode);
}

void printflist(listnode *h)
{	
	printf("當前連結串列元素為:\n");
	listnode *p=h;
	while(p->next!=h)
	{
		printf("%4d",p->data);
		p=p->next;	//漏了
	}
	printf("%4d\n",p->data);
}

listnode *CreateCircleList(int n)
{	
	listnode *head=NULL,*newnode,*pre;
	for(int i=1;i<=n;i++)
	{
		if(NULL==(newnode=(listnode *)malloc(sizeof(listnode))))
		{
			printf("malloc新節點失敗\n");
			exit(-1);
		}
		newnode->data=i;
		if(NULL==head)	//不帶頭節點的怎麼建立 技巧
			head=newnode;
		else
			pre->next=newnode;
		pre=newnode;
	}
	newnode->next=head;//構成迴圈連結串列
	return head;
}

相關文章