单向环形链表应用场景(约瑟夫问题的讲解) java详细讲解

单向环形链表应用场景

约瑟夫问题

在这里插入图片描述
Josephu(约瑟夫、约瑟夫环) 问题

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

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

注:丢手帕问题

解题思路

1、新建一个环线链表,实现链表的增查功能
在这里插入图片描述
2、设计出圈顺序,使用helper作为辅助指针,协助取消指针引用
在这里插入图片描述

代码实现

package com.qf.linkedList;

public class Josefu {
    public static void main(String[] args) {
        CircleLinkedList circleLinkedList=new CircleLinkedList();
        circleLinkedList.add(600);
        circleLinkedList.list();
        circleLinkedList.countBoy(50,20,600);
    }
}

class CircleLinkedList{
    private Boy first=new Boy(-1);

    //添加
    public void add(int num){
        if (num<1){
            System.out.println("输入的数据有误,请重试~~~");
            return;
        }

        Boy curBoy=null;
        for (int i = 1; i <= num; i++) {
            Boy boy=new Boy(i);
            if (i==1){
                //第一个元素成为了队头,并循环
                first=boy;
                first.setNext(first);
                curBoy=first;
            }else{
                boy.setNext(first);
                curBoy.setNext(boy);
                curBoy=boy;
            }
        }
    }

    public void countBoy(int startNo,int countNums,int nums){
        //从startNo开始数数 ,countNums表示的是步长,nums代表的是总共的长度
        if (first==null||startNo<1||countNums>nums){
            System.out.println("输入的数据有误,请重新输入");
        }

        Boy helper=first;
        //1、找到helper的位置,它在first的前一个位置
        while (true){
            if (helper.getNext()==first){
                break;
            }
            helper=helper.getNext();
        }

        //2、让first、helper移动到指定的位置startNo,需要移动startNo-1下
        for (int i=0;i<startNo-1;i++){
            first=first.getNext();
            helper=helper.getNext();
        }

        //3、让小孩报数,移动first和helper的指针,移动countNums-1下
        while (true){
            if (first==helper){
                break;
            }

            for (int j = 0; j < countNums-1; j++) {
                first=first.getNext();
                helper=helper.getNext();
            }
            System.out.println("出圈的编号为:"+first.getNo());
            first = first.getNext();
            helper.setNext(first);

        }

        System.out.println("组后出圈的编号为:"+first.getNo());

    }

    //展示
    public void list(){
        Boy temp=first;
        while (true){
            System.out.println(temp);
            if (temp.getNext()==first){
                break;
            }
            temp=temp.getNext();
        }
    }
}
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 +
                '}';
    }
}

posted @ 2022-08-30 22:41  雾托邦  阅读(71)  评论(0编辑  收藏  举报