数据结构--约瑟夫环问题

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;
}
发布了50 篇原创文章 · 获赞 30 · 访问量 9178

猜你喜欢

转载自blog.csdn.net/qq_42913794/article/details/98895581