C++实现约瑟夫环的循环单链表
作者:些许草率罢了 发布时间:2022-11-12 19:34:29
标签:C++,约瑟夫环,单链表
约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知 n 个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。. 从编号为 k 的人开始报数,数到 m 的那个人出圈;他的下一个人又从 1 开始报数,数到 m 的那个人又出圈;依此规律重复下去,直到剩余最后一个胜利者。. 例如:有10个人围成一圈进行此游戏,每个人编号为 1-10 。. 若规定数到 3 的人出圈。. 则游戏过程如下。. (1)开始报数,第一个数到 3 的人为 3 号,3 号出圈。. 1, 2, 【 3 】, 4, 5, 6, 7, 8, 9, 10。. (2)从4号重新从1开始计数,则接下来数到3的人为6号,6号出圈。
废话不多说,直接上代码:
下面是头文件,命名为”约瑟夫环.h“
#ifndef Josephus_circle//判断是否被定义过Josephus_circle
#define Josephus_circle
struct Node//定义一个结构体,用来表示每一个结点
{
int data;//表示每一个结点的数字,也就是序号
Node* next;//定义一个结构体指针,用来指向后一个结点
};
class Josephus//定义一个类,里面包含有三个接口,和两个私有成员变量
{
public :
Josephus(int n);//定义一个构造函数,用来创建一个约瑟夫环
~Josephus();//析构函数,用以销毁一个约瑟夫环
void ResultShow(int m);//展示出圈顺序
private :
Node * rear,*first;//定义一个节点形指针,用来指向最后一个结点
};
#endif
下面是接口的具体实现,命名为“约瑟夫环.cpp”
#include<iostream>//引入输入输出流
#include"约瑟夫环.h"//引入约瑟夫环头文件
using namespace std;
Josephus::Josephus(int n)
{
first=rear = new Node;//将头指针和尾指针指向第一个新建的结点,也就是初始化指针
rear->data = 1;//首先,将第一个结点数据域赋值为1
for (int i = 2; i <= n; i++) //从2开始
{
Node* s = new Node;//定义一个Node形指针s,指向新建的一个结点
rear->next = s;//将指向头结点的尾指针指向下一个结点,也就是s所指的结点
s->data = i;//将新建的结点数字域赋值为i
rear = s;//将尾结点移动到新建结点s
}
rear->next = first;//在循环过后,将尾结点和头节点连接起来,构成循环链表
}
Josephus::~Josephus()
{
if (first!=rear)//判断环是否为空
{
while (first != rear)//每次循环都是当头节点不等于尾结点时候,开始删除:……
{
Node * p = first;//定义一个新的节点形指针,指向头节点,用作暂存要删去的结点
first = first->next;//将头节点移动到下一个结点
delete p;//删除之前头节点所指向的结点
}
delete rear;//在删除完成后,剩下的最后就只有尾结点了,删除即可
}
else
{
cout << "约瑟夫环为空,请先建立新环!" << endl;//空表提示
}
}
void Josephus::ResultShow(int m)
{
cout << "出环顺序为:" << endl;
Node * p = first;//定义一个Node类型的p,等于first
Node * pre=first,* reserve=nullptr;//定义pre等于first,和一个代替p指针被删除的结点的指针
int count = 1;//定义一个计数的count使其为一
while (p->next != p)//如果p->next所指向的结点是p的话,表示,这已经是最后一个结点了,该节点为最后出圈
{
if (count < m)//count来计数,每次到了m就出圈对应结点
{
pre = p;//将pre等于p,以便于表示p变换前的结点
p = p->next;//p向下一结点移动
count++;//移动一次count加一次
}
else//每次count=m时候就开始删除对应结点
{
pre->next = p->next;//首先从环中摘去要删除的p所指的结点
reserve = p;//使用reserve来保存被摘去的结点p
cout << p->data << "\t";//输出结点p所数据域,输出在屏幕上表示p结点的出圈
p = p->next;//p指向下一结点,以便于下一轮的循环
delete reserve;//删除保存p的reserve所对应的结点
count = 1;//将计数恢复为1,以便下一轮计数
}
}
cout << p->data << endl;//这最后一个就是最后出圈的结点,也就是所谓的胜利者,最后单独输出屏幕
delete p;//输出最后再删除这一结点,释放内存
pre=first=rear=p = NULL;//避免野指针出现使其指向空
}
下面是main函数,命名为“约瑟夫环_main.cpp”
#include<iostream>//引入输入输出流
#include"约瑟夫环.h"//引入头文件
using namespace std;
//主函数区域
int main() {
int m, n;
cout << "请输入约瑟夫环人数以及密码\n";
cout << "人数n:";
cin >> n;
cout << endl << "密码m:";
cin >> m;
Josephus L(n);//创建一个约瑟夫环,环数为10
L.ResultShow(m);//定义密码m,输出出圈顺序
return 0;
}
下面是运行截图:
来源:https://blog.csdn.net/qq_56715530/article/details/120990262


猜你喜欢
- openid可以标识一个用户,session_key会变,所以来获取一下openid。openid不能在微信小程序中直接获取,需要后台发送请
- 简介之前在项目中遇到了一个新需求,领导让我使用本地缓存,来缓存数据库查出的用户信息,经过一番资料查阅和实验,最终确定了使用Caffeine来
- 前言;Maven 作为经典的项目构建工具相信很多人已经用很久了,但如果体验过 Gradle,那感觉只有两个字“真香&am
- C语言奇偶排序算法奇偶排序,或奇偶换位排序,或砖排序,是一种相对简单的排序算法,最初发明用于有本地互连的并行计算。这是与冒泡排序特点类似的一
- Android 6本文根据我个人的开发经验,总结了从 Android 6 - Android 13 重要的行为变更。当然,这不是 Andro
- Mybatis注解查找@Select( "SELECT * FROM tt_user WHERE username Like #{
- 在Android Studio 2.1 Preview 3之后,官方开始支持双向绑定了。可惜目前Google并没有在Data Binding
- 今天看了一下数据结构,一个练习就是构建哈夫曼树,就顺手用C#写了一个。static void Main(string[] args){ &n
- 一、前言WPF没有内置IP地址输入控件,因此我们需要通过自己定义实现。我们先看一下IP地址输入控件有什么特性:输满三个数字焦点会往右移键盘←
- 本文为大家分享了java学生信息管理系统的源代码,供大家参考,具体内容如下/*学生信息管理系统,实现学生信息: *增加 int[] a=n
- 一、概述UDP和TCP是网络通讯常用的两个传输协议,C#一般可以通过Socket来实现UDP和TCP通讯,由于.NET框架通过UdpClie
- Java doGet, doPost方法和文件上传index.html<!DOCTYPE html><html lang=
- 一、显示信息对话框:使用“JOptionPane.showMessageDialog”显示:图标对话框类型语法显示错误类型对话框showMe
- 一直做Android前端,今天突然心血来潮想搭建一个后台玩玩。平时都是需要什么样的接口直接出个接口文档扔给后台的兄弟,自己从来不操心他们内部
- 前言链表是一种动态的数据结构,因为在创建链表时,不需要知道链表的长度,只需要对指针进行操作。1. 节点的创建 链表的节点包括两部分,分别是:
- 参数为对象1、提交表单2、表单序列化,使用ajax提交var data = $("#addForm").serializ
- 首先,我们需要增加用户对该脚本的执行权限,即 String cmdstring = "chmod a+x test.sh
- 1、包装类型是什么?Java 为每一个基本数据类型都引入了对应的包装类型,int 的包装类就是 Integer,从 Java 5 开始引入了
- 比如定义了一个错误的枚举类型public enum eErrorDetailCode : int &nbs
- 本文实例讲述了Android编程获取通知栏高度的方法。分享给大家供大家参考,具体如下:这里通过反射机制获取通知栏高度通知栏高度写在dimen