約瑟夫環問題可以簡單的使用數組的方式實現,但是現在我使用循環鏈表的方法來實現,因為上午看到一道面試題規定使用循環鏈表解決約瑟夫環問題。
什么是約瑟夫環?
“約瑟夫環是一個數學的應用問題:已知n個人(以編號1,2,3...n分別表示)圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列;他的下一個人又從1開始報數,數到m的那個人又出列;依此規律重復下去,直到圓桌周圍的人全部出列。”(百度百科中的解決辦法列出了很多,可以看到循環鏈表並不是最簡單的方法)
這道面試題考察了循環鏈表的“創建”,“遍歷”和“刪除”。
源代碼如下:
#include<iostream> using namespace std; struct MyNode { MyNode(int a_data):m_data(a_data),m_pNext(NULL){} int m_data; MyNode *m_pNext; }; class Josephus { public: Josephus(int a_N,int a_K,int a_M):m_N(a_N),m_K(a_K),m_M(a_M){ createList(); outputList(); } protected: void createList(); void outputList(); private: MyNode *m_pHead; //循環鏈表的頭節點 int m_N; //鏈表節點個數 int m_K; // 第一個報數人的序號 int m_M; // 報數出局的數 }; void Josephus::createList() { MyNode *pre = NULL; MyNode *cur = NULL; MyNode *p = new MyNode(1); m_pHead = p; cur = p; for(int i=2; i<=m_N;i++) { p = new MyNode(i); pre = cur; cur = p; pre->m_pNext = p; } cur->m_pNext = m_pHead; int n = m_N; p = m_pHead; cout << "初始序列為:" << endl; while(n--){ cout << p->m_data << ","; p = p->m_pNext; } cout << endl; } void Josephus::outputList() { // 讓pStart指向第一個報數人的序號 MyNode *pStart = m_pHead; int count = 1; while(count < m_K){ pStart = pStart->m_pNext; count++; } MyNode *pTemp = pStart; MyNode *pPre = NULL; MyNode *tobeDeleted = NULL; cout << "依次出局的序列為:" << endl; while(pTemp->m_pNext!=pTemp) // when pTemp->m_pNext==pTemp only one node in the list { int count = 1; while(count < m_M){ pPre = pTemp; pTemp = pTemp->m_pNext; count++; } tobeDeleted = pTemp; pTemp = pTemp->m_pNext; pPre->m_pNext = pTemp; cout << tobeDeleted->m_data << ","; } cout << pTemp->m_data << endl; } int main() { int total_people; int start; int step; cout << "請輸入總人數:" << endl; cin >> total_people; cout << "請輸入開始數的人:" << endl; cin >> start; cout << "請輸入出局人數的數:" << endl; cin >> step; Josephus josephus(total_people,start,step); return 0; }
運行程序結果如下: