Josephu问题-下——实现程序功能

Josephus问题求解

    设有n个人围坐一个圆桌周围,,现从第k人开始报数,数到第m的人出列,

    然后从出列的下一个重新开始报数,数列的第m个人又出列……如此重复,直
    到所有的人全部出列为止。对任意给定的n、k、m,求按出列次序得到的n个
    人员的顺序表。

(这个问题看别人用C以数学算法与递归法写出来,代码不过几行,我这上百行的代码确实有点汗颜)

续:算法优化——在每次数到m-1下时,保存当时那个对象的.nextPeron,就不用再重新去找被删除对象的前一个对象了,这里不再修改了。

import java.util.Scanner;
class Person{
	int no;
	Person nextPerson = null;
	public Person(int no){
		this.no = no;
	}
}
class CycleLink{
	Person firstPerson = null; //指向链表第一个人的引用
	int len; //定义链表长度
	Person temp = null;
	int k = 0;	
	int m = 0;	
	
			//设定链表长度
	public void setLen(int len){
		this.len = len;
	}
			//从第几个人开始数
	public void setK(int k){
		this.k = k;
	}
			//每次数几下
	public void setM(int m){
		this.m = m;
	}
			//创建链表
	public void createLink(){
		for(int i=1; i<=len; i++){
			Person p = new Person(i);
				//环链的第一个对象
			if(i==1){
				this.firstPerson = p;	//将第一个对象的引用存放在firstPerson中
				this.temp = p;	//将第一个对象的引用暂时赋于temp,用于接收下一个对象的引用
			}
				//环链的最后一个对象
			else if(i==len){
				this.temp.nextPerson = p;	//将最后一个对象的引用赋给倒数第二个对象的nextPerson
				temp = p;		//将当前对象(也就是最后一个对象)的引用暂赋给temp
				temp.nextPerson = this.firstPerson;	//将第一个对象的引用赋给最后一个对象的nextPerson
				
			}else{
				this.temp.nextPerson = p;//将当前对象的引用赋给上一个对象的引用变量nextPerson中
				this.temp = p;	//将当前对象的引用暂时赋于temp,用于接收下一个对象的引用
			}
		}
	}
			//打印环形链表
	public void showLink(){
		Person t = firstPerson;	
		do{
			System.out.println(t.no);
			t = t.nextPerson; /*前一个对象的nextPerson存放的下一个对象的引用
							  (因为对象也是引用类型,相当于是引用的引用)*/
		}while(t!=firstPerson);
	}
	public void play(){
		Person temp = this.firstPerson;	//将第一个人这个对象的引用交给temp临时变量
			//找到开始数数的人
		for(int i=1; i<k; i++){		// i<k是为第k个人这个对象的引用保存在前k前一个人这个对象.nextPerson中							
			temp = temp.nextPerson;	//假设k=2时,循环只执行一次,是将第二个人这个对象的引用交给temp
		}
			//数m下,找到出列的人 以下注释只符合上面k=2的情况
		while(this.len!=1){
			for(int i=1; i<m; i++){
				//找到出列的对象
				temp = temp.nextPerson;	/* 这里假设m=3,第一次循temp = 第二个对象的.nextPerson(也就是第三个对象的引用)
											第二次循环时temp = 第三个对象的.nextPerson(也就是第四个对象的引用)
											从k=2人个开始数,数m=3下,第四个人就是出列的对象,逻辑结论正确!*/
			}
			System.out.println("第"+temp.no+"个人出列了!");
				//找到要出列前一个人(对象) 续:可以在数到m-1时那个对象标记一下,可以不
			Person temp2 = temp;
			while(temp2.nextPerson!=temp){
				temp2 = temp2.nextPerson;
			}
				//将数到m的人退出圈,即退出环链
			temp2.nextPerson = temp.nextPerson;	//将出列前一个对象的nextPerson交给出列对象的下一个对象
				//让temp指向下一个数数的人
			temp = temp.nextPerson;
			this.len--;
		}
		System.out.println("最后留下的人是:"+temp.no);
	}
}
public class CycleLinkTest{
	public static void main(String[] args){
		Scanner input = new Scanner(System.in);
		System.out.print("请输入圆桌数数游戏的总人数:");
		CycleLink t = new CycleLink();
		t.setLen(input.nextInt());	//给定环形链表的长度(等同游戏人数)
		t.createLink();	//创建环链
		// t.showLink(); //测试环链是否创建成功
		System.out.print("从第几个人开始数:");
		t.setK(input.nextInt());	
		System.out.print("每次数几下:");
		t.setM(input.nextInt());
		t.play();
	}
 }
 /*********************
请输入圆桌数数游戏的总人数:7
从第几个人开始数:2
每次数几下:3
第4个人出列了!
第7个人出列了!
第3个人出列了!
第1个人出列了!
第6个人出列了!
第2个人出列了!
最后留下的人是:5
 *********************/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章