约瑟夫环问题

本文通过Java语言实现了一个循环链表来解决经典的约瑟夫环问题,具体描述了如何通过面向对象编程来模拟孩子们围成一圈进行游戏的过程,从特定的孩子开始报数,并在报数到指定次数后出圈,最终找出最后剩下的那个孩子。
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);
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值