数据结构之单向环形列表解决josef问题

1.定义节点类

   该节点类中只有孩子的编号,以及指向下一个节点的"指针"

 

package com.ebiz.list.josepfu;

/**
 * @author YHj
 * @create 2019-07-17 22:21
 * 表示节点的类
 */
public 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 "我是第" + no + "个Boy";
    }



}

2.定义单向链表类

   需要注意的是,josef问题是头尾相连的,在这也就是最后一个节点需要指向第一个节点,如果只有一个节点,那么该节点需要指向节点本身.

   解决josef问题,关键是理解最后的josef方法.

package com.ebiz.list.josepfu;

/**
 * @author YHj
 * @create 2019-07-17 22:16
 * 环形单项链表
 */
public class SingleCircleList {

        //创建一个first 节点 没有编号也可以为空
        private  Boy firstBoy =new Boy(-1);

        //添加节点,构成环形链表   需要注意的是第一个节点需要指向节点本身
        public  void add(int num){
                if (num < 1 ){
                    System.out.println("编号不正确");
                    return;
                }
                //创建辅助节点
                Boy temp=null;
                //添加节点
                for (int i = 1; i <=num ; i++) {
                    Boy boy = new Boy(i);
                    if (i == 1){ //代表第一个节点
                        firstBoy=boy;
                        firstBoy.setNext(firstBoy);
                        temp=firstBoy;  //辅助接点
                    }else {
                        temp.setNext(boy);
                        boy.setNext(firstBoy);  //这里不能为temp 因为是环形链表,后面逐渐增加的节点的next应该是头节点
                        temp=boy;
                    }
                }
        }
        //遍历环形链表
        public void list( ){
            if (firstBoy.getNo() == -1){
                System.out.println("该环形链表为空!");
                return;
            }
            //定义辅助指针
            Boy temp=firstBoy;
            while (true){
                System.out.println(temp);
                if (temp.getNext().getNo() == 1){
                    break;
                }
                temp=temp.getNext();
            }
        }


        /*
         josepfu问题的实现
         根据用户的输入,生成小孩出圈的顺序
         k:从哪里开始
         m:数几下
         num:玩游戏的小孩的数量
        */
        public void josepfu(int k,int m,int num){
            //数据校验
            if (k>num || k<1 || m<1 || num<1){
                System.out.println("参数输入有误");
            }
            if(firstBoy.getNo() == -1){
                System.out.println("链表节点为空!");
            }
            //创建辅助指针  帮助小孩完成出圈
            Boy temp=firstBoy;
            //循环遍历,将该辅助指针指向最后一个,即firstBoy前一个
            while (true){
                if(temp.getNext() == firstBoy){
                    break;
                }
                temp=temp.getNext();
            }
            // 报数之前.让first 和temp移动到对应位置 在k处报数,让first和temp移动k-1,
            // 移动到开始报数的孩子身上
            for (int i = 1; i <=k-1 ; i++) {
                firstBoy=firstBoy.getNext();
                temp=temp.getNext();
            }
            while (true){
                if (firstBoy == temp){
                    break;
                }
                //开始报数,第k个孩子,即firstBoy当前指向的孩子
                //报m个数,,从第k个孩子本身报数,所以firstBoy移动m-1次,temp也移动m-1次
                for (int i = 1; i <=m-1 ; i++) {
                    firstBoy=firstBoy.getNext();
                    temp=temp.getNext();
                }
                //上面循环结束时,firstBoy指向要出去的孩子
                System.out.printf("小孩%d出圈",firstBoy.getNo());
                //这是将firstBoy指向将要出去的孩子的下一位,并且temp的next指向他
                firstBoy=firstBoy.getNext();
                temp.setNext(firstBoy);
            }
            System.out.printf("最后留在圈中的小孩编号%d",firstBoy.getNo()); //或者temp
        }


}

3. 写一个简单测试类

package com.ebiz.list.josepfu;

/**
 * @author YHj
 * @create 2019-07-18 9:30
 */
public class Test {

    public static void main(String[] args) {

        //创建环形链表
        SingleCircleList circleList = new SingleCircleList();
        //环形链表添加节点
        circleList.add(5);
        //遍历链表
        circleList.list();

        circleList.josepfu(1,2,5);

    }
}

 

有不懂的欢迎留言评论!

 

posted @ 2019-07-22 10:23  就是喜欢大晴天  阅读(397)  评论(0编辑  收藏  举报