資料結構 - 連結串列 - 迴圈連結串列
阿新 • • 發佈:2022-03-22
用約瑟夫環問題來演示迴圈連結串列的使用。
約瑟夫環問題
約瑟夫問題是一個經典的問題。已知 \(n\) 個人(不妨分別以編號 \(1\),\(2\),\(\cdots\),\(n\) 代表)圍坐在一張圓桌周圍,從編號為 \(k\) 的人開始,從 \(1\) 開始順時針報數 \(1\),\(2\),\(\cdots\),順時針數到 \(m\) 的那個人,出列並輸出。然後從出列的下一個人開始,從 \(1\) 開始繼續順時針報數,數到 \(m\) 的那個人,出列並輸出,\(\cdots\),依此重複下去,直到圓桌周圍的人全部出列。
輸入格式
\(n,k,m\)
輸出格式
按照出列的順序依次輸出出列人的編號,編號中間相隔一個空格,每 \(10\)
非法輸入的對應輸出如下
-
輸入:\(n\)、\(k\)、\(m\) 任一個小於1
輸出:\(\text{n,m,k must bigger than 0.}\) -
輸入:\(k>n\)
輸出:\(\text{k should not bigger than n.}\)
輸入輸出樣例
輸入
9,3,2
輸出
4 6 8 1 3 7 2 9 5
題解
用迴圈連結串列暴力模擬,充分利用 STL 中的 list。
#include <cstdio> #include <algorithm> #include <queue> #include <cstring> #include <iostream> #include <set> #include <list> using namespace std; #define MAX 1005 #define INF 0x3f3f3f3f int main() { list<int> nums; int n, k, m; scanf("%d,%d,%d", &n, &k, &m); if (n < 1 || k < 1 || m < 1) { printf("n,m,k must bigger than 0.\n"); return 0; } if (k > n) { printf("k should not bigger than n.\n"); return 0; } for (int i = 1; i <= n; ++i) nums.push_back(i); int cnt = 0; list<int>::iterator it = nums.begin(); for (int i = 2; i <= k; ++i) ++it; while (!nums.empty()) { // 報數至數到 m 的那個人為止 for (int i = 2; i <= m; ++i) { ++it; if (it == nums.end()) { it = nums.begin(); } } // 輸出 if (nums.size() != 1) { ++cnt; if (cnt % 10 != 0) printf("%d ", *it); else printf("%d\n", *it); } else printf("%d\n", *it); // 刪除該報數的元素,同時利用 erase 函式的機制重新指向該元素的下一個元素 it = nums.erase(it); // 小心下一個元素指在了列表的尾指標 if (it == nums.end()) it = nums.begin(); } return 0; }