单向环形链表介绍以及约瑟夫问题分析

news2025/2/27 1:57:22

❤️一名热爱Java的大一学生,希望与各位大佬共同学习进步❤️

🧑个人主页:@周小末天天开心

各位大佬的点赞👍 收藏⭐ 关注✅,是本人学习的最大动力

感谢!

📕该篇文章收录专栏—数据结构

目录

单向环形链表

约瑟夫问题

创建Boy类,用来存放数据

创建一个单向环形链表类

构建一个单向环形链表

思路

图解

程序

遍历环形链表

思路

图解

程序

根据用户输入,删除节点

思路

图解

程序

编写Joseph类进行演示

查看输出结果


单向环形链表

从判断一个单链表是否存在循环而扩展衍生的问题,有则称之为有环链表问题,也就是经典的约瑟夫问题,也称为约瑟夫环。

如下图所示:

约瑟夫问题

约瑟夫(约瑟夫环,Joseph)问题为:

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

例如;

n = 5,即有5个人

k = 1,从第一个人开始报数

m = 2,一次数2下

提示:

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

创建Boy类,用来存放数据

class Boy {
    private int no;//编号
    private Boy next;//指向下一个节点
    public 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;
    }
}

创建一个单向环形链表类

class CircleSingleLinkedList {

}

构建一个单向环形链表

思路

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

(2)后面每创建一个新的节点,就把该节点加入到已有的环形列表中即可

图解

程序

//创建一个 first 节点,当前没有编号
    private Boy first = null;

    //添加节点,构成一个环形的链表
    public void addBoy(int nums) {
        //nums 表示节点的总个数
        //对 nums 做数据校验
        if(nums < 1) {
            System.out.println("nums的值不符合条件");
            return;
        }
        Boy curBoy = null;//辅助变量,帮助构造环形节点,因为first不能动
        //使用for循环来创建环形链表
        for (int i = 1; i <= nums; i++) {
            //根据编号,创建节点
            Boy boy = new Boy(i);
            //如果是第一个节点
            if(i == 1) {
                first = boy;//让 first 节点指向自己
                first.setNext(first);//构成环
                curBoy = first;//让 curBoy 指向第一个节点
            } else {
                curBoy.setNext(boy);
                boy.setNext(first);
                curBoy = boy;
            }
        }
    }

遍历环形链表

思路

(1)先让一个辅助指针(变量)curBoy,指向 first 节点

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

图解

curBoy = first 时开始

 curBoy.next == first 时结束

程序

//遍历该链表
    public void showBoy() {
        //判断该链表是否为空
        if(first == null) {
            //说明该链表为空
            System.out.println("该链表为空");
            return;
        }
        //因为first指向第一个节点不能动,所以需要辅助指针完成遍历
        Boy curBoy = first;
        while(true) {
            System.out.println("节点的编号为" + curBoy.getNo());
            if(curBoy.getNext() == first) {
                //说明链表已经遍历完毕,
                //因为是环形链表,所以curBoy的下一个节点要与first作比较
                break;
            }
            curBoy = curBoy.getNext();//让curBoy后移一位
        }
    }

根据用户输入,删除节点

思路

(1)需要创建一个辅助指针(变量)helper,事先指向环形链表最后的节点

(2)当节点技术前,先让first 和 helper 移动k - 1次

(3)当节点移动时,让 first 和 helper 指针同时移动m - 1次

(4)这时就可以将 first 指向的节点出圈

1)first = first.next;

2)helper.next = first;

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

图解

程序

/**
     *
     * @param startNo 表示从第几个节点开始计数
     * @param countNum 表示一次数几下
     * @param nums 表示最初有多少个节点在链表中
     */
    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) {
                //说明helper已经指向了最后的一个节点
                break;
            }
            helper = helper.getNext();
        }
        //节点计数之前,先让 first 和 helper 移动 startNo - 1 次
        for (int i = 0; i < startNo - 1; i++) {
            first = first.getNext();
            helper = helper.getNext();
        }
        //当节点计数时,先让 first 和 helper 指针同时移动 countNum - 1 次,然后出圈
        //这是一个循环操作,知道圈中只有一个节点
        while(true) {
            if(helper == first) {//说明圈中只有一个节点
                break;
            }
            //让 first 和 helper 指针同时移动 countNum - 1 次
            for (int i = 0; i < countNum - 1; i++) {
                first = first.getNext();
                helper = helper.getNext();
            }
            //这时 first 指向的节点就是要出圈的节点
            System.out.printf("节点%d出圈\n",first.getNo());
            //这时可以将 first 指向的小孩节点出圈
            first = first.getNext();
            helper.setNext(first);
        }
        System.out.println("最后留在圈中的节点编号为:" + first.getNo());
    }

编写Joseph类进行演示

public class Joseph {
    public static void main(String[] args) {
        //构建环形链表
        CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
        circleSingleLinkedList.addBoy(5);
        circleSingleLinkedList.showBoy();

        //测试节点出圈
        System.out.println("==============");
        circleSingleLinkedList.countBoy(1,2,5);
    }
}

查看输出结果

当节点为 5 个时的输出结果:

当节点为 10 个时的输出结果:

 

 

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

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

相关文章

不敲代码就能搭建个人博客?快解析内网穿透来助力

记得很多年前看到一句话&#xff0c;“博客是一个人的狂欢”。无论是享受搭建的过程&#xff0c;还是享受创作的乐趣&#xff0c;更多时候博客是在取悦自己。那么&#xff0c;在2022年的今天&#xff0c;搭建个人博客还有意义吗&#xff1f;答案是肯定的&#xff0c;当我们在搜…

Day4: 应用篇-1

应用篇-1 环境安装 应用开发交叉编译环境&#xff0c; 【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.7.pdf 章节4.3.1 在 Ubuntu 中创建目录&#xff1a;/usr/local/arm&#xff0c;命令如下&#xff1a; sudo mkdir /usr/local/arm令将交叉编译器复制到/usr/local/arm 中…

Arduino开发实例-DIY分贝测量仪

DIY分贝测量仪 1、应用介绍 分贝计,它通常用于测量声音的强度和水平。 声音响度是用分贝来衡量的。 从飞机到人类耳语的不同发声介质都有一定的声音响度,以分贝表示。 声波是具有来回运动的纵波,给出高音或低音,如图所示: 声音的响度取决于频率或波长或传播所需的时间。…

APK构建过程-命令行编译

官方对APK构建过程的介绍 官方 - 构建流程介绍 典型 Android 应用模块的构建流程&#xff0c;按照以下常规步骤执行&#xff1a; 编译器将您的源代码转换成 DEX 文件&#xff08;Dalvik 可执行文件&#xff0c;其中包括在 Android 设备上运行的字节码&#xff09;&#xff0c;…

【强化学习论文合集】专栏介绍(订阅前必读)

导读&#xff1a;什么是强化学习&#xff1f; 强化学习&#xff08;Reinforcement Learning, RL&#xff09;&#xff0c;又称再励学习、评价学习或增强学习&#xff0c;是机器学习的范式和方法论之一&#xff0c;用于描述和解决智能体&#xff08;agent&#xff09;在与环境的…

AtCoder Beginner Contest 263 G.Erasing Prime Pairs(二分图最大匹配-网络流)

题目 黑板上有n(n<100)个不同的数&#xff0c;第i个数ai(1<ai<1e7)出现了bi(1<1e9)次&#xff0c; 你每次可以选择当前黑板上存在的两个数x、y&#xff0c;满足xy是质数&#xff0c;擦掉这两个数&#xff0c; 求可以擦掉的最大次数 思路来源 AtCoder Beginner…

[LeetCode周赛复盘] 第 321 场周赛20221127

[LeetCode周赛复盘] 第 321 场周赛20221127 一、本周周赛总结二、 [Easy] 6245. 找出中枢整数1. 题目描述2. 思路分析3. 代码实现三、[Medium]6246. 追加字符以获得子序列1. 题目描述2. 思路分析3. 代码实现四、[Medium] 6247. 从链表中移除节点1. 题目描述2. 思路分析3. 代码实…

Docker-compose详解和LNMP搭建实战

目录 一、Docker-compose简介 1.前言 2.概述 二、Docker-compose安装 三、YAML文件格式及编写注意事项 1.简介 2.使用方法 四、Docker Compose 常用命令 五、Docker Compose 配置常用字段 六、Docker-compose搭建LNMP实战 一、Docker-compose简介 1.前言 我们知道使…

深度学习与总结JVM专辑(三):垃圾回收器—G1(图文+代码)

垃圾收集器G1前言概述停顿时间模型内存布局传统内存布局过时了G1实现的几个关键细节问题铺垫知识&#xff1a;跨代引用铺垫知识&#xff1a;记忆集&#xff0c;卡表&#xff0c;卡页铺垫知识&#xff1a;写屏障插眼往下看G1内存模型分区Region卡片Card堆Heap分代模型分代垃圾收…

网站分享:7个非常好用的电子书网站

❤️作者主页&#xff1a;IT技术分享社区 ❤️作者简介&#xff1a;大家好,我是IT技术分享社区的博主&#xff0c;从事C#、Java开发九年&#xff0c;对数据库、 C#、 Java、前端、运维、电脑技巧等经验丰富。 ❤️个人荣誉&#xff1a; 数据库领域优质创作者&#x1f3c6;&…

Steam下载MOD至本地文件夹

Steam下载MOD至本地文件夹1 所需app和web2 具体步骤2.1 安装SteamCMD2.2 登录SteamCMD2.3 打开网页端的Steam并搜索你想要的MOD2.4 点击你需要的MOD&#xff0c;并复制链接2.5 将链接放入 https://steamworkshopdownloader.io/2.6 把下载代码放入SteamCMD由于各种原因&#xff…

OpenVINO--初步学习笔记

英特尔发布的针对AI工作负载的一款部署神器当模型训练结束后&#xff0c;上线部署时&#xff0c;就会遇到各种问题&#xff0c;比如&#xff0c;模型性能是否满足线上要求&#xff0c;模型如何嵌入到原有工程系统&#xff0c;推理线程的并发路数是否满足&#xff0c;这些问题决…

java项目_第164期ssm定西扶贫惠农推介系统-_java毕业设计_计算机毕业设计

java项目_第164期ssm定西扶贫惠农推介系统-_java毕业设计_计算机毕业设计 【源码请到资源专栏下载】 今天分享的项目是《ssm定西扶贫惠农推介系统》 该项目分为2个角色&#xff0c;管理员和用户。 用户可以浏览前台,包含功能有&#xff1a; 首页、扶贫计划、惠农福利、优秀农民…

【C++】vector的介绍和使用

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《吃透西嘎嘎》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;vector 的…

【课设/毕业设计】电力系统潮流计算(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

相控阵天线(九):平面阵列天线综合(不可分离型切比雪夫分布、圆口径泰勒综合、可分离型分布)

目录简介不可分离型分布不可分离型切比雪夫圆口径泰勒综合可分离型分布可分离切比雪夫综合可分离泰勒综合简介 按行、列排列的可分离型矩形平面阵&#xff0c;其阵因子是两个正交排列的直线阵阵因子的乘积。可分离的平面阵方向图在两个主面内是满足预期副瓣电平的&#xff0c;…

SpringMVC学习笔记(一)

目录 一、什么是SpringMVC ? 二、Spring MVC项目的连接(用户 和 程序 的 映射) 三、获取参数的功能的实现 传递较少数量的参数&#xff1a; 通过对象传递大量参数&#xff1a; 获取表单参数&#xff1a; 获取Json对象 上传文件&#xff1a; &#x1f514;一点补充 一、…

家用 NAS 服务器搭建 | 前篇

1、前言 最近一段时间都在折腾家用 NAS 服务器&#xff0c;NAS 系统从最开始选择安装开源的 OMV&#xff08;OpenMediaVault&#xff09;、万由U-NAS&#xff0c;最终决定使用黑群晖。硬件也是一步步从旧笔记本、拆旧笔记本改nas样式、最终也是到万由410机箱。 家庭nas服务器可…

unity rtsp 视频渲染(一)

unity unity 可以说是一个不错的工具&#xff0c;建立三维的场景非常方便&#xff0c;下面我们建立一个三维的场景&#xff0c;并且在三维的场景中和场景外分别建立系统去播放视频。所谓场景内就是在三维中播放视频&#xff0c;场景外就是在三维场景前表面的二维平面中播放视频…

Go-Excelize API源码阅读(三十六)——SetSheetRow、InsertPageBreak

Go-Excelize API源码阅读&#xff08;三十六&#xff09;——SetSheetRow、InsertPageBreak 开源摘星计划&#xff08;WeOpen Star&#xff09; 是由腾源会 2022 年推出的全新项目&#xff0c;旨在为开源人提供成长激励&#xff0c;为开源项目提供成长支持&#xff0c;助力开发…