【算法】单向环形链表解决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://xiahunao.cn/news/3269413.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

使用Dependency Walker和Process Explorer排查瑞芯微工具软件RKPQTool.exe启动报错的问题

目录 1、问题说明 2、使用Dependency Walker查看工具程序的库依赖关系 3、在可以运行的电脑上使用Process Explorer查看依赖的msvcr120.dll和msvcp120.dll库的路径 4、C/C++运行时库介绍 5、可以下载安装VC_redist.x86.exe或VC_redist.x64.exe解决系统库缺失问题 C++软件异…

Radon(拉当) 变换:超详细讲解(附MATLAB,Python 代码)

Radon 变换 Radon 变换是数学上用于函数或图像的一种积分变换&#xff0c;广泛应用于图像处理领域&#xff0c;尤其是在计算机断层成像 (CT) 中。本文档将详细介绍 Radon 变换的数学含义及其在图像处理中的应用。 数学定义 Radon 变换的数学定义是将二维函数 f ( x , y ) f…

vue 开发环境配置

1. nvm 安装 在 github上下载 最新的 nvm 包 https://github.com/coreybutler/nvm-windows/releases或者在 csdn 上下载&#xff08;从github上迁移&#xff0c;方便下载&#xff09;https://download.csdn.net/download/u011171506/89585197 下载后不用修改任何配置&#x…

提取视频中的文字如何提取?分享4种简单提取方法

在短视频时代&#xff0c;视频已成为信息传播的重要载体。然而&#xff0c;面对海量的视频资源&#xff0c;如何高效提取其中的文字信息&#xff0c;成为许多人关注的焦点&#xff0c;因为快速提取出视频中的文字可以帮助我们整理、编辑文本信息&#xff0c;下面给大家分享4种简…

构建现代化农业产业服务平台的系统架构

随着全球农业产业的发展和技术的进步&#xff0c;农业生产管理面临着越来越复杂的挑战和机遇。建立一个现代化的农业产业服务平台系统架构&#xff0c;不仅能够提高农业生产效率和管理水平&#xff0c;还能促进农民收入增长和可持续发展。本文将探讨如何设计和实施这样一个系统…

1.1 线性表顺序结构的定义及实现

1. 顺序表定义 把线性表的结点按逻辑顺序依次存放在一组地址连续的存储单元里。用这种方法存储的线性表简称顺序表。 2.顺序表特点 1&#xff09;线性表的逻辑顺序与物理顺序一致&#xff1b; 2&#xff09;数据元素之间的关系是以元素在计算机内“物理位置相邻”来体现。设有…

将手机作为服务器运行docker服务

前言 目前手机的配置并不低&#xff0c;即使是2019年生产的一加七Pro&#xff0c;配置也有12256&#xff0c;CPU是骁龙855&#xff0c;作为服务器运行着配置绰绰有余了&#xff0c;二手的价格现在是400左右也能接受。相对于是自带ups电源的便携低耗docker服务器&#xff0c;还…

分布式事务和2阶段提交

在当今世界&#xff0c;数据正在以惊人的速度增长。单台计算机的存储容量是有限的&#xff0c;因此需要将数据分布在多台机器或数据库上&#xff0c;这种技术被称为分布式技术。 互联网大厂中很多系统都在采用微服务架构。在这种架构中&#xff0c;每个微服务都管理自己的数据…

NXP i.MX 6系列处理器加入“产品长期供货计划”

近期&#xff0c;NXP&#xff08;恩智浦半导体&#xff09;的i.MX 6系列处理器已加入其“产品长期供货计划”&#xff0c;不同型号处理器的生命周期得到了10~15年的延长&#xff0c;确保了长期稳定的供货与维护。 &#xff08;NXP产品长期供货计划的目的&#xff0c;是给客户的…

pycharm关闭项目时,页面卡住了,怎么办?

问题 在关闭pycharm时&#xff0c;有时会遇到卡在退出进度条的界面&#xff0c;很讨厌&#xff0c;那我们要怎么办才能退出呢&#xff1f; 说明&#xff1a;本篇文章不是从根源上解决这个问题&#xff0c;无法避免这种情况。 解决方法 方法一&#xff1a; 在卡住时&#xf…

Redis 7.x 系列【27】集群原理之通信机制

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 概述2 节点和节点2.1 集群拓扑2.2 集群总线协议2.3 流言协议2.4 心跳机制2.5 节点握…

【推研小灶】复旦与南大之间:一次独特的计算机保研之旅

写在前面 上午10点填完志愿等待复试通知&#xff0c;利用这段时间记录一下我简短的夏令营和预推免。今年变为线下之后&#xff0c;部分学校的入营情况、考核方式有明显变化。加上CS方向保研名额总体变多&#xff0c;形势有点小乱&#xff0c;甚至填报系统都在9.29中秋节当天&a…

Python如何获取终端尺寸?

os.get_terminal_size()&#xff0c;无差别获取当前终端长宽&#xff0c;让你为所欲为。 (笔记模板由python脚本于2024年07月27日 08:30:53创建&#xff0c;本篇笔记适合喜欢钻研的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Fre…

【Python系列】Parquet 数据处理与合并:高效数据操作实践

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

unity2D游戏开发08脚本化对象

创建Scriptable Object 在scripts文件夹下创建一个名为Sriptable Objects的文件夹,然后在文件夹里面创建一个名为Item的脚本 using System.Collections; using System.Collections.Generic; using UnityEngine;//[CreateAssetMenu] 是一个属性(Attribute),用于告诉Unity编…

非UI设计师勿入,英文B端界面的确有可取之处.

作为中文的UI设计师&#xff0c;可以从英文B端界面中汲取设计灵感的几种方法&#xff1a; 观察布局和结构&#xff1a; 注意英文B端界面的布局和结构&#xff0c;包括导航栏、侧边栏、内容区域等。观察它们的排列方式、比例和空白间隙的运用&#xff0c;可以借鉴到自己的设计中…

GeoHash原理介绍以及在redis中的应用

GeoHash将二维信息编码成了一个一维信息。降维后有三个好处&#xff1a; 编码后数据长度变短&#xff0c;利于节省存储。利于使用前缀检索当分割的足够细致,能够快速的对双方距离进行快速查询 GeoHash是一种地址编码方法。他能够把二维的空间经纬度数据编码成一个字符串。 1…

十一、【Python】基础教程-【Python全掌握】六大基础数据类型:布尔类型的终极指南

目录 一、基础类型“布尔型”处理方法 1. 直接赋值和使用 2. 布尔值的逻辑运算 3. 条件语句中的布尔值 4. 布尔值转换 5. 短路逻辑 6. 在循环和迭代中的使用 一、基础类型“布尔型”处理方法 在Python中&#xff0c;布尔类型是一种基本的数据类型&#xff0c;用于表示逻…

3DMAX一键藤球建模插件RattanBall使用方法

3DMAX一键藤球建模插件RattanBall使用教程 3DMAX藤球建模插件RattanBall&#xff0c;一键创建藤球模型&#xff0c;可以设置藤球大小、嵌套层数等&#xff0c;简单实用&#xff0c;一键生成&#xff01; 【适用版本】 3dMax2018.2及更高版本 【安装方法】 3DMAX一键藤球建模插…