数据结构—约瑟夫问题的C++实现

约瑟夫环描述

编号为1,2······,n的n个人按顺时针方向围坐一圈,每人持有一个密码。一开始任选一个正整数作为报数上限值m,从第一个人开始顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他的顺时针方向上的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。试设计一个程序求出出列顺序。
测试数据: m的初值为20,n=7,七个人的密码依次为3,1,7,2,4,8,4。则首先m值为6 ,正确的出列顺序应该为6,1,4,7,2,3,5。


作者:君主图灵
来源:CSDN
原文:https://blog.csdn.net/sinat_40306833/article/details/78302670?utm_source=copy
版权声明:本文为博主原创文章,转载请附上博文链接!

人员出列思路

  1. temp = temp1;
  2. temp2->next = temp1->next;
  3. temp1 = temp->next;
  4. delete temp;
    出列过程

代码示例

#include <iostream>
using namespace std;

struct People{
	int number; //人员编号
	int password; //人员密码
	People *next; //链表节点
};


class Joseph{ //Joseph类,实现循环单链表的创建
private:
	int PeopleNum; //人员数n
	int DeleteNum; //首次设置的m值
	int OverNum; //报数上限值m
	People *head; //链表头结点
public:
	Joseph(int n, int m, int first_m); //建立循环单链表
	~Joseph();
	bool game(); //执行出列
};

Joseph::Joseph(int n, int m, int first_m)
{
	PeopleNum = n;
	OverNum = m;
	DeleteNum = first_m;
	People *temp1, *temp2;

	for (int i = 1; i <= PeopleNum; i++)
	{
		int inputPassword;
		cout << "请输入第" << i << "人的密码: ";
		cin >> inputPassword;

		temp1 = new People;
		temp1->number = i;
		temp1->password = inputPassword;
		if (i == 1) //首次插入节点
		{
			head = temp1;
			temp2 = temp1;
		}
		else   
		{
			temp2->next = temp1;  //将新建立结点temp1插入到temp2之后
			temp2 = temp1;  //temp2设为最后一个节点
		}
	}
	temp2->next = head; //实现链表的循环
}

Joseph::~Joseph()
{
	//delete head;
	//head = NULL;
	//此析构函数可以让它什么都不做
}

bool Joseph::game()
{
	People *temp1, *temp2, *temp;
	temp1 = head;
	int count;
	int a = DeleteNum;

	for (int i = 1; i <= PeopleNum; i++) //游戏整体轮数
	{
		count = 1; //每一轮游戏count的初始值都为1
		while (count < a)
		{
			temp2 = temp1;
			temp1 = temp1->next;
			count++;
		}
		cout << "出列人编号: " << temp1->number << endl;
		temp = temp1; //temp指向将要出列的人
		a = temp->password; //记录密码,用来删除下一个人
		temp2->next = temp1->next;
		temp1 = temp->next;
		delete temp;
    }
		cout << endl;
		head = NULL; //最后一个人出列后,将头指针设为NULL(一定不要忘记)
		return true;
	
}

int main()
{
	int n, m, first_m;
	cout << "请输入总人数n: ";
	cin >> n;
	cout << "请输入报数上限值m: ";
	cin >> m;
	cout << "请输入首次删除的序号: ";
	cin >> first_m;

	while (first_m <= 0 || first_m >= m)
	{
		cout << "输入值无效!\n请重新输入首次删除序号: ";
		cin >> first_m;
	}

	Joseph Test(n, m, first_m);
	Test.game();

	return 0;
}

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值