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
 *********************/


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