Josephu问题

Josephu问题(丢手帕问题)

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

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

1.小孩子类

//小孩子
class Child{
	int num;//编号
	Child nextChild=null;//引用类型,指向下一个小孩
	public Child(int num){
//		给一个编号
		this.num=num;
	}
}

2.构造环形链表

//构造环形链表
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;
			}
			System.out.println("出圈的小孩编号:"+temp2.nextChild.num);
//			3.将数到m的小孩,退出圈
			temp2.nextChild=temp.nextChild;
//			让temp指向下一个数数的小孩
			temp=temp.nextChild;
			this.len--;
		}
		System.out.println("最后出圈的小孩:"+temp.num);
	}
	
//	初始化环形链表
	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.println(temp.num+"");
			temp=temp.nextChild;
		}while(temp!=this.firstChild);
	}
}

3.主函数

public class LianBiaoTest {
	public static void main(String[] args) {
		CycLink cyclink=new CycLink();
		cyclink.setLen(5);//链表长度
		cyclink.createLink();//创建链表
		cyclink.setK(1);//从第几个开始数,从第二个小孩开始数
		cyclink.setM(3);//数几下
		cyclink.show();
		cyclink.play();
	}
}

4.运行结果


5.原理图




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值