约瑟夫环问题(丢手帕游戏)Java 链表实现

约瑟夫环(丢手帕游戏)Java 链表实现

 

       已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。

  例如:n = 9, k = 1, m = 5

  【解答】

  出局人的顺序为5, 1, 7, 4, 3, 6, 9, 2, 8。

Tip:以下为单链表实现,处理出局结点时效率不高,可以考虑用循环链表实现,大家有兴趣自己尝试一下。

 

 

/*
 * 作者:winHan
 * 日期:2011.4.5
 * 功能:(丢手帕问题)Joseph环问题(链表实现)
 */
package com.lin;

public class Joseph
{

 public static void main(String[] args)
 {

  System.out.println(“【约瑟夫环数数问题(丢手帕问题)】”);
  CycLink cyclink=new CycLink();
  cyclink.setLen(5);    //玩游戏的人数
  cyclink.createLink();//创建链表
  cyclink.setK(2);    //2号开始
  cyclink.setM(2);   //数两下 ,数到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;//temp作浮标
 int len=0;//共有几个人
 int k=0;//数数开始的编号
 int m=0;//数m下
 
////////////////////////////////////////////////1
 public void setLen(int len)//设置链表大小
 {

  this.len=len;//共有几个人玩游戏
  System.out.println(“参加人数:”+this.len+”人”);

 }
 
////////////////////////////////////////////////2

 public void setK(int k)//设置开始从第几个人数数
 {

  this.k=k;
  System.out.println(“开始数数的人的编号:”+this.k+”号”);
 }
 
////////////////////////////////////////////////3

 public void setM(int m)//设置数到几才退出
 {

  this.m=m;
  System.out.println(“规则:数到”+this.m+”退出”);

 }
 
////////////////////////////////////////////////4

 public void play()//开始玩游戏
 {

  Child temp=this.firstChild;
  //1.找到开始数数的人编号k
  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 pre_Temp=temp;//创建一个临时浮标
 
  while(pre_Temp.nextChild!=temp)
  {
   pre_Temp=pre_Temp.nextChild;
  }
  //3.数到m的退出圈
  pre_Temp.nextChild=temp.nextChild;
  //继续遍历
  temp=temp.nextChild;
 
  this.len–;//出去一个,环形链表长度减一
  }
  //输出最后一个结点
  System.out.println(“/n游戏最后出圈小孩的编号为:”+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;         //temp游标向前走一步
          }
       }
    }
 
    }

//*******************************************************四

 //打印该环形链表
 public void show()
 {
 
  //使用一个浮标遍历
  Child temp=this.firstChild;
  System.out.print(“编号并输出单环形链表–>”);
  do{
  
   System.out.print(“编号”+temp.no+”  “);
   temp=temp.nextChild;//浮标后移
  
  }while(temp!=this.firstChild);
 }
 
 } 

    原文作者:约瑟夫环问题
    原文地址: https://blog.csdn.net/allisen/article/details/6315330
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞