1. 程式人生 > >資料結構—約瑟夫問題的C++實現

資料結構—約瑟夫問題的C++實現

約瑟夫環描述

編號為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。

人員出列思路

  1. temp = temp1;
  2. temp2->next = temp1->next;
  3. temp1 = temp->next;
  4. 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;
}