约瑟夫环问题(单向循环链表)

1 篇文章 0 订阅
1 篇文章 0 订阅

问题描述:
约瑟夫问题的一种描述是:编号为1,2,3~n的n个人按顺时针方向围坐一圈,没人持有一个密码(正整数),开始时任选一个整数作为报数上限值m,
从第一个人开始顺时针自1开始数序报数,报道m时停止报数。报m的人出列,将他的密码作为新的m值,从他顺时针的方向上下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止。设计一个程序,求出出列顺序。
利用单向循环列表作为存储结构模拟过程,按照出列顺序打印出个人的编号。
例如:m的初始值为20,n=7,7个人的密码分别是3,1,7,2,4,8,4,出列的顺序为6,1,4,7,2,3,5.

解题思路:
1.利用m=m%n,进行求余计算,然后遍历到此节点的前一个结点,进行删除操作
2.每次输出后更改m和n的值
3.结束的条件

#include<iostream>
using namespace std;
struct ListNode//创建节点
{
	int number;//number代表每个人的序列号
	int password;//每个人的密码
	struct ListNode* next;
};
struct ListNode* readList(int n)//创建链表,传入参数n时确定链表的长度
{
	struct ListNode* head = NULL, * last = NULL, * p;
	int temp;
	int a = n;
	for (int i = 1; i <= a; i++)
	{
		scanf_s("%d", &temp);//temp代表每个人的密码
		p = (struct ListNode*)malloc(sizeof(struct ListNode));
		p->number = i;
		p->password = temp;
		p->next = NULL;
		if (head == NULL)
			head = p;
		else last->next = p;
		last = p;
		
	}
	last->next = head;//尾部结点指向头节点,构成单向循环链表
	return head;
}
int main()
{
	int m, n;
	struct ListNode* L;
	printf("请输入m和n的值");
	scanf_s("%d %d",&m,&n);
	printf( "请依次输入每个人的密码:");
	L = readList(n);
	while (n)//结束条件
	{
		
		struct ListNode* temp;
		m = m % n;
		for (int i = 1; i < m - 1; i++)//找到需要删除节点的前一个节点
		{
			L = L->next;
		}
		temp = L->next;
		L->next = temp->next;
		printf("%d", temp->number);
		n--;
		m = temp->password;
		if (n != 0)//条件
		{
			if (m % n != 1)
			{
				L = L->next;
			}
		}
		free(temp);
	}

	
	return 0;
}
  • 5
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
好的,我可以帮你解答这个问题。 首先,让我们来了解一下约瑟夫问题的背景。约瑟夫问题是一个经典的问题,据传是由古代历史学家约瑟夫斯(Josephus)提出的。问题的具体描述如下: 有n个人围成一圈,从第一个人开始报数,报到m的人出圈,剩下的人继续从1开始报数,直到剩下最后一个人。求出最后一个出圈的人的编号。 为了解决这个问题,我们可以使用单向循环链表来实现。下面是一个简单的C++单向循环链表的实现,包含了三个文件:Node.h、List.h和List.cpp。 首先是Node.h文件,用来定义节点类: ```cpp // Node.h #ifndef NODE_H #define NODE_H class Node { public: int data; Node* next; Node(int data) { this->data = data; next = nullptr; } }; #endif ``` 然后是List.h文件,用来定义链表类: ```cpp // List.h #ifndef LIST_H #define LIST_H #include "Node.h" class List { public: List(); ~List(); void insert(int data); void remove(Node* node); Node* getHead(); Node* getNext(Node* node); private: Node* head; }; #endif ``` 最后是List.cpp文件,用来实现链表类的方法: ```cpp // List.cpp #include "List.h" List::List() { head = nullptr; } List::~List() { Node* curr = head; while (curr != nullptr) { Node* temp = curr; curr = curr->next; delete temp; } } void List::insert(int data) { Node* node = new Node(data); if (head == nullptr) { head = node; head->next = head; } else { Node* curr = head; while (curr->next != head) { curr = curr->next; } curr->next = node; node->next = head; } } void List::remove(Node* node) { Node* curr = head; if (node == head) { head = head->next; } else { while (curr->next != node) { curr = curr->next; } curr->next = node->next; } delete node; } Node* List::getHead() { return head; } Node* List::getNext(Node* node) { return node->next; } ``` 现在我们就可以使用这个单向循环链表来解决约瑟夫问题了。下面是一个简单的解决方案: ```cpp #include <iostream> #include "List.h" int josephus(int n, int m) { List list; for (int i = 1; i <= n; i++) { list.insert(i); } Node* curr = list.getHead(); while (n > 1) { for (int i = 1; i < m; i++) { curr = list.getNext(curr); } Node* temp = curr; curr = list.getNext(curr); list.remove(temp); n--; } return list.getHead()->data; } int main() { int n = 5; int m = 3; int result = josephus(n, m); std::cout << "The last person is " << result << std::endl; return 0; } ``` 这个程序将输出: ``` The last person is 4 ``` 这就是使用C++单向循环链表解决约瑟夫问题的一个简单的例子。希望能对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是令狐冲啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值