构建环形链表

构建单向的环形链表的思路:
1.先创建第一个节点,让first指向该节点,并形成环形
2.后面当我们每创建一个新的节点,就把该节点,加入到环形链表中即可

package linkedlist;
/*
* 约瑟夫环
* */
public class Josepfu {
    public static void main(String[] args) {
        CircleSingleLinkedList list = new CircleSingleLinkedList();
        list.addBoy(5);
        list.countBoy(2,3,5);
        //list.showBoy();
        System.out.println("--------------------------");

    }
}

//创建一个环形的单向链表
class CircleSingleLinkedList{
    //创建一个first节点,当前先没有编号
    private Boy first = new Boy(-1);

    //添加小孩节点,构成环形链表
    public void addBoy(int nums){
        //进行一个数据校验
        if (nums < 1){
            System.out.println("nums值不正确,nums值应该大于1");
        }
        Boy curBoy = null; //辅助指针,帮助构建环形链表
        //用循环构建环形链表
        for (int i = 1 ; i <= nums ; i++){
            Boy boy = new Boy(i);//根据编号,构建小孩节点

            if (i == 1){ //头结点
                first = boy;
                first.setNext(first);  //构成环形节点
                curBoy = first;         //让curBoy指向first
            }else{
                curBoy.setNext(boy);
                boy.setNext(first);
                curBoy = boy;
            }

        }

    }//添加小孩节点结束


    //遍历环形链表
    public void showBoy(){
        //判断链表是否为空
        if (first == null){
            System.out.println("该链表为空!!!");
            return;
        }

        Boy curBoy = first;//临时变量
        while(true){
            System.out.printf("当前小孩的编号为: %d\n",curBoy.getNo());
            if (curBoy.getNext() == first){
                break;
            }
            curBoy = curBoy.getNext();
        }
    }
    //遍历环形链表结束

    //根据用户输入,计算小孩出圈的顺序
    /**
    * @param startNo 表示从的几个孩子开始数
     * @param countNum 表示数几下
     * @param nums 表示最开始有几个小孩在圈内
    * */
    public void countBoy(int startNo,int countNum, int nums){
        if (first == null || startNo < 1 || startNo > nums){
            System.out.println("您输入的参数有误,请重新输入!");
        }

        //创建辅助指针,帮助完成小孩出圈
        Boy helper = first;
        //helper应事先指向最后一个节点
        while(true){
            if (helper.getNext() == first){
                break;
            }
            helper = helper.getNext();
        }
        //小孩报数前,先让first和helper移动到报数的位置
        for (int i=0; i < startNo-1; i++){
            first = first.getNext();
            helper = helper.getNext();
        }
        //报数,然后出圈,就是让指针移动m-1次
        //当循环链表里面只有一个节点时,出圈结束
        while (true){
            if (first == helper){
                break;
            }
            //移动到出圈的位置
            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.println("最后留在圈中的小孩:"+first.getNo());
    }//小孩出圈结束
}

//创建一个Boy类,表示一个节点
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;
    }
}

遍历环形链表
1.先让一个辅助指针curBoy,指向first节点
2.然后通过一个while循环遍历该环形链表即可。curBoy.next == first结束


版权声明:本文为weixin_45301190原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。