資料結構—約瑟夫問題的C++實現
阿新 • • 發佈:2018-12-14
約瑟夫環描述
編號為1,2······,n的n個人按順時針方向圍坐一圈,每人持有一個密碼。一開始任選一個正整數作為報數上限值m,從第一個人開始順時針方向自1開始順序報數,報到m時停止報數。報m的人出列,將他的密碼作為新的m值,從他的順時針方向上的下一個人開始重新從1報數,如此下去,直到所有人全部出列為止。試設計一個程式求出出列順序。 測試資料: m的初值為20,n=7,七個人的密碼依次為3,1,7,2,4,8,4。則首先m值為6 ,正確的出列順序應該為6,1,4,7,2,3,5。
人員出列思路
- temp = temp1;
- temp2->next = temp1->next;
- temp1 = temp->next;
- delete temp;
程式碼示例
#include <iostream> using namespace std; struct People{ int number; //人員編號 int password; //人員密碼 People *next; //連結串列節點 }; class Joseph{ //Joseph類,實現迴圈單鏈表的建立 private: int PeopleNum; //人員數n int DeleteNum; //首次設定的m值 int OverNum; //報數上限值m People *head; //連結串列頭結點 public: Joseph(int n, int m, int first_m); //建立迴圈單鏈表 ~Joseph(); bool game(); //執行出列 }; Joseph::Joseph(int n, int m, int first_m) { PeopleNum = n; OverNum = m; DeleteNum = first_m; People *temp1, *temp2; for (int i = 1; i <= PeopleNum; i++) { int inputPassword; cout << "請輸入第" << i << "人的密碼: "; cin >> inputPassword; temp1 = new People; temp1->number = i; temp1->password = inputPassword; if (i == 1) //首次插入節點 { head = temp1; temp2 = temp1; } else { temp2->next = temp1; //將新建立結點temp1插入到temp2之後 temp2 = temp1; //temp2設為最後一個節點 } } temp2->next = head; //實現連結串列的迴圈 } Joseph::~Joseph() { //delete head; //head = NULL; //此解構函式可以讓它什麼都不做 } bool Joseph::game() { People *temp1, *temp2, *temp; temp1 = head; int count; int a = DeleteNum; for (int i = 1; i <= PeopleNum; i++) //遊戲整體輪數 { count = 1; //每一輪遊戲count的初始值都為1 while (count < a) { temp2 = temp1; temp1 = temp1->next; count++; } cout << "出列人編號: " << temp1->number << endl; temp = temp1; //temp指向將要出列的人 a = temp->password; //記錄密碼,用來刪除下一個人 temp2->next = temp1->next; temp1 = temp->next; delete temp; } cout << endl; head = NULL; //最後一個人出列後,將頭指標設為NULL(一定不要忘記) return true; } int main() { int n, m, first_m; cout << "請輸入總人數n: "; cin >> n; cout << "請輸入報數上限值m: "; cin >> m; cout << "請輸入首次刪除的序號: "; cin >> first_m; while (first_m <= 0 || first_m >= m) { cout << "輸入值無效!\n請重新輸入首次刪除序號: "; cin >> first_m; } Joseph Test(n, m, first_m); Test.game(); return 0; }