[JAVA练习] Josephu 约瑟夫问题

/**
 * Josephu问题,设编号为 1,2,...,nn个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,
 * 他的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有的人出列为止,由此产生一个出队编号的序列。
 * 来源于韩顺平所著《JAVA从入门到精通》Created by william on 15-10-13.
 */
public class Demo121 {

    public static void main(String [] args){
       CycLink cyclink = new CycLink();
       cyclink.setLen(35);//链表长度
        cyclink.createLink();//初始化单向循环链表
        cyclink.show();//打印这个循环链表
        cyclink.setK(5);//从第几个小孩开始数
        cyclink.setM(12);//数几下
        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(){
        System.out.println("开始游戏,出圈顺序为:");
        Child temp = this.firstChild;
        //1,先找到开始数数的小孩
        for(int i = 1; i<k;i++){
            temp=temp.nextChild;
        }
        while(this.len!=1){
            //2,m下,数完毕之后temp就指向要出圈的小孩
            for(int j =1;j<m;j++){
                temp=temp.nextChild;
            }
            System.out.print(temp.no+"  ");
            //找到要出圈的前一个小孩,while循环最多执行一圈,执行完while循环之后,temp2就指向要出圈的前一个小孩。
            Child temp2 = temp;
            while (temp2.nextChild != temp){
                temp2=temp2.nextChild;
            }
            //3,将数到m的小孩退出圈,把退出圈的前后两个小孩连起来
            temp2.nextChild=temp.nextChild;
            //temp指向下一个开始数数的小孩
            temp = temp.nextChild;
            this.len--;
        }
        //最后一个小孩,在this.len = 1的时候
        System.out.println(temp.no);
        System.out.println("最后出圈的小孩:"+temp.no);
    }
    //初始化单向环形链表
    public void createLink(){
        for(int i = 1; i<=len; i++){
            Child ch=new Child(i);
            if(i==1){
                //创建第一个小孩
                this.firstChild = ch;
                this.temp = ch;
            }else if(len==i){//创建最后一个小孩
                temp.nextChild=ch;
                temp=ch;
                temp.nextChild=this.firstChild;
            }else{
                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);
        System.out.println();
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值