线性表练习1——约瑟夫环

问题描述

在这里插入图片描述

解题思路

  • 涉及循环链表的创建,删除

代码

#include <iostream>
using namespace std;
typedef int ElemType;

typedef struct CNode
{
	struct CNode* next;
	ElemType id;
	ElemType psd;
}CNode,*CLinkList;
bool CreateCLinkList(CLinkList& L, int n)
{
	L = (CNode*)malloc(sizeof(CNode));
	cin >> L->psd;
	L->id = 1;
	CNode* head = L;
	for (int i = 1; i < n; i++)
	{
		CNode* newNode = (CNode*)malloc(sizeof(CNode));
		cin >> newNode->psd;
		newNode->id = i + 1;
		L->next = newNode;
		L = newNode;
	}
	L->next = head;
	L = head;
	return true;
}
int main()
{
	int n, m;
	cin >> n >> m;
	CLinkList JosephList;
	CreateCLinkList(JosephList, n);
	CNode* p = JosephList;
	while (JosephList)
	{
		for (int i = 0; i < m-2; ++i)
		{
			p = p->next;
		}
		cout << p->next->id<<" ";
		m = p->next->psd;
		CNode* q = p->next;
		if (q->next == p)
		{
			cout << p->id;
			break;
		}
		p->next = q->next;
		free(q);
		if (m == 1)
		{
			CNode* q2 = p->next;
			cout << q2->id<<" ";
			if (q2->next = p)
			{
				cout << p->id;
				break;
			}
			p->next = q2->next;
			free(q2);
		}
		p = p->next;
	}
	return 0;
}
### 回答1: 这是一个关于约瑟夫环的问题。约瑟夫(Joseph)是指编号为1、2、3……n的n个人按顺时针方向围坐在一圈。每个人持有一个密码(正整数)。一开始,任意指定一个正整数作为报数上限值m。从第一个人开始顺时针地逐个报数,到第m个人时停止报数。同时,这个人要将自己的密码告诉旁边的人。然后,从他的下一个人开始再次顺时针逐个报数,直到报到第m个人时再次停止报数,并告诉旁边的人自己的密码。如此循环进行下去,直到最后只剩下一个人为止。这个问题要求选择一个正整数作为报数上限值m,使得在指定的n个人中,最后留下的那个人所持有的密码在第一个人开始报数时被报出来。 ### 回答2: 约瑟夫环是一种经典的问题,其基本思路是利用循环链表模拟人围成环形的场景,从而通过一定规则不断删除元素,直到只剩下一个元素为止。这个问题涉及到了线性表中的循环链表、链式存储结构、循环操作等内容,具有很强的实际应用价值。 解决约瑟夫环问题的基本思路是,从第一个人开始报数,每次报到m就出列,直到所有人都出列为止。为了能够便捷地删除被淘汰的人,我们需要采用链表的方式来实现。在具体实现时,我们可以将所有人看作链表中的结点,将它们通过指针相连成为一个循环链表。由于循环链表的最后一个结点指向链表的第一个结点,因此可以实现“环形”的效果。 当然,在实际计算中还需要进行一些优化。比如,当当前报数的人数大于m时,可以利用循环操作,方便地将当前结点移到距离它m位置后面的结点。此外,由于报数是环形的,因此我们需要对序号进行取模操作。具体算法步骤如下: 1、将所有人构成一个循环链表。 2、从第一个人开始报数(从1开始),每次报数都将当前结点移至距离它m的后面一个结点。 3、当当前人数小于或等于m时,删除当前节点,直至只剩下一个结点。 4、输出剩下的这个结点的编号,即为最后获胜者的编号。 总的来说,约瑟夫环是一个非常有趣的问题,它不仅仅涉及到数据结构与算法方面的知识,还可以帮助我们锻炼逻辑思维和问题解决能力。同时,它也具有很多实际应用价值,比如密码学领域中的随机数生成、进程管理等方面。因此,我们应当及时学习与掌握这个问题的解决方法,以便更好地应对各种挑战。 ### 回答3: 一开始,让第一个人从1开始报数,依次下去,凡报到m的倍数的人都要出列,直到最后只剩下一个人为止。这个人就是约瑟夫环问题的解。约瑟夫环问题可以用线性表来解决。 线性表是指由n个数据元素$ {a_1,a_2,...,a_n} $ 组成的有限序列,这些元素可以是基本数据类型或者结构类型,它们之间的关系是线性的,即前驱后继关系唯一确定。 对于约瑟夫环问题,我们可以用线性表来表示。可以用顺序表、链表或循环链表来实现。其中,循环链表最符合问题的特点,因为它可以将表首和表尾相连,形成一个环。 具体实现方法是,将n个人依次插入循环链表中,每个结点存储一个密码和一个指向下一个结点的指针。然后,从表头开始,每次数到m,就删除相应的结点,直到只剩下一个结点为止。最后留下的这个结点就是问题的解。 约瑟夫环问题有很多种求解方法,除了线性表之外,还可以用递归、数学公式等方法来求解。但是,用线性表来解决问题具有简单易懂、效率高等优点,是最常用的方法之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值