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

一、约瑟夫环问题

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

二、解决思路

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

三、实现代码

1.需要的数据结构

节点

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;
    }
    @Override
    public String toString() {
        return "Boy{" +
                "no=" + no +
                '}';
    }
}

单向环形链表

class CircleList{

    private Boy first = null;

    /**
     *
     * @param startNo   从第几个小孩开始数
     * @param countNo   每次数几下
     * @param nums 小孩的数量
     */
    public void outOfCircle(int startNo, int countNo,int nums){
        if (first==null || startNo<1|| startNo>nums){
            System.out.println("参数输入有误");
            return;
        }
        //创建辅助指针helper即要出圈小孩的前一个节点
        Boy helper = first;
        while (true){
            if (helper.getNext()==first){
                break;//helper已经到达first前的节点
            }
            helper=helper.getNext();
        }
        //移动到开始报数的位置
        for (int i = 0; i 
2.测试代码与结果

测试类

public class Josepfu {

    public static void main(String[] args) {
        CircleList c = new CircleList();
        c.addBoy(5);
        c.outOfCircle(1,2,5);
    }

}

运行结果

单向环形链表解决约瑟夫环(Josephus)问题_第1张图片

你可能感兴趣的:(单向环形链表解决约瑟夫环(Josephus)问题)