约瑟夫问题3

简单的问题描述:
一个有五百个小孩拉成的圈子
然后进行报数1 2 3,每次报到三的人退出游戏,并且下一次开始重新报数
求最后留下来的小孩一开始是圈里面的第几个孩子。

这一次的代码是加入了java的面向对象的思想

先进行简单的分析
这个问题里面可以分析出来个类     小孩类    小孩拉成的圈类
先来定义小孩类
package com.fly;
/**
 * 
 * 孩子类
 * 
 * @author 郭鹏飞
 * 
 */
public class Kid {
 /**
  * 类成员变量 id 编号 Kid right 和 left 定义俩个 孩子类的变量
  */
 public int id;
 public Kid right;
 public Kid left;
 /**
  * 定义一个有参数的构造方法 初始化 编号
  */
 public Kid(int id) {
  this.id = id;
 }
}
定义一个小孩拉成的圈类
package com.fly;
/**
 * 
 * 孩子们围成的圆的类
 * 
 * @author 郭鹏飞
 * 
 */
public class Circle {
 /**
  * 定义成员变量 count 孩子的数量 frist last 定义俩个孩子类 记录圆的开头和结束
  */
 public int count = 0;
 public Kid first, last;
 /**
  * 
  * @param count
  *            定义一个有参数的构造函数 实现count的初始化和添加孩子
  */
//有多少个小孩就添加多少个小孩
 public Circle(int count) {
  for (int i = 0; i < count; i++)
   addKid();
 }
 /**
  * 定义一个添加孩子的函数 新添加的孩子从最后一个和第一个之间插入 核心部分 一个双向回环链表的实现
  */
 public void addKid() {
  Kid k = new Kid(this.count);
//核心部分   其实是实现了一个双向回环链表表
//判断如果一开始一个小孩也没有   那么新添加的小孩既是这个圈的第一个也是最后一个   
//并且 这个小孩的 左边是这个小孩自己 右边还是这个小孩自己
  if (this.count == 0) {
   this.first = k;    
   this.last = k;
   k.left = k;
   k.right = k;
  } 
//如果一开始就有小孩了   那么新添加的小孩插入在最后一个小孩和第一个小孩自己中间
 else {
   this.last.right = k;//所以最后一个小孩的右边是新添加的小孩
   k.left = this.last;//这个小孩的左边是最后的那个小孩
   k.right = this.first;//这个小孩的右边是第一个小孩
   this.first.left = k;//第一个小孩的左边是新添加的小孩
   this.last = k;//最后把新添加的小孩变成最后一个小孩
  }
  this.count++;//小孩的人数加一
 }
 /**
  * 定义一个有参数的删除孩子的函数
  * 
  * @param k
  *            核心部分 一个双向回环链表的实现
  */
 public void deleteKid(Kid k) {
//如果没有小孩  输出:没有数据可以删除!!!   然后返回
  if (this.count == 0) {
   System.out.println("没有数据可以删除!!!");
   return;
  }
//否则判断是不是只有一个小孩   如果是你们删除以后  就没有小孩了     
 else if (this.count == 1) {
   this.first = this.last = null;//没有小孩存在了   所以给第一个和最后一个都赋值为空
  }
//如果不是只有一个小孩 
 else {
   k.left.right = k.right;//删除小孩的左边的小孩的右边是这个小孩的右边的小孩
   k.right.left = k.left;//删除小孩的右边的小孩的左边是这个小孩的左边的小孩
//判断删除的小孩是不是第一个    
   if (k == this.first) {
    this.first = k.right;//如果是  就把现在这个小孩的右边的小孩改为第一个
   }
//判断删除的小孩是不是最后一个  
 else if (k == this.last) {
    this.last = k.left;//如果是   就把现在这个 小孩的左边的小孩改为最后一个
   }
  }
  this.count--;//最后圈里面的小孩人数减一
 }
}
 最后是一个测试类
 import com.fly.Circle;
import com.fly.Kid;
/**
 * 测试类
 * 
 * @author 郭鹏飞
 * 
 */
public class KidQuit {
 public static void main(String[] args) {
  Circle circle = new Circle(500);//new一个500个小孩围成的圈
  int kidNumber = 0;//记录报数的值
  Kid k = circle.first;
  while (circle.count > 1) {
   kidNumber++;
   if (kidNumber == 3) {
    kidNumber = 0;
    circle.deleteKid(k);
   }
   k = k.right;
  }
  System.out.println(circle.first.id + 1);
 }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值