JAVA约瑟夫问题(丢手帕问题)

来源:互联网 发布:文章发布系统php源码 编辑:程序博客网 时间:2024/05/15 23:52
package com.eric;/** * 功能 : 约瑟夫问题(丢手帕问题) * N个人围成一圈,才1数 数m个后,该人出列,重下一个继续数,数m个出列,依次循环,知道剩下最后一个人。求该人是的编号~~ * 逻辑不复杂,看了一遍基本就掌握了。 * 有时候玩玩算法,还是挺有趣的~ *  * @author eric<imphp[at]qq[dot]com> * @date2014-07-15 */public class Demo4 {public static void main(String[] args){CycLink cyc = new CycLink();cyc.setLen(5);cyc.createLink();//cyc.showLink();cyc.setStart(2);cyc.setM(2);cyc.play();}}// 孩子class Child {// 每个孩子的编号int no;// 下一个孩子Child nextChild;// 构造函数,创建每个孩子的时候给上编号public Child(int no){this.no = no;}}// 创建环形链表class CycLink {// 指向第一个小孩的引用,不能动Child firstChild;// 游标Child cursor;// 定义一个链表的大小 (共有多少个小孩)int len;// 定义一个起始编号int start;// 定义长度int m;public void setLen(int len){this.len = len;}public void setStart(int start){this.start = start;}public void setM(int m){this.m = m;}// 开始玩游戏public void play(){// 游标小孩Child tmp = this.firstChild;// 定义要出列的小孩的上一个小孩Child tmp2 = null;// 1.找到开始数数的人, 通过数数的人的上一个小孩,找到数数的人for (int i=1; i<this.start; i++) {// tmp就是数数的人tmp = tmp.nextChild;}// System.out.println("数数的小孩为:"+tmp.no);// System.out.println("参与游戏的小朋友总数:"+this.len);// 当圈内孩子大于1个的时候,就一直游戏下去while (this.len != 1) {// 2.数m下,从start小孩数到m下后的那个小孩,也就是要出圈的小孩for (int j = 1; j<this.m; j++) {// 出圈小孩的上一个小孩tmp2 = tmp;// 要出圈的小孩tmp = tmp.nextChild;}// System.out.println("被退出的小孩编号为:"+tmp.no);// 找到要出圈小孩的前一个小孩  可以优化写在第二步// Child tmp2 = tmp;// 相当于又遍历了一遍,找到 出圈小孩的上一个小孩// while (tmp != tmp2.nextChild) {//tmp2 = tmp2.nextChild;// }// System.out.println("出圈小孩的上一个小孩"+tmp2.no);// 4.将出圈小孩退出游戏圈 , 就是将退出圈的小孩的上一个小孩的小一个孩子指向退出圈小孩的下一个小孩即可tmp2.nextChild = tmp.nextChild;tmp = tmp.nextChild;this.len--;}System.out.println("最后的小孩编号为:"+tmp.no);}// 创建一个环形链接public void createLink(){for (int i=1; i<=this.len; i++) {Child ch = new Child(i);// 第一个孩子if (i == 1) {this.firstChild = ch;this.cursor = ch;// 最后一个孩子} else if (i == this.len) {this.cursor.nextChild = ch;this.cursor = ch;this.cursor.nextChild = this.firstChild;// 其他孩子} else {this.cursor.nextChild = ch;this.cursor = ch;}}/* * 逻辑思路比较清晰的写法 *for (int i=1; i<=this.len; i++) {// 如果是第一个小孩if (i == 1) {// 创建一个孩子,赋上编号Child ch = new Child(i);this.firstChild = ch;// 指针指向该对象this.cursor = ch;} else {// 如果是最后一个孩子if (i == this.len) {Child ch = new Child(i);// 上一个孩子的下一个孩子是最后一个孩子啦this.cursor.nextChild = ch;// 设置游标为最后一个孩子this.cursor = ch;// 当为最后一个孩子的时候,那他的下一个孩子自然就是第一个孩子啦this.cursor.nextChild = this.firstChild;} else {// 中间的孩子Child ch = new Child(i);this.cursor.nextChild = ch;this.cursor = ch;}}}*/}// 打印环形链表public void showLink(){// 创建游标Child cursor = this.firstChild;// do while 先执行一次,故将第一个firstChild pass过去了,再次遇到,则为回到了起始do {// 打印每一个孩子System.out.println("编号:"+cursor.no);// 打印完,需要将对象指向到该孩子的下一个孩子上cursor = cursor.nextChild;// while循环知道 cursor 再次等于 firstChild终止} while(cursor != this.firstChild);}}


0 0
原创粉丝点击