环形链表方法解决约瑟夫环问题(JAVA)

2023年5月5日09:06:55

    编号是1,2...n的n个人围坐一圈,编号为k(1<=k<=n)的人从1开始报数,每数到第m个,该人就要离开此圈,它的下一位从1开始报数,数到m出列,这样依次下来,直到圈中所有人出列,最后产生一个出队编号。

目录

一、首先编写一个节点类

二、问题解决思路

三、省略部分对应代码

四、测试代码


一、首先编写一个节点类

public class Node {

    //节点编号(题中人的编号)
    private int id;
    //下一个节点
    private Node next;

    public Node(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

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

    public Node getNext() {
        return next;
    }

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

    @Override
    public String toString() {
        return "Node{" +
                "id=" + id +
                '}';
    }
}

二、问题解决思路

定义一个头节点,不代表题中任何人的编号;

  1. 添加节点;
  2. 查看环形链表中的所有节点;
  3. 根据题意,编写对应代码。

省略代码在第三部分

public class CSLinkedList {

    //头节点,编号不计算
    public Node first = new Node(-1);


    /**
     * 为环形链表添加节点
     * @param num 环形链表的节点个数
     */
    public void addNode(int num){
        //代码
    }


    /**
     * 查看环形链表中所有的节点
     */
    public void showNode(){  
        //代码
    }

    
    /**
     * 约瑟夫环问题
     * @param start 开始报数人的编号:编号为k(1<=k<=n)的人从1开始报数
     * @param count 离开时报的数:每数到第m个,该人就要离开此圈,它的下一位又从1开始报数
     * @param num 圈内人数:编号是1,2...n的n个人围坐一圈
     */
    public void josephCircle(int start, int count, int num){
        //代码
    }

}

三、省略部分对应代码

1、添加节点

    /**
     * 为环形链表添加节点
     * @param num 环形链表的节点个数
     */
    public void addNode(int num){

        //判断num
        if (num < 1){
            System.out.println("不符合要求!");
            return;
        }

        //临时节点
        //添加临时节点,只用更改临时节点指向的节点即可,不需要对环形链表中的节点进行复杂操作
        Node temp = null;

        for (int i = 1; i <= num; i++) {

            //新节点
            //从编号1开始,每循环一次,添加一个新节点
            Node node = new Node(i);

            //判断添加方式
            if (i == 1){
                //第一个节点的添加
                //使编号为1的节点为第一个节点,第一个节点的下一个节点指向自身。
                first = node;
                first.setNext(first);
                //使编号为1的节点指向临时节点,方便以后的添加操作
                temp = first;
            }else {
                //其它节点的添加
                //使临时节点指向新添加的节点
                temp.setNext(node);
                //新添加的节点指向编号为1的节点
                node.setNext(first);
                //使新添加的节点指向临时节点,方便以后操作
                temp = node;
             }
          }
      }

2、查看环形链表中的所有节点

public void showNode(){
        
        if (first.getNext() == null){
            System.out.println("该环形链表为空!");
            return;
        }

        Node node = first;

        while (true){
            //输出每一个节点的编号
            System.out.printf("编号为%d\n",node.getId());

            //节点的下一个节点指向第一个节点时,循环结束
            if(node.getNext() == first){
                break;
            }
            //使节点向后移动
            node = node.getNext();
        }
    }

3、约瑟夫环问题相关代码

public void josephCircle(int start, int count, int num){

         //判断输入是否正确
        if (first == null || start < 1 || count > num){
            System.out.println("输入有错误!");
            return;
        }

        //定义一个结束节点,指向环形链表的最后一个元素
        Node end = first;
        while (end.getNext() != first){
            end = end.getNext();
        }

        //定义一个开始节点
        //开始报数人的编号为2,则first节点移动2-1次
        //first节点移动,结束节点(end)也会移动,移动次数和first节点相同
        for (int i = 0; i < start - 1; i++) {
            first = first.getNext();
            end = end.getNext();
        }

        //出列节点
        //判断节点个数,只有一个节点
        while (end != first){

            //判断出列节点
            //报3的人出列,first是编号为2的人,则移动3-1次,编号为4的人出列,
            for (int i = 0; i < count - 1; i++) {
                first = first.getNext();
                end = end.getNext();
            }

            System.out.printf("编号-%d-节点出环形链表!\n",first.getId());

            first = first.getNext();
            end.setNext(first);
        }
        System.out.printf("编号-%d-节点出环形链表!\n",first.getId());
    }

四、测试代码

public class Test01 {
    public static void main(String[] args) {
        Node node1 = new Node(1);

        CSLinkedList list = new CSLinkedList();

        list.addNode(15);
        list.showNode();
        System.out.println("-------------------");
        list.josephCircle(1,2,15);
    }
}

测试结果如下:


  这是我在书里面看的,书名记不太清,看到就是缘分!

互联网时代,我们即将看到,无创造则无毁灭。


        以上仅供学习参考,可能会有不正确的地方,不过问题应该不大吧,注释是我的想法,表述可能有一点点粗糙,希望可以帮助大家!

  • 作者:二个二个二
  • 原文链接:https://blog.csdn.net/qq_47688745/article/details/125628267
    更新时间:2023年5月5日09:06:55 ,共 2665 字。