单链表实现约瑟夫环(JosephCircle) 问题

单链表实现约瑟夫环(JosephCircle) 问题_第1张图片

首先先了解一下什么是约瑟夫环问题

Josephus有过的故事:39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓。于是决定了自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀。然后下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列

其实解决约瑟夫环问题可以有很多种解法,用数组等等,但是用单链表来解决确是相对比较更直观更方便的一种,当把单链表头尾相接的时候它就变成了一个环,也比较符合问题的实际模型,

因为我们这里是使用单链表进行实现约瑟夫环,所以单链表肯定是必不可少的,为了方便用单链表建一个环,这里用到了几个关于单链表的基本操作,包括单链表结点结构体的定义,结点的创建,尾插,找到指定结点位置

对于单链表来实现解决约瑟夫环问题,我们在环中定义指针cur,每次指针走k次后删除当前指针所指位置的结点,然后继续向后走k次,接着删除当前所指结点,执行循环,直到环中只剩下一个结点(即cur->next == cur),那么最后的这个结点就是我们要找的结点,返回它的地址

总的来说解决约瑟夫环问题的思路并不复杂,代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include
#include

typedef int DataType;

typedef struct SListNode
{
	struct SListNode* _next;
	DataType _data;
}SListNode;

SListNode* BuySListNode(DataType x)
{

	SListNode* tmp = (SListNode*)malloc(sizeof(SListNode));
	if (tmp != NULL)
	{
		tmp->_data = x;
		tmp->_next = NULL;
		return tmp;
	}
	printf("节点创建失败!");
	return tmp;
}

void SListPushBack(SListNode** ppHead, DataType x)//从尾部插入数据
{
	SListNode* newNode;
	SListNode* tmp;
	newNode = BuySListNode(x);
	tmp = *ppHead;
	if (NULL == *ppHead)
	{
		*ppHead = newNode;
		(*ppHead)->_next = NULL;
	}
	else
	{
		while (tmp->_next)
		{
			tmp = tmp->_next;
		}
		tmp->_next = newNode;
		newNode->_next = NULL;
	}
}

SListNode* SListFind(SListNode* pHead, DataType x)//找到链表中的某个元素
{
	SListNode* tmp;
	tmp = pHead;
	while (tmp)
	{
		if (tmp->_data == x)
		{
			return tmp;
		}
		tmp = tmp->_next;
	}
	return tmp;
}

SListNode* SListJosephCircle(SListNode* pHead, int k)//单链表实现约瑟夫环(JosephCircle) 
{
	SListNode* cur = pHead;
	SListNode* tmp = NULL;
	while (cur != cur->_next)
	{
		int count = k;
		while (--count)
		{
			cur = cur->_next;
		}
		tmp = cur->_next;
		cur->_data = tmp->_data;
		cur->_next = tmp->_next;
		free(tmp);
	}
	return cur;
}


int main()
{

	SListNode* SList1 = NULL;
	SListPushBack(&SList1, 1);
	SListPushBack(&SList1, 2);
	SListPushBack(&SList1, 3);
	SListPushBack(&SList1, 4);
	SListPushBack(&SList1, 5);
	SListPushBack(&SList1, 6);
	SListPushBack(&SList1, 7);
	SListFind(SList1, 7)->_next = SListFind(SList1,1);
	printf("%d\n", SListJosephCircle(SList1, 3)->_data);
	system("pause");
	return 0;
}

这里简单的用1、2、3、4、5、6、7来做了一个简单的测试

单链表实现约瑟夫环(JosephCircle) 问题_第2张图片

以上就是关于用单链表解决约瑟夫环问题的相关解法以及思路





你可能感兴趣的:(数据结构)