单项环形链表

单向环形链表应用场景

Josephu(约瑟夫、约瑟夫环) 问题

Josephu 问题为:设编号为 1,2,… n 的 n 个人围坐一圈,约定编号为 k(1<=k<=n)的人从 1 开始报数,数
到 m 的那个人出列,它的下一位又从 1 开始报数,数到 m 的那个人又出列,依次类推,直到所有人出列为止,由
此产生一个出队编号的序列。
在这里插入图片描述
提示:用一个不带头结点的循环链表来处理 Josephu 问题:先构成一个有 n 个结点的单循环链表,然后由 k 结
点起从 1 开始计数,计到 m 时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从 1 开始计数,直
到最后一个结点从链表中删除算法结束。

单向环形链表介绍

在这里插入图片描述

  • 约瑟夫问题-创建环形链表的思路图解

在这里插入图片描述

  • 约瑟夫问题-小孩出圈的思路分析图
    在这里插入图片描述
  • Josephu 问题的代码实现

CircleSingleLinkedNode.java

package com.yg.datastructures.linkedlist;

/**
 * @Description: 环形单项列表模型
 * @Author yg
 * @Date 2021-03-24 16:32
 */
public class CircleSingleLinkedNode {

    private int id;
    private String name;
    private CircleSingleLinkedNode next;

    public CircleSingleLinkedNode() {

    }

    public CircleSingleLinkedNode(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public CircleSingleLinkedNode getNext() {
        return next;
    }

    public void setNext(CircleSingleLinkedNode next) {
        this.next = next;
    }

    @Override
    public String toString() {
        return "CircleSingleLinkedNode{" +
                "id=" + id +
                ", name='" + name + '\'' +

                '}';
    }
}

CircleSingleLinkedList.java

package com.yg.datastructures.linkedlist;

/**
 * @Description: 环形单项列表
 * @Author yg
 * @Date 2021-03-24 16:32
 */
public class CircleSingleLinkedList {

    private CircleSingleLinkedNode first = null;

    /**
     * 初始化 环形链表结构
     *
     * @param nums
     */
    public void initNode(int nums) {
        if (nums <= 0) {
            System.out.println("输入参数小于等于0,请重新输入");
            return;
        }
        CircleSingleLinkedNode curNode = null;

        for (int i = 1; i <= nums; i++) {
            CircleSingleLinkedNode node = new CircleSingleLinkedNode(i, "");
            if (i == 1) {
                first = node;
                first.setNext(first);
                //curnode 向后移动
                curNode = node;
            } else {
                curNode.setNext(node);
                node.setNext(first);
                //curnode 向后移动
                curNode = node;
            }
        }
    }

    public void showNode() {
        if (first == null) {
            System.out.println("环形链表为空");
            return;
        }
        CircleSingleLinkedNode temp = first;
        while (true) {
            System.out.println("环形链表节点:" + temp.getId());

            if (temp.getNext() != first) {
                temp = temp.getNext();
            } else {
                break;
            }
        }
    }

    /**
     * 根据输入 计算出出圈的顺序
     *
     * @param startNo  开始计算的编号
     * @param countNum 计算数
     * @param initNum  初始化多少人
     */
    public void countOut(int startNo, int countNum, int initNum) {
        if (startNo < 0 || countNum < 0 || initNum < 0) {
            System.out.println("入参存在小于零的参数,请重新输入!");
            return;
        }
        if (initNum < 1) {
            System.out.println("初始化人数不能小于1");
            return;
        }
        if (startNo > initNum) {
            System.out.println("起始位置不能大于总人数");
            return;
        }

        //初始化人数
        initNode(initNum);

        CircleSingleLinkedNode temp = first;

        // 需求创建一个辅助指针(变量) temp , 事先应该指向环形链表的最后这个节点
        while (true) {
            // 说明 temp 指向最后小孩节点
            if (temp.getNext() == first) {
                break;
            }
            temp = temp.getNext();
        }

        //设置起始位置 ,移动 startno - 1
        for (int i = 0; i < startNo - 1; i++) {
            first = first.getNext();
            temp = temp.getNext();
        }
        System.out.println("起始位置是temp = " + temp);
        System.out.println("起始位置是first = " + first);

        //开始遍历 出圈
        while (true) {
            if (temp == first) {
                //遍历完了,就剩这一个了
                break;
            }
            //让 first 和 temp 指针同时 的移动 countNum - 1
            for (int i = 0; i < countNum - 1; i++) {
                first = first.getNext();
                temp = temp.getNext();
            }
            ///这时 first 指向的节点,就是要出圈的小孩节点
            System.out.printf("小孩%d 出圈\n", first.getId());

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


}

CircleSingleLinkedListDemo.java

package com.yg.datastructures.linkedlist;

/**
 * @Description: 测试
 * @Author yg
 * @Date 2021-03-24 17:26
 */
public class CircleSingleLinkedListDemo {
    public static void main(String[] args) {
        // 测试一把看看构建环形链表,和遍历是否 ok
        CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
//        // 加入 5 个小孩节点
        circleSingleLinkedList.initNode(5);
        circleSingleLinkedList.showNode();
        //测试一把小孩出圈是否正确 // 2->4->1->5->3
        circleSingleLinkedList.countOut(5, 5, 20);
    }
}

运行结果:

D:\jdk1.8.0_251\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:3863,suspend=y,server=n -javaagent:C:\Users\Administrator\AppData\Local\JetBrains\IntelliJIdea2020.3\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "D:\jdk1.8.0_251\jre\lib\charsets.jar;D:\jdk1.8.0_251\jre\lib\deploy.jar;D:\jdk1.8.0_251\jre\lib\ext\access-bridge-64.jar;D:\jdk1.8.0_251\jre\lib\ext\cldrdata.jar;D:\jdk1.8.0_251\jre\lib\ext\dnsns.jar;D:\jdk1.8.0_251\jre\lib\ext\jaccess.jar;D:\jdk1.8.0_251\jre\lib\ext\jfxrt.jar;D:\jdk1.8.0_251\jre\lib\ext\localedata.jar;D:\jdk1.8.0_251\jre\lib\ext\nashorn.jar;D:\jdk1.8.0_251\jre\lib\ext\sunec.jar;D:\jdk1.8.0_251\jre\lib\ext\sunjce_provider.jar;D:\jdk1.8.0_251\jre\lib\ext\sunmscapi.jar;D:\jdk1.8.0_251\jre\lib\ext\sunpkcs11.jar;D:\jdk1.8.0_251\jre\lib\ext\zipfs.jar;D:\jdk1.8.0_251\jre\lib\javaws.jar;D:\jdk1.8.0_251\jre\lib\jce.jar;D:\jdk1.8.0_251\jre\lib\jfr.jar;D:\jdk1.8.0_251\jre\lib\jfxswt.jar;D:\jdk1.8.0_251\jre\lib\jsse.jar;D:\jdk1.8.0_251\jre\lib\management-agent.jar;D:\jdk1.8.0_251\jre\lib\plugin.jar;D:\jdk1.8.0_251\jre\lib\resources.jar;D:\jdk1.8.0_251\jre\lib\rt.jar;D:\IdeaProjects\datastructures\target\classes;D:\RepMaven\org\springframework\boot\spring-boot-starter-web\2.4.4\spring-boot-starter-web-2.4.4.jar;D:\RepMaven\org\springframework\boot\spring-boot-starter\2.4.4\spring-boot-starter-2.4.4.jar;D:\RepMaven\org\springframework\boot\spring-boot\2.4.4\spring-boot-2.4.4.jar;D:\RepMaven\org\springframework\boot\spring-boot-autoconfigure\2.4.4\spring-boot-autoconfigure-2.4.4.jar;D:\RepMaven\org\springframework\boot\spring-boot-starter-logging\2.4.4\spring-boot-starter-logging-2.4.4.jar;D:\RepMaven\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;D:\RepMaven\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;D:\RepMaven\org\apache\logging\log4j\log4j-to-slf4j\2.13.3\log4j-to-slf4j-2.13.3.jar;D:\RepMaven\org\apache\logging\log4j\log4j-api\2.13.3\log4j-api-2.13.3.jar;D:\RepMaven\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;D:\RepMaven\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;D:\RepMaven\org\yaml\snakeyaml\1.27\snakeyaml-1.27.jar;D:\RepMaven\org\springframework\boot\spring-boot-starter-json\2.4.4\spring-boot-starter-json-2.4.4.jar;D:\RepMaven\com\fasterxml\jackson\core\jackson-databind\2.11.4\jackson-databind-2.11.4.jar;D:\RepMaven\com\fasterxml\jackson\core\jackson-annotations\2.11.4\jackson-annotations-2.11.4.jar;D:\RepMaven\com\fasterxml\jackson\core\jackson-core\2.11.4\jackson-core-2.11.4.jar;D:\RepMaven\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.11.4\jackson-datatype-jdk8-2.11.4.jar;D:\RepMaven\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.11.4\jackson-datatype-jsr310-2.11.4.jar;D:\RepMaven\com\fasterxml\jackson\module\jackson-module-parameter-names\2.11.4\jackson-module-parameter-names-2.11.4.jar;D:\RepMaven\org\springframework\boot\spring-boot-starter-tomcat\2.4.4\spring-boot-starter-tomcat-2.4.4.jar;D:\RepMaven\org\apache\tomcat\embed\tomcat-embed-core\9.0.44\tomcat-embed-core-9.0.44.jar;D:\RepMaven\org\glassfish\jakarta.el\3.0.3\jakarta.el-3.0.3.jar;D:\RepMaven\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.44\tomcat-embed-websocket-9.0.44.jar;D:\RepMaven\org\springframework\spring-web\5.3.5\spring-web-5.3.5.jar;D:\RepMaven\org\springframework\spring-beans\5.3.5\spring-beans-5.3.5.jar;D:\RepMaven\org\springframework\spring-webmvc\5.3.5\spring-webmvc-5.3.5.jar;D:\RepMaven\org\springframework\spring-aop\5.3.5\spring-aop-5.3.5.jar;D:\RepMaven\org\springframework\spring-context\5.3.5\spring-context-5.3.5.jar;D:\RepMaven\org\springframework\spring-expression\5.3.5\spring-expression-5.3.5.jar;D:\RepMaven\mysql\mysql-connector-java\8.0.23\mysql-connector-java-8.0.23.jar;D:\RepMaven\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;D:\RepMaven\org\springframework\spring-core\5.3.5\spring-core-5.3.5.jar;D:\RepMaven\org\springframework\spring-jcl\5.3.5\spring-jcl-5.3.5.jar;D:\JetBrains\IntelliJ IDEA 2020.3\lib\idea_rt.jar" com.yg.datastructures.linkedlist.CircleSingleLinkedListDemo
Connected to the target VM, address: '127.0.0.1:3863', transport: 'socket'
环形链表节点:1
环形链表节点:2
环形链表节点:3
环形链表节点:4
环形链表节点:5
起始位置是temp = CircleSingleLinkedNode{id=4, name=''}
起始位置是first = CircleSingleLinkedNode{id=5, name=''}
小孩9 出圈
小孩14 出圈
小孩19 出圈
小孩4 出圈
小孩10 出圈
小孩16 出圈
小孩2 出圈
小孩8 出圈
小孩17 出圈
小孩5 出圈
小孩13 出圈
小孩3 出圈
小孩15 出圈
小孩7 出圈
小孩1 出圈
小孩20 出圈
小孩6 出圈
小孩12 出圈
小孩18 出圈
最后留在圈中的小孩编号11 
Disconnected from the target VM, address: '127.0.0.1:3863', transport: 'socket'

Process finished with exit code 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值