1. 程式人生 > >約瑟夫環的一個簡單演算法

約瑟夫環的一個簡單演算法

    前些天看到了一個常見的演算法題,約瑟夫環問題。       約瑟夫環是一個數學的應用問題:已知n個人(以編號1,2,3...n分別表示)圍坐在一張圓桌周圍。從編號為1的人開始報數,數到k的那個人出列;他的下一個人又從1開始報數,數到k的那個人又出列;依此規律重複下去,直到圓桌周圍的人全部出列。 例子:  n = 9,k = 5,從1開始報數。 【解答】  出局人的順序為5,1,7,4,3,6,9,2,8。 如果單純的不加思考,我們可以用迴圈連結串列來實現。 不過我把這個問題簡單的和數學結合,想出了一個簡單的演算法來實現。 基本思想為:通過迴圈遍歷陣列(長度為n),輸出出列的人的編號,然後再把剩下的人存到一個新的陣列       (長度為n-1),新陣列的第一個人為出列的人的後面一個,然後再通過函式遞迴來實現。 Coding的時候思考了幾天,由於考慮不周到,出現了蠻多bug,在和南開的同學討論後,稍稍修改了下,把很多情況都考慮到了,通過Debug和增加測試,使得程式執行成功。 演算法的實現具體請看下面:
#include <iostream>
using namespacestd; 

void Josephus( int n, int k, inta[] ) // 求解約瑟夫環的核心函式 
{
int i, j, c, t; //需要用到的變數 
int *b = new int[ n - 1 ]; //為陣列分配空間 
for( i = 0; i < n;i++ ) // 通過迴圈遍歷來輸出出列的人的編號 
{ 
if( n == k ) //如果n與k相等的話 
  t = k; // 編號為k的人將出列 
else if( k % n == 0 ) //考慮到取模為0的情況 
  t = n; // 編號為n的人將出列 
else
  t = k % n; // 編號為k%n的人將出列 
  
if( ( i + 1 ) == t ) //如果迴圈到的那個陣列下標與編號相等,則輸出(即出列) 
{
  cout<< a[i]<< " ";
  break; //break不能少 
}
}

for( j=i+1,c=0;c<n-1; c++,j++ ) //出列後將剩下的人分到一個新數組裡面,          
{                          //並以出列的人的後面一個人為起始元素 
if( j == n )
  j = 0;
b[c] = a[j];
}
n--; //佇列人數減去1 
if( n == 0 )  return; // 已全部出列,結束 
else   Josephus(n, k, b ); // 繼續遞迴 
}

int main()
{
int d[7]={1,2,3,4,5,6,7}; 
Josephus(7,7,d);
cout<< endl;
Josephus(7,4,d);
cout<< endl;
Josephus(7,10,d);
cout<< endl;
return 0;
}


特別鳴謝南開大學的DT童鞋為本人的程式碼做了debug工作~ 版權所有,若有引用,請標明出處並通知本人,謝謝對智慧財產權的合作~