模拟实现约瑟夫环

约瑟夫环介绍

在这里插入图片描述在这里插入图片描述

添加节点思路分析

在这里插入图片描述
在这里插入图片描述

移出链表思路

1.创建一个helper指针 指向最后一个节点
2.在报数之前让 让helper和first 移动 start-1次 从第几个节点 开始
3.让helper 和first指针 向后移动 countNum-1次
4.出圈 让 first=first.next; helper.next=first;

结合代码查看
在这里插入图片描述

代码实现

package 链表;

/**
 * @author 一介草莽子
 * version 1.0
 */
@SuppressWarnings({
    
    "all"})
public class josepfu {
    
    
    public static void main(String[] args) {
    
    
        JosePfuLinkedList josePfuLinkedList = new JosePfuLinkedList();
        josePfuLinkedList.add(125);
        josePfuLinkedList.Print();
        josePfuLinkedList.RemoveBoy(2,4,125);

    }
}

class JosePfuLinkedList {
    
    
    private Boy first;//创建一个头结点first 即是头结点有是第一个小孩

    /**
     * @param startNum 从那个小孩开始
     * @param countNum 循环几次踢出一个去
     * @param nums     最初小孩的个数
     *   1.创建一个helper指针 指向最后一个节点
     *   2.在报数之前让 让helper和first 移动 start-1次 从第几个节点开始
     *   3.让helper 和first指针 向后移动 countNum-1次
     *   4.出圈 让 first=first.next;   helper.next=first;
     */

    public void RemoveBoy(int startNum, int countNum, int nums) {
    
    
        //判断合法性
        if(startNum<0||countNum<1||first==null||nums<1){
    
    
            throw new RuntimeException("数据不合法");
        }
        //1.创建一个helper指针 指向最后一个节点
        Boy helper=first;
        while (helper.getNext()!=first){
    
    
            helper=helper.getNext();
        }

        //2.在报数之前让 让helper和first 移动 start-1次 从第几个节点开始
        for (int i = 0; i < startNum-1; i++) {
    
    
            helper=helper.getNext();
            first=first.getNext();
        }
        while (true) {
    
    
            if(first==helper){
    
    
                break;//两个指针指向同一个就退出
            }
            //3.让helper 和first指针 向后移动 countNum-1次【也就是喊号了】
            for (int i = 0; i < countNum - 1; i++) {
    
    
                helper = helper.getNext();
                first = first.getNext();
            }

            System.out.printf("出圈的小孩是%d\n",first.getNo());
            //4.出圈 让 first=first.next;   helper.next=first;
            first=first.getNext();
            helper.setNext(first);

        }
        System.out.println("最后小孩是 ="+first.getNo());
    }


    //形成约瑟夫环 nums是该环有几个节点
    public void add(int nums) {
    
    
        if (nums < 1) {
    
    
            throw new RuntimeException("nums不能小于1");
        }
        Boy curBoy = null;
        for (int i = 1; i <= nums; i++) {
    
    
            Boy boy = new Boy(i);

            if (i == 1) {
    
    
                first = boy;
                first.setNext(boy);//第一个自己指向自己
                curBoy = first;
            } else {
    
    
                curBoy.setNext(boy);
                boy.setNext(first);//新的节点在指向下一个
                curBoy = boy;
            }
        }
    }

    //打印环
    public void Print() {
    
    
        if (first == null) {
    
    
            throw new RuntimeException("空链表");
        }
        Boy temp = first;
        while (true) {
    
    

            System.out.printf("[%d] ", temp.getNo());
            if (temp.getNext() == first) {
    
    
                break;//指向了第相同的就退出
            }
            temp = temp.getNext();

        }
        System.out.println();
    }
}

//小孩类
class Boy {
    
    
    private int no;
    private Boy next;

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

    public int getNo() {
    
    
        return no;
    }

    public Boy getNext() {
    
    
        return next;
    }

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

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

猜你喜欢

转载自blog.csdn.net/m0_56398287/article/details/127144744