約瑟夫環問題連結串列實現
阿新 • • 發佈:2018-12-14
問題描述:約瑟夫環問題是,編號為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; }