C語言解決約瑟夫問題演算法
阿新 • • 發佈:2019-02-10
據說著名猶太曆史學家 Josephus有過以下的故事:在羅馬人佔領喬塔帕特後,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下一個重新報數,直到所有人都自殺身亡為止。然而Josephus
和他的朋友並不想遵從。首先從一個人開始,越過k-2個人(因為第一個人已經被越過),並殺掉第k個人。接著,再越過k-1個人,並殺掉第k個人。這個過程沿著圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續活著。問題是,給定了和,一開始要站在什麼地方才能避免被處決?Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲 。這就是著名的約瑟問題的由來。
約瑟夫問題是個有名的問題:N個人圍成一圈,從第一個開始報數,第M個將被殺掉,最後剩下一個,其餘人都將被殺掉。例如N=6,M=5,被殺掉的順序是:5,4,6,2,3,1。
我寫的解決約瑟夫問題的演算法如下:
void NewJosephus (int n,int order,int remain) { int count=1; int i; J *p=CreateLink(n);//建立迴圈單鏈表,並將頭指標返回給p J *q=p->next;//q初始指向第一個節點 J *m=p;//m初始指向頭指標 if(remain>=n) { printf("錯誤/n"); } else { while(p!=NULL) { if(count==order) { if(m==q) { break; } m->next=q->next; printf("%d ",q->data); free(q); q=m->next; count=1; n-=1; if(n==remain) { break; } } else { m=q; q=q->next; count+=1; } } p->next=q; printf("\n剩下的人為:\n"); for(i=0;i<remain;i++) { printf("%d ",q->data); q=q->next; } } }
其中,n為人的總數,order即為第幾個人被pass掉,remain是剩下人的個數。
建立單迴圈連結串列的演算法如下:
輸入41,3,2(即求原始的約瑟夫問題的解),結果如圖J* CreateLink(int n) { int i; J *head,*p,*q; head=(J*)malloc(sizeof(J)); head->next=NULL; q=head; for(i=1;i<=n;i++) { p=(J*)malloc(sizeof(J)); p->data=i; q->next=p; p->next=NULL; q=p; } q->next=head->next; return head; }
如果有不足之處,還望大家指出!