约瑟夫问题的环形链表实现[Java]

news2025/1/17 0:57:20

⭐作者介绍:大二本科网络工程专业在读,持续学习Java,努力输出优质文章
⭐作者主页:@逐梦苍穹
⭐如果觉得文章写的不错,欢迎点个关注一键三连😉有写的不好的地方也欢迎指正,一同进步😁

约瑟夫问题

  • 1、背景介绍
  • 2、问题
  • 3、实现过程
  • 4、全部代码

1、背景介绍

  约瑟夫问题(Josephus Problem)是一个古老而有趣的数学问题,源自于犹太历史学家弗拉维奥·约瑟夫斯(Flavius Josephus)。问题的描述如下:
  在古代,约瑟夫斯是一个被罗马占领的犹太人城市的叛乱者。为了避免被捕,他与一群同伴藏身于一个山洞中。但是,当他们被罗马军队发现并围困在山洞里时,他们必须决定是被俘还是选择集体自杀。
  为了做出决定,约瑟夫斯提出了一种方法来确定哪些人将被选中。他让所有人站成一个圆圈,并从一个人开始,按照一定的规则逐个数数。每数到第 m 个人时,该人将被杀掉,然后从下一个人开始重新数数。这个过程一直进行下去,直到只剩下最后一个人。
  约瑟夫问题的关键是确定起始位置和数数的规则。通常起始位置用 K 表示,数数规则用 M 表示,即每数到第 M 个人时,该人被杀掉。问题的目标是确定最后剩下的人的位置。
  约瑟夫问题可以用数学公式来解决,也可以通过模拟环形链表的方式来求解。无论使用哪种方法,解决约瑟夫问题都需要一定的算法思想和数学推导。
  约瑟夫问题的应用非常广泛,涉及到计算机科学、数学、密码学等领域。解决约瑟夫问题的算法思想也可以应用于任务调度、资源分配等实际问题中。

2、问题

Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。

3、实现过程

在环形链表的基础上进行修改,得到JosephusCircularLinkedList。改动地方如下:
在这里插入图片描述

同时,增加了一个方法countOrder。这是实现约瑟夫问题的主要方法,详细注释版本如下:
在这里插入图片描述

对该方法的解析:
  该方法根据用户输入的参数,计算出小孩出圈的顺序。首先进行参数校验,确保输入的参数合法。然后创建一个辅助指针helper,用于辅助完成小孩出圈的操作。通过遍历找到环形链表的最后一个节点,并将helper指向最后一个小孩节点。
  接下来,根据起始位置start,将firstNode和helper指针分别移动(start - 1)次,使它们指向起始位置的小孩节点。
  然后,通过循环操作,每次让firstNode和helper指针同时移动(countNum - 1)次,表示小孩报数。当helper和firstNode指向同一个节点时,说明圈中只剩下一个节点,循环结束。
  在循环过程中,每次移动完成后,firstNode指向的节点即为要出圈的小孩节点,输出其编号。
  最后,将firstNode指向的小孩节点出圈,即将其从链表中移除,并更新helper的指向。循环结束后,输出最后留在圈中的小孩的编号。

这段代码实现了约瑟夫问题的解决方案,根据起始位置和报数规则,依次输出出圈的小孩编号,直到最后只剩下一个小孩。

4、全部代码

package linkedList.circularLinkedList.Josephu;

import linkedList.circularLinkedList.Node;

/**
 * @author 逐梦苍穹
 * @date 2023/5/22 14:48
 */
public class JosephusCircularLinkedList {
    private Node firstNode = null;

    /**
     * 添加
     */
    public void add(int studentsNums) {
        // nums 做一个数据校验
        if (studentsNums < 1) {
            System.out.println("nums的值不正确");
            return;
        }
        Node temp = null; // 辅助指针,帮助构建环形链表
        // 使用for来创建我们的环形链表
        for (int i = 1; i <= studentsNums; i++) {
            // 根据编号,创建小孩节点
            Node node = new Node(i);
            // 如果是第一个小孩
            if (i == 1) {
                firstNode = node;
                firstNode.setNext(firstNode); // 构成环
                temp = firstNode; // temp指向第一个小孩
            } else {
                temp.setNext(node);
                node.setNext(firstNode);
                temp = node;
            }
        }
    }

    /**
     * 根据用户的输入,计算出小孩出圈的顺序
     * @param start 表示从第几个小孩开始数数(K)
     * @param countNum 表示数几下(m)
     * @param InitialNums 表示最初有多少小孩在圈中
     */
    public void countOrder(int start, int countNum, int InitialNums) {
        // 先对数据进行校验
        if (firstNode == null || start < 1 || start > InitialNums) {
            System.out.println("参数输入有误, 请重新输入");
            return;
        }
        // 创建要给辅助指针,帮助完成小孩出圈
        Node helper = firstNode;
        // 需求创建一个辅助指针(变量) helper , 事先应该指向环形链表的最后这个节点
        while (true) {
            if (helper.getNext() == firstNode) { // 说明helper指向最后小孩节点
                break;
            }
            helper = helper.getNext();
        }
        //小孩报数前,先让 first 和  helper 移动 k - 1次
        for(int j = 0; j < start - 1; j++) {
            firstNode = firstNode.getNext();
            helper = helper.getNext();
        }
        //当小孩报数时,让first 和 helper 指针同时 的移动  m  - 1 次, 然后出圈
        //这里是一个循环操作,知道圈中只有一个节点
        while(true) {
            if(helper == firstNode) { //说明圈中只有一个节点
                break;
            }
            //让 first 和 helper 指针同时 的移动 countNum - 1
            for(int j = 0; j < countNum - 1; j++) {
                firstNode = firstNode.getNext();
                helper = helper.getNext();
            }
            //这时first指向的节点,就是要出圈的小孩节点
            System.out.printf("小孩%d出圈\n", firstNode.getId());
            //这时将first指向的小孩节点出圈
            firstNode = firstNode.getNext();
            helper.setNext(firstNode); //

        }
        System.out.printf("最后留在圈中的小孩编号%d \n", firstNode.getId());

    }

    /**
     * 删除
     */
    public void delete(int id) {
        Node temp = this.firstNode;
        if (temp == null) {
            System.out.println("链表空无法删除");
            return;
        }
        while (true) {
            if (temp.getNext() == firstNode) break;
            if (temp.getNext().getId() == id) {
                temp.setNext(temp.getNext().getNext());
                System.out.println("Node{id=" + id + "}:删除成功");
                return;
            }
            temp = temp.getNext();
        }
        System.out.println("无此节点");
    }

    /**
     * 显示
     */
    public void show(){
        if (firstNode == null) {
            System.out.println("环形链表为空无法显示");
            return;
        }
        // 因为firstNode不能动,因此我们仍然使用一个辅助指针完成遍历
        Node temp = firstNode;
        while (true) {
            System.out.println(temp);
            if (temp.getNext() == firstNode) {// 说明已经遍历完毕
                break;
            }
            temp = temp.getNext(); // temp后移
        }
    }
}

在这里插入图片描述

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

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

相关文章

(全网最详细攻略)【Crypto++】在Visual studio2022中运行Cryptopp

文章目录 前言一、Cryptopp是什么&#xff1f;1. Cryptopp&#xff08;CRYPTO&#xff09;官方文档wiki 二、下载Cryptopp2. Crypto下载地址3. 下载PEM包 三、在VS2022中使用Cryptopp库4. 处理crypto源文件5. 在VS2022项目中使用crypto库 四、运行代码后一些关于c的错误总结 前…

单片机--中断实验练习

【1】实验要求&#xff1a; STM32上电LED&#xff08;PB0&#xff09;灯亮 &#xff0c;当检测到按键&#xff08;PA8&#xff09;按下时处理中断事件&#xff0c;变量i 扩展&#xff1a;知识点 响应优先级->在两个中断同时触发时&#xff0c;且这两个中断的优先级相同&a…

SpringBootWeb入门

1. SpringBootWeb快速入门 1.1 需求 需求&#xff1a;基于SpringBoot的方式开发一个web应用&#xff0c;浏览器发起请求/hello后&#xff0c;给浏览器返回字符串 “Hello World ~”。 1.2 开发步骤 第1步&#xff1a;创建SpringBoot工程项目 第2步&#xff1a;定义HelloCon…

chatgpt赋能Python-python_docx_目录

简介 Python是一种非常优秀的编程语言&#xff0c;主要用于数据分析、机器学习、人工智能等领域。在这些领域中&#xff0c;常常需要使用文档处理相关的工具&#xff0c;例如Microsoft Word。在使用Python编程的过程中&#xff0c;文档处理是非常常见的操作&#xff0c;因此Py…

AC规则-1

本文主要参考规范 GPD_Secure Element Access Control_vxxx.pdf OMA 架构 基本定义 GP(GlobalPlatform)定义了一套允许各应用提供方独立且安全地管理其在SE上的应用的安全框架&#xff0c;而AC(Access Control)&#xff0c;顾名思义&#xff0c;是对外部应用进行SE上应用访问…

pyinstaller 打包 ! pyinstaller 打包路径问题!wordcloud打包缺失stopwords文件

wordcloud打包缺失stopwords文件 错误描述 Unhandled exception in script Failed to execute scriptmain due to unhandled exception: (Errno 2] No such file or directory: C:\Users\VADMINI\appDatallLocal\Templ\2\ME186322\wordcloud\stopwords解决办法 找到安装word…

实验室基础操作

一&#xff1a;FZmotion。 1&#xff1a;查看相机是否加入成功。 2&#xff1a;添加蒙版。 3&#xff1a;选择标定杆类型。500mm 4&#xff1a;标定。 5&#xff1a;数据传输。 二&#xff1a;MotionBuilder。 1&#xff1a;所使用插件。 2&#xff1a;fzmotion插件安装。 Mo…

chatgpt赋能Python-python_errno22

Python的errno22错误——引起问题的原因及解决方法 如果你使用过Python编程语言进行过开发&#xff0c;你可能会像其他开发者一样遭遇过errno22错误。这种错误通常会导致程序崩溃或者无法正常运行。在这篇文章里&#xff0c;我们将深入了解errno22错误的原因&#xff0c;并提供…

【数据结构】C--顺序表1.0版本(本文非常适合小白观看,已尽力详解,以及图解也是尽量列举)

目录 0.前言 什么是数据结构&#xff1f; 1.逻辑结构: 1.1线性结构: 1.2非线性结构: (1)集合 (2)树形结构 (3)图形结构或者网状结构 2.存储结构 一.线性表 二.顺序表 顺序表与数组的关系:(非常容易混淆) 1.静态顺序表&#xff1a;使用定长数组存储元素 2.动态顺序表…

MySQL中auto_increment有什么作用?(IT枫斗者)

MySQL中auto_increment有什么作用&#xff1f; 问题来源 很多时候&#xff0c;MySQL语句中会出现【auto_increment】这个词汇&#xff0c;大多数时候&#xff0c;表都是自动生成的&#xff0c;刚开始学习MySQL数据库时会学习到&#xff0c;后来&#xff0c;渐渐地可能会忘记&…

Windows安装VirtualBox教程(图文版)

VirtualBox是一款免费的虚拟化软件&#xff0c;可以在一台计算机上运行多个操作系统。它可以在Windows、Linux、Mac OS X和Solaris等操作系统上运行。VirtualBox支持多种虚拟硬件设备&#xff0c;包括网络适配器、USB控制器、显卡等。用户可以通过VirtualBox创建一个虚拟的计算…

同个前端页面,在手机端和PC端打开,访问到的资源有可能不是同一个

记录项目遇到的问题&#xff0c;问题表现为&#xff1a; 1、用手机端和PC端打开同一个前端页面&#xff0c;通讯到达的后端服务却不是同一个 排查&#xff1a; 1、确认手机端和PC端打开后&#xff0c;实际访问的前端资源并不是同一个 2、手机端配置的socket端口有误&#x…

图片模块封装:Glide高级使用+使用设计模式图片框架封装+Bitmap尺寸压缩和质量压缩+Bitmap加载大图长图

图片模块封装&#xff1a;Glide高级使用使用设计模式图片封装Bitmap尺寸压缩和质量压缩Bitmap加载大图长图 一.如何更换图片框架二.Glide配置1.依赖&#xff1a;2.缓存配置&#xff1a;3.网络配置&#xff1a;glide默认使用httpUrlConnection完成网络请求&#xff0c;可以改成o…

Python学习笔记——《吴恩达Machine Learning》逻辑回归例程

文章目录 逻辑回归和线性回归的区别&#xff1f;正则化逻辑回归逻辑回归中的梯度下降&#xff1a; 模型预测案例解决二分类问题&#xff1a;不同的 λ \lambda λ会产生不同的分类结果: 逻辑回归和线性回归的区别&#xff1f; 逻辑回归可以理解为线性回归的一个plus版&#xf…

架构-软件工程模块-3

系统测试 #mermaid-svg-cpVF4noxB0estLWd {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-cpVF4noxB0estLWd .error-icon{fill:#552222;}#mermaid-svg-cpVF4noxB0estLWd .error-text{fill:#552222;stroke:#552222;}#…

【Python】判断语句 ③ ( if elif else 语句 | 语法简介 | 代码示例 )

文章目录 一、 if elif else 语句语法二、 代码示例 一、 if elif else 语句语法 在开发场景中 , 经常用到 多条件判定 , 初次判定 , 先进行 条件 1 判定 , 如果 条件 1 满足 则执行 条件 1 对应动作 , 如果 条件 1 不满足 , 则 判定 条件 2 是否满足 , 如果 条件 2 满足 则 …

linux操作系统【进阶完整版】

文章目录 基础命令tailvimsystemctl 用户和组/权限su/sudo创建删除ls -lchmodchown 实用操作快捷键软件安装软链接时区与时间date修改时区 ip、主机名网络传输请求端口 进程管理主机状态监控系统资源占用磁盘信息监控网络状态监控 环境变量上传和下载压缩和解压tarzip/unzip 安…

一、尚医通上传医院接口

文章目录 一、上传医院接口1、集成mongodb1.1添加依赖1.2添加配置 2、添加医院基础类2.1 添加model2.2 添加Repository2.3 添加service接口及实现类2.4 添加controller 3、上传医院3.1 接口数据分析3.2 添加service接口3.3 添加repository接口3.4 添加controller接口3.5 添加帮…

chatgpt赋能Python-python_errno2

Python errno2: 深入了解错误代码并解决问题 当你在使用 Python 进行编程时&#xff0c;不可避免地会遇到一些错误。这些错误通常会被分配一个错误代码&#xff0c;也称为errno。errno2是Python中的一个特定错误代码类型。在本文中&#xff0c;我们将深入了解errno2及其在Pyth…

chatgpt赋能Python-python_errno

Python errno: 什么是errno和它在Python中的应用 在Python编程中&#xff0c;errno是一个非常重要的概念&#xff0c;用于表示系统调用或库函数调用返回的错误代码。在本文中&#xff0c;我们将深入探讨errno是什么&#xff0c;如何在Python中使用它&#xff0c;以及一些常见的…