數據結構--約瑟夫環問題

1.問題描述
約瑟夫環(約瑟夫問題)是一個數學的應用問題:已知n個人(以編號1,2,3…n分別表示)圍坐在一張圓桌周圍。從編號爲k的人開始報數,數到m的那個人出列;他的下一個人又從1開始報數,數到m的那個人又出列;依此規律重複下去,直到圓桌周圍的人全部出列。

鏈表思路:
我是通過單鏈表實現的,
首先要思考怎麼成一個圈?(循環鏈表不必考慮這個問題。)
1.給n個人依次從小到大編號,先將最大號碼放入鏈表,再定義一個指針plast代表表尾,此時它既爲表頭phead,又爲表尾。
2.依次將後面的號碼放入鏈表,表頭phead不斷更新,表尾plast始終指向最開始放入的最大號碼。
3.待號碼全部放入時,將表尾的next指向表頭,成環。

//先把最大的數放進去
	SListPushFront(&phead, m);
	plast = phead;

	//依次放入剩下的數,形成鏈表
	for (i = m - 1; i >=1; i--)
	{
		SListPushFront(&phead, i);
	}
	plast->next = phead;//形成一個環

然後再思考怎樣數數?
1.首先先找到數數的結束條件,就是只剩下一個人時,停止數數,玩家勝利。數數的次數應該=剩下的人數-1。每當有一個人出局時,數數次數就減少一次。
2.再找一個指針,它指向的節點的next就是要出局的節點。

cur = plast;//只有第一個跳的個數不一樣,這樣可以保證第一次的正確

	for (; m > 1; m--)
	{
		for (i = 1; i < n; i++)	//數數,跳n-1步後刪
		{
			cur = cur->next;
			printf("%d號報%d\n", cur->data, i);
		}
		printf("%d號出圈\n", cur->next->data, i);
		SListEraseAfter(cur);
	}

測試
輸入人數m爲5,數的數字n爲2:
在這裏插入圖片描述
源代碼:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>


//無頭單向非循環鏈表
typedef int SLTDataType;

typedef struct SListNode
{
	SLTDataType data;
	struct SListNode *next;
}SListNode;

void SListInit(SListNode **pphead)//初始化
{
	*pphead = NULL;
}
void SListPushFront(SListNode **pphead, SLTDataType x)//頭插
{
	SListNode *tmp = BuySListNode(x);
	tmp->next = (*pphead);
	(*pphead) = tmp;
}
void SListEraseAfter(SListNode *pos)//刪除pos後面的節點,把pos的地址傳進來,改變pos指向的空間
{
	SListNode *tmp = pos->next;
	if (tmp == NULL)
	{
		return;
	}
	pos->next = tmp->next;
	tmp = NULL;
}


int main()
{
	int i = 0;
	int n = 0;//數的數字
	int m = 0;//數數的人數
	SListNode* phead;
	SListNode* plast=NULL;
	SListNode* cur=NULL;
	scanf("%d %d", &m, &n);
	SListInit(&phead);
	//先把最大的數放進去
	SListPushFront(&phead, m);
	plast = phead;

	//依次放入剩下的數,形成鏈表
	for (i = m - 1; i >=1; i--)
	{
		SListPushFront(&phead, i);
	}
	plast->next = phead;//形成一個環

	cur = plast;//只有第一個跳的個數不一樣,這樣可以保證第一次的正確

	for (; m > 1; m--)
	{
		for (i = 1; i < n; i++)	//數數,跳n-1步後刪
		{
			cur = cur->next;
			printf("%d號報%d\n", cur->data, i);
		}
		printf("%d號出圈\n", cur->next->data, i);
		SListEraseAfter(cur);
	}
	printf("%d號勝利\n", cur->data);
	free(cur);
	system("pause");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章