Josephu问题

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

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

1.设计child链表。
包括当前child编号,以及下一个child指向

 int num;
 Child nextChild;
 public Child(int num){
      this.num = num;  //创建构造器,获取当前child编号
}

2.设计玩法

   Child firstChild=null;  //指向第一个玩家,不能修改
   Child nowChild=null;    //当前指针指向的玩家
   int length=0;           //参与游戏人数
   int k=0;                //从谁开始
   int m=0;                //每回合计算数,到m就将玩家踢出局
   public void setM(int m){
         this.m = m;
   }
   public void setLength(int length){
          this.length=length;
   }
   public void setK(int k){
          this.k=k;
   }
   
   public void play(){
       //将指针指向指定第一位玩家
       Child nowChild = this.firstChild;
	   //找到开始玩家
	   for(int i=1;i<k;i++){
	       nowChild=nowChild.nextChild;
	   }
	   
	   //开始计算,每当计算到m时,玩家出局,循环直至最后一人
	   while(this.length!=1){
	       for(int j=1;j<m;j++){
		        nowChild = nowChild.nextChild;
		   }
		   
		   //找到当前指针指向的上一个玩家,修改他的下一位玩家,保持链表链接
		   child preChild=nowChild;
		   while(preChild.nextChild!=nowChild){
		        preChild=preChild.nextChild;
		   }
		   
		   //将数到m的玩家踢出游戏
		   preChild.nextChild=nowChild.nextChild;
		   Syso("出圈的是:"+nowChild.num);
		   
		   //指针指向下一位玩家
		   nowChild=nowChild.nextChild;
		   //由于玩家被踢出,人数-1
		   this.length--;
		}
	//最终玩家
	Syso("最终出圈的是:"+nowChild.num);
   }
   
   //将列表转变成环形链表
   public void createLink(){
       for(int i=1;i<=length;i++){
	        //设置第一个玩家并移动指针
	        if(i==1){
			    Child child = new Child(i);
			    this.firstChild=child;
				nowChild=child;
			}else{
			    //设置最后一个玩家并移动指针
			    if(i==length){
				    Child child = child(i);
					nowChild.nextChild=child;
					nowChild = child;
					nowChild = this.firstChild;
				}else{
				    //循环设置玩家并移动指针
				    Child child =  new Child(i);
					nowChild.nextChild=child;
					nowChild=child;
				}
			}
	   
	   }
   }
   
   //遍历玩家列表
   public void show(){
       Child nowChild = this.firstChild;
	   do{
	        Syso(nowChild.num+" ")
	   }while(nowChild!=this.firstChild);
       Syso();
   }

3.程序入口

.setLength()
.createLink();
.setK()
.setM()
.show()
.play()	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值