package com.l2.link;
/*
*
* 约瑟夫环问题,一个经典的算法问题
* ------此为Java语言 的循环链表实现
* 可模拟为孩子做游戏:面向对象编程
* 由len个孩子围成一个首尾相连的圈报数,做游戏
*从第k个孩子开始,从1开始报数,报数报到j的孩子出圈,
*剩下的孩子继续从1开始报数,直到最后一个出圈的孩子。
*对于给定的len,k和j,求出最后剩下的那个孩子.
* 2013-7-20
**/
public class Link2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
CryLink cryclink = new CryLink();//创建一个环形孩子圈
cryclink.setlen(100);//环中有5个孩子
//创建环形链表 原理等价于C语言中的 链表创建过程
cryclink.createlink();
//cryclink.show();//遍历环形链表
cryclink.setl(1);//从第2个孩子数数
cryclink.setl2(9);//数2下
cryclink.play();//开始做游戏
}
}
class Child{
int no;//孩子编号
Child nextChild=null;
public Child(int no){
this.no = no;
}
}
//环形孩子圈
class CryLink{
Child fristChild = null;
//Child nextChild=null;
Child tmp=null;
int len=0;//循环链表长度
int length=0;//记录len最初值
int k;//从第k个小孩开始数
int j; //数j下
public void setlen(int len){
this.len=len;
this.length =len;
}
public void setl(int k){
this.k=k;
}
public void setl2(int j){
this.j=j;
}
//环形圈中的孩子开始玩游戏
public void play(){
Child tmp = this.fristChild;
Child tmp2=null;
//找到第 k 个小孩
for(int i=1;i<k;i++){
tmp = tmp.nextChild;
}
// System.out.println("开始小孩是"+tmp.no);
//数j下
while(this.len!=1){
for(int m=1;m<j;m++){
if(m==j-1){ //找到当前小孩的前一个-------方法一
tmp2 = tmp; //找到当前小孩(编号j)的前一个(编号j-1)tmp2
}
tmp = tmp.nextChild;
}
//System.out.println("当前小孩是"+tmp.no);
/*Child tmp2 = tmp;
while(tmp2.nextChild!=tmp){
tmp2= tmp2.nextChild; //找到当前小孩的前一个--------方法二
//找到当前小孩(编号j)的前一个(编号j-1)tmp2
}
*/
//System.out.println("上一个小孩是"+tmp2.no);
tmp2.nextChild=tmp.nextChild;//链表重新连接
tmp=tmp.nextChild;//游标指向下一个
this.len--;
}
System.out.println("开始:"+this.length+"个小孩"+"从第"+k+"个小孩开始"+"不断数"+j+"下");
System.out.println("最后出圈的小孩是"+tmp.no);
}
//创建环形链表 原理等价于C语言中的 链表创建过程
public void createlink(){
int i;
for(i=1;i<=len;i++)
{
if(i==1)
{
Child ch = new Child(i);
this.fristChild=ch;
this.tmp=ch;
}
else{
if(i==len)
{ Child ch = new Child(i);
tmp.nextChild=ch;
tmp=ch;
tmp.nextChild=this.fristChild;
}
else{
Child ch = new Child(i);
tmp.nextChild = ch;
tmp=ch;
}
}
}
}
public void show(){ //遍历循环链表
Child tmp = this.fristChild;
do{
System.out.println(tmp.no+" 链表节点 ");
tmp=tmp.nextChild;
}while(tmp!=this.fristChild);
}
}