Josephu问题(丢手帕问题)

Josephu问题为:设编号为1,2,...n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。例如当n = 8, m =4, k =3时,出列的顺序依次为6, 2, 7, 4, 3, 5, 1, 8。

解题:用一个不带头结点的循环链表来处理Josephu问题,先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点的人从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束。

//使用单向链表
public class Demo121 {
    public static void main(String[] args) {
        CycLink cyclink=new CycLink();
        cyclink.setLen(5);//链表长度
         cyclink.createLink();
        cyclink.setK(2);//从第几个人开始数
         cyclink.setM(2);//数几下
         cyclink.show();
        cyclink.play();
    }
}

class Child{
    int no;
    Child nextChild=null;
    public Child(int no){
        //给一个编号
        this.no=no;
    }
}

//单向环形链表
class CycLink{
    //先定义一个指向链表第一个小孩的引用
    //指向第一个小孩的引用,不能动
    Child firstChild=null;
    Child temp=null;
    int len=0;//表示共有多少个小孩
    int k=0;
    int m=0;
    //设置m数几下
    public void setM(int m){
        this.m=m;
    }
    //设置环形链表大小
    public void setLen(int len){
        this.len=len;
    }
    //设置从第几个人开始数数
    public void setK(int k){
        this.k=k;
    }
    //开始play
    public void play(){
        Child temp=this.firstChild;
        //1.先找到开始数数的人
        for(int i=1;i<k;i++){
            temp=temp.nextChild;
        }
        while(this.len!=1){
            //2.数m下
            for(int j=1;j<m;j++){
                temp=temp.nextChild;
            }
            //找到要出圈的前一个小孩
            Child temp2=temp;
            while(temp2.nextChild!=temp){
                temp2=temp2.nextChild;
            }
            //3.将数到m的小孩,退出圈
            temp2.nextChild=temp.nextChild;
            //让temp指向下一个数数的小孩
            temp=temp.nextChild;
            this.len--;
        }
        //最后一个小孩
        System.out.println("最后出圈的小孩:"+temp.no);
    }

    //初始化单向环形链表
    public void createLink(){
        for(int i=1;i<=len;i++){
            if(i==1){
                //创建第一个小孩
                Child ch=new Child(i);
                this.firstChild=ch;
                this.temp=ch;
            }else{
                //创建最后一个小孩
                if(i==len){
                    Child ch=new Child(i);
                    temp.nextChild=ch;
                    temp=ch;
                    temp.nextChild=this.firstChild;
                }else{
                    //继续创建小孩
                    Child ch=new Child(i);
                    temp.nextChild=ch;
                    temp=ch;
                }
            }
        }
    }
    //打印该环形链表
    public void show(){
        //定义一个跑龙套
        Child temp=this.firstChild;
        do{
            System.out.print(temp.no+" ");
            temp=temp.nextChild;
        }while(temp!=this.firstChild);
    }
}

Josephu问题(丢手帕问题),布布扣,bubuko.com

时间: 2024-08-05 07:04:59

Josephu问题(丢手帕问题)的相关文章

丢手帕问题

丢手帕问题 传入的参数变量:多少个人 count,第一个开始的位置 start, 每次丢几个 size 传出:最后出列者的编号 public int[] ignoreOne(int[] src, int startIndex, int size){ if(src.length == 1){ return src; }else{ for(int i = 0; i < src.length; i++){ size--; if(size == 0){ ignoreOne(deleteAttr(src,

韩顺平_PHP程序员玩转算法公开课(第一季)01_算法重要性_五子棋算法_汉诺塔_回溯算法_学习笔记_源代码图解_PPT文档整理

文西马龙:http://blog.csdn.net/wenximalong/ 课程说明:算法是程序的灵魂,为什么有些网站能够在高并发,和海量吞吐情况下依然坚如磐石,大家可能会说: 网站使用了服务器集群技术.数据库读写分离和缓存技术(比如memcahced和redis等),那如果我再深入的问一句,这些优化技术又是怎样被那些天才的技术高手设计出来的呢? 我在上大学的时候就在想,究竟是什么让不同的人写出的代码从功能看是一样的,但从运行效率上却有天壤之别, 就拿以前在软件公司工作的实际经历来说吧, 我是

php实现单,双向链表,环形链表解决约瑟夫问题

传智播客PHP学院 韩顺平 PHP程序员玩转算法第一季  http://php.itcast.cn 聊天篇: 数学对我们编程来说,重不重要? 看你站在什么样的层次来说. 如果你应用程序开发,对数学要求不高 但是,如果你开发系统软件,比如(搜索/识别软件[图像,语言识别]/操作系统...)对数学高 建模.大量数学模型. 老师啊啊.我是学C++的.麻烦,谈哈对QT和MFC的看法嘛.前景什么的, 记住 : 打好基础,大有可为! 初中毕业能去传智学习吗? 学习It, 不管是java ,php ,c#,对

java学习笔记——韩顺平视频

第0讲:开山篇 1.  Java se J2se        桌面 Java ee J2ee        网络 Java me J2me        手机 2.  SQL server   Mysql   Oracle 3. 学习软件编程的注意事项 1.高效愉快学习 2.先建立一个整体框架然后细节 3.用什么再学习什么 4.先知道how,再知道why 5.软件编程是一门"做中学"学科,做了才会 6.适当囫囵吞枣 7.琢磨别人怎么做,不是我认为这么做 第1讲  内容介绍.项目演示.

linux简单介绍,helloworld,vi使用,用户管理

linux特点1.免费的.开源的2.支持多线程.多用户的3.安全性好4.对内存和文件管理优越 缺点:操作相对困难 linux最小只需要4m -> 嵌入式开发 我们使用 vm[虚拟机] 虚拟了一个 linux startx 进入图形化界面图形界面注销回到命令行 linux命令 shutdown -h now 立刻进行关机shotdown -r now 重启计算机reboot 重启计算机 su - 登陆时尽量少用root登陆,因为它是系统管理员,最大的权限,避免操作失误,可以利用普通用户登录,登陆后

环形链表---Java

/** * * @author Administrator * 功能:丢手帕问题 */ package com.litao; public class Demo4 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub CycLink cycLink = new CycLink(); cycLink.setLen(9); cycLink.createLin

java的基础学习(1)

在暑假荒废一星期,武汉看海之后.为了面对接下来的广州实习,我又重新温习了java的一些基本特征和进行手打代码.因为之前的学习更多是停留在纸面的理解上,没有实际的代码编辑.这两天学习要点在于对java的继承,重载,方法覆盖,多态以及约瑟夫问题. 重载,具有相同的方法名,但在参数的个数,类型,顺序上至少要有一个不同.返回类型和修饰符可以不同,但如果仅仅是返回类型不同,或仅仅是修饰符不同,是不足以构成方法的重载的. 方法的覆盖,是在父类已有成员方法的基础上,子类可以有对同名成员方法的不同实现,将会使父

约瑟夫问题的java实现

丢手帕问题,又称约瑟夫问题.本人闲来无事试着实现了一下,实现逻辑简单,没有复杂的算法,适合新手参考. //参数step指步进值,步进到几则出列 //参数count指共有几个人 public static int diuShouPa(int step, int count) { //用List模拟一个队列 List<Integer> queue = new ArrayList<Integer>(); for (int i = 1; i <= count; i++) { queu

数据结构复习之链表———约瑟夫问题案例

* 约瑟芬问题,俗称丢手帕问题: * 有n个人围成一圈,从指定的第一个人开始从1依次报数, * 数到m的那个人出列,接着下一个人从1开始接着报数, * 直到最后只剩下一个人出列,问最后出列的是第几个人? 1.单链表解决: 1 /** 2 * 结点类 3 * @author Administrator 4 * @since 2015年8月8日 下午4:10:20 5 * @version 6 * @since JDK 1.6 7 */ 8 class Node{ 9 private int val