单向环形链表-解决Josephu问题

Josephu, 约瑟夫, 约瑟夫环问题
设编号为1~n的n个人围坐到一圈, 约定编号为k(1<=k<=n)的人开始从1开始报数, 数到m的那个人出列, 它的下一位又开始从1开始数, 一次类推, 直到所有人都出列, 得到一个出列的序列.

分析
利用一个不带头结点的环形链表

创建一个不带头结点的环形链表
1.先创建一个节点, 并让frist指针指向该节点, 并形成环形
2.后面每新建一个新的节点, 就把该节点加入到已有的环形链表中去.

遍历环形链表
1.先让一个辅助指针cur指向第一个节点frist,
2.然后使用一个while循环遍历该环形链表,
3.直到当cur.next= frist结束.

解决问题的算法
1.需要创建一个last作为辅助变量, 实现指向最后一个节点, 当last== frist时就可以判断出是剩下最后一个
2.报数之前应先让frist和last同时移动k-1次, 到达一开始的报数位置
3.报数时, 让frist和last同时移动m-1次
4.这时frist指向的节点就可以出圈
5.frist指向下一个再开始报数, 出圈的这个节点没有被引用, 就会被回收

public class Josephu {
    
    
    public static void main(String[] args) {
    
    
        Ringsinglerlinkedlist rsll = new Ringsinglerlinkedlist();
        rsll.create(5);
        rsll.show();
        rsll.showJosephu(1,2,5);
        //rsll.show();
    }
}
class Ringsinglerlinkedlist {
    
    
    private Boy frist = null;


    //传入一个int值, 创建一个int值个数的单向环形链表
    public void create(int count){
    
    
        if (count < 1){
    
    
            System.out.println("节点的个数直少有一个");
            return;
        }
        Boy cur = null;
        for (int i = 1; i <= count; i++){
    
    
            Boy boy = new Boy(i);
            if (i == 1){
    
    
                frist = boy;
                frist.next = frist;
                cur = frist;
            }else{
    
    
                cur.next = boy;
                boy.next = frist;
                cur = boy;
            }
        }
    }
    //遍历单向环形链表并打印
    public void show(){
    
    
        if (frist == null){
    
    
            System.out.println("这个单向环形链表为空");
            return;
        }
        Boy cur = frist;
        while(true){
    
    
            System.out.print(cur);
            if (cur.next == frist){
    
    
                break;
            }
            cur = cur.next;
        }
        System.out.println();
    }
    //约瑟夫问题的出列序列
    public void showJosephu(int k, int m, int count){
    
    
        if (k < 1 || k > count || frist == null){
    
    
            System.out.println("链表是空或者开始位置有误~ ");
        }
        Boy last = frist;
        while(true){
    
    
            if (last.next == frist){
    
    
                break;
            }
            last = last.next;
        }
        for (int i = 1; i<= k-1; i++){
    
    
            frist = frist.next;
            last = last.next;
        }
        while(true){
    
    
            if (last == frist){
    
    
                System.out.println(frist);
                break;
            }
            for (int j = 1; j <= m-1; j++){
    
    
                frist = frist.next;
                last = last.next;
            }
            System.out.println(frist);
            last.next = frist.next;
            frist = frist.next;
        }
    }
}
class Boy{
    
    
    public int number;
    public Boy next;

    public Boy(int number){
    
    
        this.number = number;
    }

    @Override
    public String toString() {
    
    
        return "Boy{" +
                "number=" + number +
                '}';
    }
}

Guess you like

Origin blog.csdn.net/weixin_45032905/article/details/121055497