約瑟夫環問題可以簡單的使用數組的方式實現,但是現在我使用循環鏈表的方法來實現,因為上午看到一道面試題規定使用循環鏈表解決約瑟夫環問題。
什么是約瑟夫環?
“約瑟夫環是一個數學的應用問題:已知n個人(以編號1,2,3...n分別表示)圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列;他的下一個人又從1開始報數,數到m的那個人又出列;依此規律重復下去,直到圓桌周圍的人全部出列。”(百度百科中的解決辦法列出了很多,可以看到循環鏈表并不是最簡單的方法)
這道面試題考察了循環鏈表的“創建”,“遍歷”和“刪除”。
創建的循環鏈表的結構圖:
解決約瑟夫環問題的過程
C++實現代碼如下:


1 /**循環鏈表解決約瑟夫環問題 2 * 問題:約瑟夫環 3 * 有編號從1到N的N個人坐成一圈報數,從第K個人開始報數,報到M的人出局, 4 * 下一位再從1開始報數,如此持續,直止剩下一位為止,報告此人的編號X。 5 * 輸入N,K,M,求出X。 6 */ 7 8 #include <iostream> 9 using namespace std; 10 11 struct MyNode 12 { 13 MyNode(int a_data):m_data(a_data),m_pNext(NULL) {} 14 15 int m_data; 16 MyNode *m_pNext; 17 }; 18 19 class Josephus 20 { 21 public: 22 Josephus(int a_N, int a_K, int a_M):m_N(a_N),m_K(a_K),m_M(a_M) 23 { 24 createList(); 25 outputList(); 26 } 27 28 protected: 29 void createList(); 30 void outputList(); 31 32 private: 33 MyNode *m_pHead;//循環鏈表的頭節點 34 int m_N; //鏈表節點個數 35 int m_K; //第一個報數人的序號 36 int m_M; //報數出局的數 37 }; 38 39 void Josephus::createList() 40 { 41 MyNode *pre = NULL; 42 MyNode *cur = NULL; 43 MyNode *p = new MyNode(1); 44 m_pHead = p; 45 cur = p; 46 for (int i=2; i<=m_N; i++) 47 { 48 p = new MyNode(i); 49 pre = cur; 50 cur = p; 51 pre->m_pNext = cur; 52 } 53 cur->m_pNext = m_pHead; 54 55 int n=m_N; 56 p = m_pHead; 57 while (n--) 58 { 59 cout << p->m_data << ","; 60 p = p->m_pNext; 61 } 62 cout << endl; 63 } 64 65 void Josephus::outputList() 66 { 67 MyNode *pre = NULL; 68 MyNode *cur = m_pHead; 69 m_K--; 70 while (m_K--) //尋找第K個人(開始報數的人) 71 { 72 pre = cur; 73 cur = cur->m_pNext; 74 } 75 while (m_N--) //輸出鏈表中所有的節點值 76 { 77 int s = m_M-1; 78 while (s--) //尋找間隔M的人 79 { 80 pre = cur; 81 cur = cur->m_pNext; 82 } 83 MyNode *p = cur; 84 cout << p->m_data << ","; 85 cur = cur->m_pNext; //刪除節點的過程 86 pre->m_pNext = cur; 87 delete p; 88 p=NULL; 89 } 90 } 91 92 int main() 93 { 94 Josephus josephus(100,5,5); 95 return 0; 96 }
?
測試結果: