C++利用循环单链表解决约瑟夫环问题

有n个元素,编号从1号开始一直到n号,形成一个环,从第k号开始报数,报到m的出列,直到所有元素都出列为止。

要求:n,k,m的值由用户输入,调用函数实现。

测试数据:

例:10个元素,从1号开始,报到3的元素出列。则出列顺序为:3,6,9,2,7,1,8,5,10,4;

10个元素,从5号开始,报到1的元素出列。则出列顺序为:5,6,7,8,9,10,1,2,3,4;

100个元素,从20开始,报到33的元素出列,则出列顺序是什么?

以测试数据1为例:

-------------------------------------------------------------------------------------

定义单链表数据结构

#include <iostream>
using namespace std;

typedef int ElemType;
typedef struct LNode 
{
	ElemType data;
	LNode* next;
} LinkNode;

1.初始化循环单链表

void InitNode (LinkNode*& L)
{
	L = new LinkNode;
	L-> next = L;
}

 

2.尾插法建立循环单链表

void CreateListByRear (LinkNode*& L, LinkNode*& r, ElemType arr[], int n) 
{
	r = L;     				// 尾指针并指向头节点
	L->data = arr[0];       // 头节点的data赋值
	
	for (int i = 1; i < n; ++i) // 新建节点并插入数据
    {       
		LinkNode* s = new LinkNode;
		s->data = arr[i];
		r->next = s;
		r = s;
    }
	r->next = L;
}   

 

 3.输出出圈顺序

pre指针指向p的前驱结点,方便销毁结点后,连接下一个结点。

void out(LinkNode*& p, LinkNode*& pre, int count, int move) 
{
	int i = 1;
	
//  移动节点,到开始的那个数
	while (--move) {
		p = p->next;
		pre = pre->next;
	}
	
//  当圈不为1个人时,循环出圈
	while (p->next != p)
    {
		
		if (i == count) // 数到某个数,就出圈
        {       
			i = 1;
			cout << p->data << " ";
			
			pre->next = p->next;    // 删除出圈节点
			delete p;
			p = pre->next;
			
		} 
        else
        {
			pre = pre->next;        // 如果没数到指定的数,就继续移动,并统计
			p = p->next;
			++i;
		}
	}
	cout << p->data << endl;        // 输出圈的最后一个数
}

--------------------------------------------------------------------------------------主函数

int main() 
{
// 1. 定义头尾节点指针, 初始化头节点指针
	LinkNode* head; InitNode(head);
	LinkNode* rear;
	
// 2.定义, 输入需要的参数; 初始化数组并赋值
	int n, m, from;
	cout << "请输入元素个数: "; cin >> n;
	cout << "从第几个人开始? "; cin >> from;
	cout << "第几个人出圈? "; cin >> m;
	int* a = new int[n];        // 创建动态数组

	for (int i = 0; i < n; ++i) {   // 把元素插入到数组中
		a[i] = i + 1;
	}
	
//  3. 尾插法创建循环单链表并得到尾指针
	CreateListByRear(head, rear, a, n);
	
//  4. 出圈并输出
    cout << "出圈顺序为: ";
	out(head, rear, m, from);
	
//  5. 出圈后仅剩头节点,释放头节点指针所指空间即可
	delete head;
	
	return 0;
}

  • 8
    点赞
  • 117
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

henry594小李

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

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

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

打赏作者

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

抵扣说明:

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

余额充值