简洁明了!Java实现单向环形链表以解决约瑟夫环Josepfu问题

简介: 简洁明了!Java实现单向环形链表以解决约瑟夫环Josepfu问题

文章目录


简单介绍

代码实现


简单介绍


如果把单链表的最后一个节点的指针指向链表头部,而不是指向NULL,那么就构成了一个单向循环链表,通俗讲就是让尾节点指向头结点。


2c5c4eb9337e40deb734352325a2836a.png


单向环形链表应用场景:Josephu(约瑟夫、约瑟夫环)问题:

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


代码实现


节点类


//节点类
class JNode {
    private int id;
    private JNode next;
    public JNode(int id) {
        this.id = id;
    }
    public int getId() {
        return id;
    }
    public JNode getNext() {
        return next;
    }
    public void setNext(JNode next) {
        this.next = next;
    }
}


链表类(包括节点管理和约瑟夫环问题解决)


//链表类
class CircleSingleLinkedList {
    private JNode first = null; //定义第一个节点,未创建时为null
    //添加节点,构建环形链表
    public void add(int num) {
        if (num < 1){
            System.out.println("创建个数不符合规定!");
            return;
        }
        JNode curNode = null; //辅助变量
        for (int i = 1; i <= num; i++) {
            JNode newNode = new JNode(i);
            if (i == 1){ //第一个节点较为特殊
                first = newNode; //真正创建了第一个节点
                first.setNext(first); //形成环状
                curNode = first; //让辅助变量开始作用
            }else { //第二个及其之后节点
                curNode.setNext(newNode); //让当前节点指向新建的节点
                newNode.setNext(first); //让新建的节点指向第一个节点,形成环状
                curNode = newNode; //更新辅助变量
            }
        }
    }
    //遍历链表
    public void list(){
        if (first == null){
            System.out.println("链表为空!");
            return;
        }
        JNode temp = first;
        while (true){
            System.out.printf("取出节点%d\n",temp.getId());
            if (temp.getNext() == first){ //说明已经遍历到最后一个了
                break;
            }
            temp = temp.getNext();
        }
    }
    //根据参数让节点出圈(Josepfu)
    public void josepfu(int startNode,int count,int num){ //startNode为开始的那个节点,count为每次数第几个,num为链表节点个数
        if (first == null || startNode < 1 || count < 1 || startNode > num){
            System.out.println("链表为空或者输入的参数不符合标准!");
            return;
        }
        //让first移动到startNode指定的节点,即移动startNode-1次
        for (int i = 0; i < startNode - 1; i++) {
            first = first.getNext();
        }
        //创建一个辅助变量,让其指向最后一个节点(first前一个)
        JNode helper = first;
        while (helper.getNext() != first){
            helper = helper.getNext();
        }
        //开始按照要求出圈,每次都让helper和first移动count-1次
        while (true){
            if (helper == first){ //圈中只剩下一个节点
                break;
            }
            for (int i = 0; i < count - 1; i++) {
                first = first.getNext();
                helper = helper.getNext();
            }
            //此时first指向的即为要出圈的节点
            System.out.printf("节点%d出圈\n",first.getId());
            //将出圈的节点从链表中移除
            first = first.getNext();
            helper.setNext(first);
        }
        System.out.printf("节点%d为最后一个节点",first.getId());
    }
}


测试类


/**
 * @Author: Yeman
 * @Date: 2021-10-15-22:33
 * @Description:
 */
public class JosepfuTest {
    public static void main(String[] args) {
        CircleSingleLinkedList linkedList = new CircleSingleLinkedList();
        linkedList.add(5);
        linkedList.list();
        System.out.println("===================");
        linkedList.josepfu(1,2,5);
    }
}


相关文章
|
3月前
|
Java
java数据结构,双向链表的实现
文章介绍了双向链表的实现,包括数据结构定义、插入和删除操作的代码实现,以及双向链表的其他操作方法,并提供了完整的Java代码实现。
java数据结构,双向链表的实现
|
2月前
|
存储 安全 Java
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
【用Java学习数据结构系列】探索顺序表和链表的无尽秘密(附带练习唔)pro
28 3
|
2月前
|
存储
【初阶数据结构】深入解析单链表:探索底层逻辑(无头单向非循环链表)(一)
【初阶数据结构】深入解析单链表:探索底层逻辑(无头单向非循环链表)
|
2月前
|
算法 Java
数据结构与算法学习六:单向环形链表应用实例的约瑟夫环问题
这篇文章通过单向环形链表的应用实例,详细讲解了约瑟夫环问题的解决方案,并提供了Java代码实现。
29 0
|
2月前
|
存储 缓存
【初阶数据结构】深入解析单链表:探索底层逻辑(无头单向非循环链表)(二)
【初阶数据结构】深入解析单链表:探索底层逻辑(无头单向非循环链表)
|
4月前
|
存储 Java
|
4月前
|
存储 Java
java实现单链表的创建、增、删、改、查
这篇文章详细介绍了Java中如何实现单链表的创建以及对单链表进行增加、删除、修改、查询等操作的方法,并提供了相应的代码示例。
java实现单链表的创建、增、删、改、查
|
4月前
|
存储 Java 开发者
揭秘!HashMap底层结构大起底:从数组到链表,再到红黑树,Java性能优化的秘密武器!
【8月更文挑战第24天】HashMap是Java集合框架中的核心组件,以其高效的键值对存储和快速访问能力广受开发者欢迎。在JDK 1.8及以后版本中,HashMap采用了数组+链表+红黑树的混合结构,实现了高性能的同时解决了哈希冲突问题。数组作为基石确保了快速定位;链表则用于处理哈希冲突;而当链表长度达到一定阈值时,通过转换为红黑树进一步提升性能。此外,HashMap还具备动态扩容机制,当负载因子超过预设值时自动扩大容量并重新哈希,确保整体性能。通过对HashMap底层结构的深入了解,我们可以更好地利用其优势解决实际开发中的问题。
125 0
|
4月前
|
存储 Java
【Java集合类面试十】、HashMap中的循环链表是如何产生的?
在多线程环境下,HashMap在扩容时如果发生条件竞争,元素的插入顺序可能形成循环链表,导致死循环。
|
4月前
|
存储 Java
java实现双向链表的增删改查
这篇文章展示了如何在Java中实现双向链表的增加、删除、修改和查询操作,并通过代码示例演示了在双向链表中存储和操作学生信息的过程。