【算法】单向环形链表解决Josephu(约瑟夫)问题

应用场景

n 个小孩标号,逆时针站一圈。从 k 号开始,每一次从当前的小孩逆时针数 m 个,然后让最后这个小孩出列。不断循环上述过程,直到所有小孩出列,由此产生出一个队列编号。

提示

用一个不带头节点的循环链表来处理 Josephu 问题:先构成一个有 n 个节点的单循环链表,然后从 k 节点起从 1 开始计数,记到 m 时对应的节点从链表中删除,然后从下一个节点从 1 开始计数,直到最后一个节点从链表中删除算法结束

单向环形链表

构建一个单向环形链表的思路

1.先创建第一个节点,让 first 指向该节点,并形成环形

2.后面当我们每创建一个新节点,就将该节点加入到已有的环形链表中即可

//添加节点,构建成一个环形链表public void addBoy(int nums) {  //nums代表添加的节点的个数//nums 做一个数据校验if (nums < 1) {System.out.println("nums的值不正确");return;}Boy curBoy = null;  //辅助指针,帮助创建环形链表//使用for循环创建一个环形链表for (int i = 1; i <= nums; i++) {//根据编号,创建节点Boy boy  = new Boy(i);//如果是第一个小孩if (i == 1) {first = boy;first.setNext(first);  //构成一个环curBoy = first;  //让curBoy指向第一个小孩} else {curBoy.setNext(boy);boy.setNext(first);curBoy = boy;}}}

遍历环形链表

1.先让一个辅助变量 curBoy 指向 first 节点

2.然后通过一个 while 循环遍历该环形链表即可,当 curBoy.next == first 时结束

//遍历当前环形链表public void showBoy() {//判断链表是否为空if (first == null) {System.out.println("链表为空");return;}//因为first不能动,因此我们使用辅助指针完成遍历Boy curBoy = first;while (true) {System.out.printf("小孩的编号为%d\n", curBoy.getNo());if (curBoy.getNext() == first) {break;}curBoy = curBoy.getNext();  //让curBoy后移}}

根据用户输入,生产一个小孩出圈的顺序

1.需要创建一个辅助指针 helper ,事先应该指向环形链表的最后这个节点

2.在报数前,先让 first 和 helper 移动 k-1 次

3.当小孩报数时,让 first 和 helper 指针同时移动 m-1 次

4.这时就可以将 first 指向的小孩节点出圈

first = first.next;

helper.next = first

原来 first 指向的节点就没有任何引用,就会被回收

//根据用户输入,计算小孩出圈顺序public void  countBoy(int startNo, int countNum, int nums) {//先对数据进行校验if (first == null || startNo < 1 || startNo > nums) {System.out.println("输入的参数有误,请重新输入");return;}//创建一个辅助指针,帮助完成小孩出圈Boy helper = first;//需要创建一个辅助指针 helper ,事先应该指向环形链表的最后这个节点while(true) {if (helper.getNext() == first) {break;}helper = helper.getNext();}//小孩报数之前,让 first 和 helper 指针移动 k-1 次for (int j = 0; j < startNo - 1; j++) {first = first.getNext();helper = helper.getNext();}//当小孩报数时,让 first 和 helper 指针同时移动 m-1 次,然后出圈//这里是一个循环操作,直到圈中只有一个节点while (true) {if (helper == first) {  //说明圈中只有一个节点break;}//让 first 和 helper 指针同时移动 countNum - 1for (int j = 0; j < countNum - 1; j++) {first = first.getNext();helper = helper.getNext();}//这时 first 指向的节点就是要出圈的小孩节点System.out.printf("小孩%d出圈\n", first.getNo());//这时将 first 指向的小孩节点出圈first = first.getNext();helper.setNext(first);}System.out.printf("最后留在圈中的小孩编号%d\n", first.getNo());}

Josephu 问题的解决以及测试

public class Josephu {public static void main(String[] args) {//测试一把,看看构建环形链表和遍历是否okCircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();circleSingleLinkedList.addBoy(5);circleSingleLinkedList.showBoy();System.out.println();//测试一把小孩出圈是否正确circleSingleLinkedList.countBoy(1,2,5);System.out.println();}
}//创建一个环形的单向链表
class CircleSingleLinkedList {//创建一个first节点,当前没有编号private Boy first = new Boy(-1);//添加节点,构建成一个环形链表public void addBoy(int nums) {  //nums代表添加的节点的个数//nums 做一个数据校验if (nums < 1) {System.out.println("nums的值不正确");return;}Boy curBoy = null;  //辅助指针,帮助创建环形链表//使用for循环创建一个环形链表for (int i = 1; i <= nums; i++) {//根据编号,创建节点Boy boy  = new Boy(i);//如果是第一个小孩if (i == 1) {first = boy;first.setNext(first);  //构成一个环curBoy = first;  //让curBoy指向第一个小孩} else {curBoy.setNext(boy);boy.setNext(first);curBoy = boy;}}}//遍历当前环形链表public void showBoy() {//判断链表是否为空if (first == null) {System.out.println("链表为空");return;}//因为first不能动,因此我们使用辅助指针完成遍历Boy curBoy = first;while (true) {System.out.printf("小孩的编号为%d\n", curBoy.getNo());if (curBoy.getNext() == first) {break;}curBoy = curBoy.getNext();  //让curBoy后移}}//根据用户输入,计算小孩出圈顺序public void  countBoy(int startNo, int countNum, int nums) {//先对数据进行校验if (first == null || startNo < 1 || startNo > nums) {System.out.println("输入的参数有误,请重新输入");return;}//创建一个辅助指针,帮助完成小孩出圈Boy helper = first;//需要创建一个辅助指针 helper ,事先应该指向环形链表的最后这个节点while(true) {if (helper.getNext() == first) {break;}helper = helper.getNext();}//小孩报数之前,让 first 和 helper 指针移动 k-1 次for (int j = 0; j < startNo - 1; j++) {first = first.getNext();helper = helper.getNext();}//当小孩报数时,让 first 和 helper 指针同时移动 m-1 次,然后出圈//这里是一个循环操作,直到圈中只有一个节点while (true) {if (helper == first) {  //说明圈中只有一个节点break;}//让 first 和 helper 指针同时移动 countNum - 1for (int j = 0; j < countNum - 1; j++) {first = first.getNext();helper = helper.getNext();}//这时 first 指向的节点就是要出圈的小孩节点System.out.printf("小孩%d出圈\n", first.getNo());//这时将 first 指向的小孩节点出圈first = first.getNext();helper.setNext(first);}System.out.printf("最后留在圈中的小孩编号%d\n", first.getNo());}
}//创建一个Boy类,表示一个节点
class Boy{private int no;  //编号private Boy next;  //指向下一节点,默认为nullpublic Boy(int no) {this.no = no;}public int getNo() {return no;}public void setNo(int no) {this.no = no;}public Boy getNext() {return next;}public void setNext(Boy next) {this.next = next;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/50784.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FPGA开发——状态机的使用

一、概述 我们在使用FPGA进行开发的过程当中&#xff0c;实现一个东西用得最多的实现方法就是状态机的实现方法&#xff0c;用一句话总结就是万物皆可状态机&#xff0c;这和我们在学习Linux时常说的在Linux中万物都是文件差不多&#xff0c;这里就主要就是突出状态机的应用范…

技术实践—微前端技术应用

微前端是一种新兴的前端架构模式&#xff0c;是一种类似于微服务的架构&#xff0c;将微服务的理念应用于浏览器端。其核心理念是将一个大而单一的前端应用拆分为多个小型独立的微应用。这些微应用各自独立&#xff0c;可以由不同团队开发维护&#xff0c;部署&#xff0c;组合…

【调色板软件】免费、开源的调色板软件,焰火十二卷,提供了多种功能来生成一组调和色彩NO.108

本文一共:316 个字,需要阅读:1 分钟,更新时间:2024年7 月27日,部分内容具有时效性,如有失效请留言,阅读量:0 使用平台&#xff1a; Windows/macOS/CentOS/Ubuntu 由于我不是很懂&#xff0c;有需要的人自己摸索吧 资源来源于网络&#xff0c;免费分享仅供学习和测试使用&…

go 并发

一、问题 1.1描述 我想要检测一组url的运行状态&#xff0c;如果ok则返回true&#xff0c;结果返回的结果是空的 func CheckWebsites(wc WebsiteChecker, urls []string) map[string]bool {results : make(map[string]bool)for _, url : range urls {go func() {results[url…

PostgreSQL 中如何重置序列值:将自增 ID 设定为特定值开始

我是从excel中将数据导入&#xff0c;然后再通过sql插入数据&#xff0c;就报错。 需要设置自增ID开始值 1、确定序列名称&#xff1a; 首先&#xff0c;需要找到与的增字段相关的序列名称。假设表名是 my_table 和自增字段是 id&#xff0c;可以使用以下查询来获取序列名称…

C 语言动态链表

线性结构->顺序存储->动态链表 一、理论部分 从起源中理解事物&#xff0c;就是从本质上理解事物。 -杜勒鲁奇 动态链表是通过结点&#xff08;Node&#xff09;的集合来非连续地存储数据&#xff0c;结点之间通过指针相互连接。 动态链表本身就是一种动态分配内存的…

mysql8.0.13限制用户对库表得增删改查权限

-- 如果用户存在删除用户 DROP USER test%; -- 创建test用户并赋密码 CREATE USER test% IDENTIFIED BY 123456; -- 给账号权限&#xff08;查询、修改权限&#xff09; grant select,update on test.user to test% -- 解决mysql8报错:ERROR 1410 (42000): You are not allowe…

读写RDS或RData等不同格式的文件,包括CSV和TXT、Excel的常见文件格式,和SPSS、SAS、Stata、Minitab等统计软件的数据文件

R语言是数据分析和科学计算的强大工具,其丰富的函数和包使得处理各种数据格式变得相对简单。在本文中,我们将详细介绍如何使用R语言的函数命令读取和写入不同格式的文件,包括RDS或RData格式文件、常见的文本文件(如CSV和TXT)、Excel文件,和和SPSS、SAS、Stata、Minitab等…

【深度学习】LLaMA-Factory 大模型微调工具, 大模型GLM-4-9B Chat ,微调与部署 (2)

文章目录 数据准备chat评估模型导出模型部署总结 资料&#xff1a; https://github.com/hiyouga/LLaMA-Factory/blob/main/README_zh.md https://www.53ai.com/news/qianyanjishu/2015.html 代码拉取&#xff1a; git clone https://github.com/hiyouga/LLaMA-Factory.git cd …

万物互联,触手可及“2024南京智慧城市,物联网,大数据展会”

在金秋送爽的11月&#xff0c;南京这座历史悠久而又充满活力的城市&#xff0c;即将迎来一场科技盛宴——2024南京智慧城市、物联网、大数据展会。这不仅是一场技术的集会&#xff0c;更是未来生活蓝图的预览&#xff0c;它汇聚了全球顶尖的科技企业、创新者及行业精英&#xf…

【C++】循环结构-while语句

while 语句的语法格式&#xff1a; while (循环条件) {在满足循环条件下执行的操作} 注意要留有跳出循环的方式&#xff0c;避免死循环 1、不写 whlie (1)&#xff0c;写具体的循环条件 2、写while(1)&#xff0c;用 break 跳出循环 下面是一个实例 #include<iostream…

邮件攻击案例系列三:动态 IP 池爆破员工邮箱钓鱼重要客户

案例描述 2023 年 11 月&#xff0c;某制造业企业员工 Emily 接到海外客户电话&#xff0c;向其核实一封电子邮件的真实性&#xff0c;因为客户认为&#xff0c;该邮件所给出的链接不像是该公司的官网网址。Emily 查看自己的邮箱&#xff0c;并未发现客户所说的邮件。但从客户…

Oracle(26) 什么是区(Extent)?

在Oracle数据库中&#xff0c;区&#xff08;Extent&#xff09;是用于分配和管理存储空间的一个逻辑单元。一个区由一组连续的数据块&#xff08;Data Blocks&#xff09;组成&#xff0c;数据库对象&#xff08;如表、索引等&#xff09;通过分配一个或多个区来存储其数据。区…

数据结构-----对列

前言 Hello, 小伙伴们&#xff0c;你们的作者菌又来了&#xff0c;前不久&#xff0c;我们学习了一种数据结构----栈&#xff0c;他特殊的性质使得他在一些数据管理的问题上被广泛的使用&#xff0c;那今天&#xff0c;我们就来学习另一种十分重要的数据结构--对列。 在开始之…

基于STM32设计的个人健康检测仪(华为云IOT)(191)

基于STM32设计的个人健康检测仪(华为云IOT)(191) 文章目录 一、设计需求1.1 设计需求总结1.2 设计思路【1】整体设计思路【2】整体构架【3】ESP8266模块配置【4】上位机开发思路【5】供电方式1.3 项目开发背景【1】选题的意义【2】可行性分析【3】参考文献【4】课题研究的意义【…

Linux字符设备驱动基本框架

本章我们从 Linux 驱动开发中最基础的字符设备驱动开始&#xff0c;重点学习 Linux 下字符设备驱动开发框架。本章会以一个虚拟的设备为例&#xff0c;讲解如何进行字符设备驱动开发&#xff0c;以及如何编写测试 APP 来测试驱动工作是否正常&#xff0c;为以后的学习打下坚实的…

3. 系统上电启动流程

1. 概述 上电启动&#xff0c;可参考恒玄sdk的指导手册。 注&#xff1a;可以在sdk这里加载自己的入口函数 STEP1&#xff1a; STEP2&#xff1a; STEP3&#xff1a; STEP4&#xff1a;

【日常记录】【插件】多媒体文本化: text-image 可以将文字、图片、视频进行「文本化」

文章目录 1. html基本结构2. 画文字3. 画图片4. 画视频参考地址 1. html基本结构 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-s…

ctfshow web入门 中期测评 web492--web502

web492 <?php include(render/render_class.php); include(render/db_class.php);$action$_GET[action]; if(!isset($action)){header(location:index.php?actionlogin);die(); }if($actioncheck){extract($_GET);if(preg_match(/^[A-Za-z0-9]$/, $username)){$sql &qu…

如何设置postgresql数据库的账户密码

说明&#xff1a;在我的云服务器上&#xff0c;postgres是使用yum的方式安装的&#xff0c;不需要设置postgres账户的密码&#xff0c;本文介绍安装后如何手动设置postgres账户的密码&#xff1b; postgres数据库安装&#xff0c;参考下面这篇文章&#xff1a; PostgreSQL安装…