:链表 -- 单向环形链表约瑟夫问题(约瑟夫环)

Posted CodeJiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了:链表 -- 单向环形链表约瑟夫问题(约瑟夫环)相关的知识,希望对你有一定的参考价值。

1. 约瑟夫问题(约瑟夫环)

约瑟夫问题(约瑟夫环):

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

2. 单向环形链表介绍

采用一个单项环形链表来处理(可以带表头也可以不带表头),具体使用头结点还是不带头结点,后面会具体分析。

约瑟问题示意图:

  • n=5,即有5个人
  • k=1,从第一个人开始报数
  • m=2,数2下





3. 解决约瑟夫问题分为两个步骤

  1. 第一步:做环形链表
  2. 第二步:解决约瑟夫问题

BoyNode.java

package data_structure;

/**
 * 结点类
 */
public class BoyNode 

    //结点编号
    private int no;

    //指向下一个节点
    private BoyNode next;

    public BoyNode(int no) 
        this.no = no;
    

    public int getNo() 
        return no;
    

    public void setNo(int no) 
        this.no = no;
    

    public BoyNode getNext() 
        return next;
    

    public void setNext(BoyNode next) 
        this.next = next;
    

CircleSingleLinkedList.java

package data_structure;


public class CircleSingleLinkedList 

    private BoyNode first = new BoyNode(-1);

    /**
     * 构建环形链表   5
     */
    public void addBoy(int nums) 
        if (nums < 1) 
            System.out.println("数据不正确");
            return;
        

        BoyNode temp = null;

        for (int i = 1; i <= nums; i++) 

            BoyNode boyNode = new BoyNode(i);

            /*
             * 判断你是否是第一个小孩
             */
            if (i == 1) 
                first = boyNode;
                first.setNext(first);
                temp = first;
             else 
                temp.setNext(boyNode);
                boyNode.setNext(first);
                temp = boyNode;
            

        

    

    /**
     * 查看环形链表中的节点
     */
    public void showBoy() 
        if (first == null) 
            System.out.println("链表为空..");
            return;
        

        BoyNode boyNode = first;
        while (true) 
            System.out.printf("小孩子的编号%d\\n", boyNode.getNo());
            if (boyNode.getNext() == first) 
                break;
            
            boyNode = boyNode.getNext();

        
    

    /**
     * 当调用该方法输入第几个小孩子开始数数,数几次,环形链表中一共几个小孩
     */
    public void countBoy(int startNo, int countNum, int nums) 
        if (first == null || startNo < 1 || startNo > nums) 
            System.out.println("参数输入有错误...");
            return;
        

        /*
         * 定义辅助指针,指向的是环形单链表中的最后一个节点
         */
        BoyNode helper = first;
        while (helper.getNext() != first) 
            helper = helper.getNext();
        
        /*
         * 寻找起始位置,把first定义为起始位置
         */
        for (int j = 0; j < startNo - 1; j++) 
            first = first.getNext();
            helper = helper.getNext();
        
        /*
         * 当小孩进行报数时,数到m的孩子进行出列,让first和helper移动m-1次即可,找到了
         * 出列孩子
         */
        while (helper != first) 
            for (int j = 0; j < countNum - 1; j++) 
                first = first.getNext();
                helper = helper.getNext();
            
            System.out.printf("小孩子%d 出列\\n", first.getNo());
            first = first.getNext();
            helper.setNext(first);
        
        System.out.printf("最后出圈的小孩编号%d\\n", first.getNo());
    

LinkedTest.java

package data_structure;

public class LinkedTest 

    public static void main(String[] args) 
        CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
        circleSingleLinkedList.addBoy(5);
        circleSingleLinkedList.showBoy();
        circleSingleLinkedList.countBoy(1, 2, 5);
    


运行结果:



以上是关于:链表 -- 单向环形链表约瑟夫问题(约瑟夫环)的主要内容,如果未能解决你的问题,请参考以下文章

单向环形链表解决Josephu(约瑟夫)问题

单向环形链表解决Josephu(约瑟夫)问题

Java数据结构之单向环形链表(解决Josephu约瑟夫环问题)

JAVA实现: 使用单链表实现约瑟夫环(约瑟夫问题)

单向环形链表

环形链表介绍和约瑟夫问题