单向环形链表之约瑟夫问题(JAVA实现)

单向环形链表之约瑟夫问题(JAVA实现)

1、约瑟夫问题介绍
--------一堆猴子(小孩)都有编号,编号是1,2,3 …m,这群猴子(m个)按照1-m的顺序围坐一圈,从第1开始数,每数到第N个,该猴子就要离开此圈,这样依次下来,直到圈中只剩下最后一只猴子,求出圈的猴子编号。

2、代码思路
围成一圈,类似环形链表结构。 单向环形链表,即单向链表最后一个节点指向首节点,构成环形。每出圈一个,将其删除。
链表的创建:
(1)先创建第一个节点,给定的first节点=该节点,first节点并指向该节点,辅助节点=first,形成环形。
(2)每创建一个新节点,加入到环形中。(使用辅助节点)。辅助节点.next=新节点,新节点.next=first,辅助节点后移。
链表的遍历:
(1)辅助节点,指向first。
(2)while遍历。终止条件:辅助节点.next=first。
出圈操作:
(1)辅助节点helper放置链表最后。
(2)先定位几号小孩报数。报数M,first和helper移动M-1下
(3)first指向的小孩出圈。first=first.nest;helper.next=first。

3、代码实现

package test.lianbiao;
/**
 * @author shkstart
 * @create 2021-01-07 9:39
 */
public class Joepfu {
    public static void main(String[] args) {
        CorcleSlinkList corcleSlinkList = new CorcleSlinkList();
        corcleSlinkList.add(5);
        corcleSlinkList.list();
        corcleSlinkList.count(1,2,5);
    }
}
class CorcleSlinkList {
    private Boy first = new Boy(0);//first 节点

    public void add(int num) {
        //num>1 先判断,此处省略
        Boy curboy = null;//辅助变量  因为first不能动
        for (int i = 1; i <= num; i++) {
            Boy boy = new Boy(i);
            if (i == 1) {
                first = boy;
                first.setNext(boy);//构成环
                curboy = first;
            }
           else{
                curboy.setNext(boy);
                boy.setNext(first);
                curboy = curboy.getNext();
            }
        }
    }

    public void list(){
        if(first.getNext()==null){
            System.out.println("空");return;
        }
        //first 不能动,辅助变量
        Boy curboy=first;    //指向变量
        while (true){
            System.out.printf("小孩编号%d\n",curboy.getNo());
            if (curboy.getNext() == first){
                break;
            }

            curboy=curboy.getNext();
        }
    }
    
    public void count(int startNo,int cnum,int num){   //从第startNo号小孩数,数cnum个数,有几个小孩
        if (first.getNext() == null || startNo < 1 || startNo > num) {
            System.out.println("参数输入有误, 请重新输入");
            return;
        }

        Boy helper=first;
        while (true){   //helper在链表最后
            if(helper.getNext()==first){
                break;
            }
            helper=helper.getNext();
        }
        for (int j=1;j<startNo;j++){
            first=first.getNext();
            helper=helper.getNext();//定位到第一个数数的人
        }
        while (first.getNext()!=first) {//直到圈中只有一个人
            for (int i =1; i < cnum; i++) {
                first = first.getNext();
                helper = helper.getNext();  //定位到出圈的人
            }
              System.out.println(first.getNo());
                first = first.getNext();
                helper.setNext(first);

        }
        System.out.println(first.getNo());//最后一人也要输出显示
    }
}
class Boy {
    private int no;// 编号
    private Boy next; // 指向下一个节点,默认null

    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;
    }
}

共5人,数到2的人出圈,最后结果为 2 4 1 5 3。

PS:打call尚硅谷!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值