欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

约瑟夫问题

程序员文章站 2022-09-24 19:57:09
问题描述Josephu(约瑟夫、约瑟夫环) 问题 Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。举个例子n = 5 , 即有5个人k = 1, 从第一个人开始报数m = 2, 数2下经过一次出圈后第二次出圈第三次出圈第四次出圈所以最终的出.....

问题描述

Josephu(约瑟夫、约瑟夫环)  问题 Josephu  问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类

推,直到所有人出列为止,由此产生一个出队编号的序列。

举个例子

n = 5 , 即有5个人

k = 1, 从第一个人开始报数

m = 2, 数2下

约瑟夫问题

经过一次出圈后

约瑟夫问题

第二次出圈

约瑟夫问题

第三次出圈

约瑟夫问题

第四次出圈

约瑟夫问题

所以最终的出圈顺序 2->4->1->5->3

以上方法是使用单向循环链表来完成的,下面看代码展示

创建一个孩子类,每个孩子对象表示一个节点

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

创建单向循环链表

并且创建添加孩子和显示的方法

class CircleSingleLinkedList{
    private Boy first = null;

    public CircleSingleLinkedList(){}

    /**
     * 添加指定的节点
     * @param nums
     */
    public void add(int nums){
        if(nums < 1){
            System.out.println("输入的数据不合法~~");
            return;
        }
        Boy curBoy = null;
        for (int i = 1; i < nums + 1; i++) {
            Boy boy = new Boy(i);
            if(i == 1){
                first = boy;
                curBoy = first;
                boy.setNext(first);
            }else{
                curBoy.setNext(boy);
                boy.setNext(first);
                curBoy = boy;
            }
        }
    }

    public void showBoy(){
        if (first == null){
            System.out.println("链表为空~~");
            return;
        }
        //因为first不能动,所以创建一个辅助指针
        Boy curBoy = first;
        while(true){
            System.out.println("小孩的编号是" + 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("输入的数据有误~~~");
            return;
        }
        //创建辅助指针,指向first指针的前一位
        Boy helper = first;
        while(helper.getNext() != first ){
            helper = helper.getNext();
        }
        //根据开始小孩的编号,是first指针指向开始小孩
        for (int i = 0; i < startNo - 1; i++) {
            first = first.getNext();
            helper = helper.getNext();
        }
        //开始报数出队
        while(first.getNext() != first){
            //报数
            for (int i = 0; i < countNum - 1; i++) {
                first = first.getNext();
                helper = helper.getNext();
            }
            //出队
            System.out.println("小孩" + first.getNo() + "出圈~~");
            helper.setNext(first.getNext());
            first = first.getNext();
        }
        System.out.println("最后出圈的小孩编号" + first.getNo());
    }

 

本文地址:https://blog.csdn.net/qq_45796208/article/details/109901904

相关标签: java 数据结构