/************************************************************************/
/* 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;
}