約瑟夫環的一個簡單演算法
阿新 • • 發佈:2019-01-28
前些天看到了一個常見的演算法題,約瑟夫環問題。
約瑟夫環是一個數學的應用問題:已知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和增加測試,使得程式執行成功。
演算法的實現具體請看下面:
特別鳴謝南開大學的DT童鞋為本人的程式碼做了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工作~ 版權所有,若有引用,請標明出處並通知本人,謝謝對智慧財產權的合作~