约瑟夫环算法用面向对象的一种实现
来源:互联网 发布:网络新词及意思和出处 编辑:程序博客网 时间:2024/04/24 17:58
首先介绍下约瑟夫环:
下面就来个实际例子:
500(n)个小孩围成一圈,从第1(k)个开始报数:1,2,3,1,2,3,1,2,3......每次报3(m)的小孩退出.
问最后剩下的那个小孩,在以前500人里是第几个?
这里对应约瑟夫环的变量值分别为:
n=500;k=1;m=3;
下面就用面向对象来模拟这个场景,小孩我们可以看成一个类cass Child{}
小孩有哪些属性呢?
1.报数(小孩当前应该报什么数字),2.位置(小孩一开始所在第几个位置)
理论上只有这两个属性,但是既然是模拟现实场景,那么我们自然而然要考虑到每个小孩的真实处境
小孩围成一个圈,那就说明每一个小孩两边都有小孩,这个隐藏属性不能忽略了.最后我们的小孩类就产生了
// 定义小孩类class Child{public Child(int position){this.position = position;}public int number; // 小孩当前的报数public final int position; // 小孩的初始位置,固定不变的public Child beforeChild; // 小孩前一个孩子public Child nextChild; // 小孩后一个孩子}
有没发现其实这个就是一个Node节点类.
类设计出来了,下面就开始玩游戏.
首先小孩围成一个圈,我们可以初始化500个Child对象,然后分别设置他们的左右两边的孩子
Child[] children = new Child[n];// 初始化小孩子,将孩子相互关联起来// 可以理解为,手拉手围成一个圈// 第一个孩子跟最后一个孩子拉手for (int i = 0; i <n; i++) {children[i] = new Child(i+1);if(i > 0){ // 第二个人开始together(children[i-1],children[i]);}if(i == n-1){ // 最后一个// 关联到第一个together(children[i],children[0]);}}
最后一个孩子自然要跟第一个孩子关联起来.
准备工作做好了,然后开始报数,报3的人退出.这里遇到的问题有:
1.判断当前报3的孩子
2.报3的孩子如何退出
3.接下来的孩子又开始报1
4.如何判断只剩下一个人
第一个问题好办,直接判断number==3即可
第二个问题,让他退出也就是他两边没有小孩了,换句话说就是他左边的小孩跟他右边的小孩相关联起来.
第三个问题,我们让他下面的小孩重新开始报1就可以,currentChild.nextChild.number = 1;
第四个问题,如果只剩下一个人的话,小孩的nextChild属性会指向自己,这个思考下不难理解
解决了上述问题,我们的核心代码也就出来了:
// 取第一个孩子开始报数Child currentChild = children[k-1];currentChild.number = 1; // 第一个孩子当然报1// 循环,一直报数,当剩下1个小孩就停下来while(true){// 如果下一个小孩引用的对象是自己说明只剩下一个人了if(currentChild.nextChild == currentChild){break; // 停止报数}// 如果报数是3,把他的上一个小孩跟他的下一个小孩关联起来// 这意味着他失去关联,退出if(currentChild.number == m){together(currentChild.beforeChild,currentChild.nextChild);// 下一个小孩重新报数1currentChild.nextChild.number = 1;}else if(currentChild.number < m){// 如果不是3,转移到下一个小孩// 下一个小孩报数+1currentChild.nextChild.number = (currentChild.number + 1);}// 轮到下一个小孩currentChild = currentChild.nextChild;}System.out.println("第"+currentChild.position+"个小孩");
// 相互关联,手拉手private static void together(Child before,Child next){before.nextChild = next;next.beforeChild = before;}
到此程序已经设计完毕了,等到循环退出时,我们只需要打印当前小孩的position属性即可.
完整代码:
package test;// 定义小孩类class Child{public Child(int position){this.position = position;}public int number; // 小孩当前的报数public final int position; // 小孩的初始位置,固定不变的public Child beforeChild; // 小孩前一个孩子public Child nextChild; // 小孩后一个孩子}public class Test {public static void main(String[] args) {int n = 500,k = 1,m = 3;Child[] children = new Child[n];// 初始化小孩子,将孩子相互关联起来// 可以理解为,手拉手围成一个圈// 第一个孩子跟最后一个孩子拉手for (int i = 0; i <n; i++) {children[i] = new Child(i+1);if(i > 0){ // 第二个人开始together(children[i-1],children[i]);}if(i == n-1){ // 最后一个// 关联到第一个together(children[i],children[0]);}}// 取第一个孩子开始报数Child currentChild = children[k-1];currentChild.number = 1; // 第一个孩子当然报1// 循环,一直报数,只剩下1个小孩就停下来while(true){// 如果下一个小孩引用的对象是自己说明只剩下一个人了if(currentChild.nextChild == currentChild){break; // 停止报数}// 如果报数是3,把他的上一个小孩跟他的下一个小孩关联起来// 这意味着他失去关联,退出if(currentChild.number == m){together(currentChild.beforeChild,currentChild.nextChild);// 下一个小孩重新报数1currentChild.nextChild.number = 1;}else if(currentChild.number < m){// 如果不是3,转移到下一个小孩// 下一个小孩报数+1currentChild.nextChild.number = (currentChild.number + 1);}// 轮到下一个小孩currentChild = currentChild.nextChild;}System.out.println("第"+currentChild.position+"个小孩"); // 第436个小孩}// 相互关联,手拉手private static void together(Child before,Child next){before.nextChild = next;next.beforeChild = before;}}
- 约瑟夫环算法用面向对象的一种实现
- 实现约瑟夫环的算法
- [面试] 面向对象的约瑟夫环问题的通法 [ C++实现 ] [为夏逸轩师弟作]
- [Java] 数组-04 面向对象的约瑟夫环 (Good!)
- 约瑟夫环实现算法
- 一种面向对象的Java Bean查询方法的实现
- 小算法:约瑟夫环的Java实现
- 算法----约瑟夫环的简易实现
- 约瑟夫环:用java解决的一种办法
- 约瑟夫环的算法
- 约瑟夫(josephus)环算法实现
- 约瑟夫环问题的一种描述
- 约瑟夫环的一种简单解法
- 面向对象及行程一种面向对象的编程思维!
- 约瑟夫环的实现
- 约瑟夫环的实现
- 约瑟夫环的实现
- 约瑟夫环的实现
- hibernate 分页的两种方法
- 计算机视觉资源汇总 - Part IV(期刊会议)
- 提交按钮动画效果(基于SVGi)
- java开源工具:网站开发工具清单
- mount: you must specify the filesystem type
- 约瑟夫环算法用面向对象的一种实现
- 为什么要用Bootstrap
- java lesson1
- Java正则表达式的解释说明
- Android之场景桌面(二)----模拟时钟实现
- knockout总结
- 什么是java序列化,如何实现java序列化?
- 15.3 泛型接口
- DropDownList分级绑定显示数据