約瑟夫問題的Java實現

約瑟夫問題,也是被稱爲丟手絹問題。利用C++或者Java的單向環形鏈表能夠較好的解決,但肯定不是最簡單的方法。就僅僅是我在學習Java的過程中的一個小的作業題。

問題的來源,據說著名猶太歷史學家 Josephus有過以下的故事:在羅馬人佔領喬塔帕特後,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下一個重新報數,直到所有人都自殺身亡爲止。然而Josephus 和他的朋友並不想遵從。首先從一個人開始,越過k-2個人(因爲第一個人已經被越過),並殺掉第k個人。接着,再越過k-1個人,並殺掉第k個人。這個過程沿着圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續活着。問題是,一開始要站在什麼地方纔能避免被處決?Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。

具體的要求參見度娘:約瑟夫問題

/**
 * 作者:迷了路的鹿
 * 功能:約瑟夫問題(丟手帕問題)
 * 時間:2018年9月14日 09:17:01
 */

public class Demo4 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		CycLink cyclink = new CycLink();
		int len=41;
		int k=1;
		int m=3;
		cyclink.setLen(len);
		cyclink.creatLink();
		cyclink.show();
		cyclink.setK(k);
		cyclink.setM(m);
		cyclink.playgame();
	}

}
class Node
{
	int no;
	Node nextNode = null;
	//節點的構造函數
	public Node(int no)
	{
		//給一個編號
		this.no = no;
	}
}
//環形鏈表
class CycLink
{
	//先定義一個指向鏈表第一個節點的引用
	//指向第一個節點的引用不能動
	Node firstNode = null;//沒有新開闢空間,它在紙上談兵!!!!
	Node tempNode =null;//跑龍套的選手!!!很重要!!!!(紙上談兵)
	int len = 0;//表示共有多少個節點(Node)
	int k =0;//表示要從第k個節點開始計數
	int m =0;//表示每數到m個節點要被刪除
	//設置鏈表的大小(長度)
	public void setLen(int len)
	{
		this.len = len;
	}
	
	//設置從第k個人開始計數
	public void setK(int k)
	{
		this.k=k;
	}
	
	//設置從第m個人開始計數
		public void setM(int m)
		{
			this.m=m;
		}
	//初始化環形鏈表
	public void creatLink()
	{
		for(int i=1;i<= len ;i++)
		{
			if(i==1)
			{
				//創建第一個節點
				Node ch=new Node(i);//ch可不是紙上談兵,實實在在的開闢了空間
				this.firstNode = ch;//“紙上”的firstNode指向了有實際空間的ch
				this.tempNode = ch;//“紙上”的tempNode指向了有實際空間的ch
			}
			else //其餘節點(不是第一個頭結點)
			{
				if(i==len)//(如果要創建最後一個節點)
				{
					//創建最後一個節點
					Node ch=new Node(i);//創建(實際開闢)最後節點,以第二個爲例
					tempNode.nextNode = ch;//"紙上"的tempNode.nextNode指向2節點
					tempNode = ch;//在“紙上”變更龍套選手
					tempNode.nextNode = this.firstNode;//純粹紙上談兵,龍套(最後節點)的下個節點指回初始節點
				}
				else
				{
					//繼續創建一個節點
					Node ch=new Node(i);//創建(實際開闢)下一個節點,以第二個爲例
					tempNode.nextNode = ch;//"紙上"的tempNode.nextNode指向2節點
					tempNode = ch;//在“紙上”變更龍套選手
				}
			}
		}
	}
	//開始丟手帕遊戲
	public void playgame()
	{
		//1、找到第k個節點
		Node temp1=null;
		Node temp2=null;
		temp1 = firstNode;
		
		for(int i=1; i<k; i++)
		{
			temp1=temp1.nextNode;
		}
		int cn=1;//刪除的順序標誌
		while(len!=1)
		{
		//2、從第1步中找到的k人開始計數,找第m-1個用戶(方便第3步修改其下個節點的指向)
			for(int j=1; j<m-1; j++)
			{
				temp1=temp1.nextNode;
			}
		//3、將第2步中找到的用戶修改其下個節點的指向
			temp2=temp1.nextNode;//temp2就是要被刪去的節點
			System.out.println("第"+cn+"個刪除的節點編號:"+ temp2.no);
			temp1.nextNode=temp2.nextNode;
			temp1 = temp1.nextNode;
			cn++;
			len--;
		}
		//4、顯示最後剩下的節點
		System.out.println("最後剩下的節點是:"+temp1.no);
	}
	//打印該循環鏈表
	public void show()
	{
		//定義個龍套選手
		Node temp=this.firstNode;//將“龍套”選手的“帽子”扣在第一個節點上
		System.out.print("初始節點編號: ");
		do {
			System.out.print(temp.no+" ");
			temp = temp.nextNode;
		}while(temp!=this.firstNode);
		System.out.println(" ");
	}
}

 

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