約瑟夫環 佇列+連結串列

自為風月馬前卒發表於2017-03-28
設有n個人依次圍成一圈,從第1個人開始報數,數到第m個人出列,然後從出列的下一個人開始報數,數到第m個人又出列,…,如此反覆到所有的人全部出列為止。設n個人的編號分別為1,2,…,n,列印出列的順序。
【演算法分析】
       本題我們可以用陣列建立標誌位等方法求解,但如果用上資料結構中迴圈鏈的思想,則更貼切題意,解題效率更高。n人圍成一圈,把一人看成一個結點,n人之間的關係採用連結方式,即每一結點有一個前繼結點和一個後繼結點,每一個結點有一個指標指向下一個結點,最後一個結點指標指向第一個結點。這就是單迴圈鏈的資料結構。當m人出列時,將m結點的前繼結點指標指向m結點的後繼結點指標,即把m結點驅出迴圈鏈。
1、建立迴圈連結串列。
       當用陣列實現本題鏈式結構時,陣列a[i]作為"指標"變數來使用,a[i]存放下一個結點的位置。設立指標j指向當前結點,則移動結點過程為j=a[j],當數到m時,m結點出鏈,則a[j]=a[a[j]]。 當直接用鏈來實現時,則比較直觀,每個結點有兩個域:一個數值域,一個指標域,當數到m時,m出鏈,將m結點的前繼結點指標指向其後繼結點;
2、設立指標,指向當前結點,設立計數器,計數數到多少人;
3、沿鏈移動指標,每移動一個結點,計數器值加1,當計數器值為m時,  則m結點出鏈,計數器值置為1。
4、重複3,直到n個結點均出鏈為止。
 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 int a[10000001];
 5 int tot=1;
 6 int main()
 7 {
 8     int n,m;
 9     cin>>n>>m;
10     int j=n;
11     for(int i=0;i<n;i++)
12     {
13         a[i]=i+1;
14     }
15     a[n]=1;
16     int k=1;//報數 
17     while(tot<=n)
18     {
19         while(k<m)
20         {
21             j=a[j];
22             k++;
23         }
24         //cout<<a[j]<<" ";
25         printf("%d ",a[j]);
26         a[j]=a[a[j]];
27         k=1;
28         tot++;
29     }
30     return 0;
31 }

 

相關文章