圖解約瑟夫問題

循環鏈解決約瑟夫問題

 詳細解釋,請見代碼註釋

package linkedList;

public class CircleLinkedListDemo
{
	public static void main(String[] args)
	{
		CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
		circleSingleLinkedList.addBoy(25);
		circleSingleLinkedList.show();
		
		circleSingleLinkedList.countBoy(1, 2, 25);
	}
}

//創建一個單向鏈表
class CircleSingleLinkedList
{
	//創建一個first節點,當前沒有編號
	private Boy first = null;
	//添加一個小孩節點,構建成一個環形的鏈表
	public void addBoy(int nums)
	{
		if(nums < 1)
		{
			System.out.println("nums的值不正確~");
			return;
		}
		Boy curBoy = null; 
		//使用for來創建我們的環形鏈表
		for(int i = 1;i <= nums;i++)
		{
			//根據編號來創建
			Boy boy = new Boy(i);
			//如果是第一個小孩
			if(i == 1)
			{
				first = boy;
				first.setNext(first);
				curBoy = first;
			}
			else
			{
				curBoy.setNext(boy);
				boy.setNext(first);
				curBoy = boy;
			}
		}
	}
	
	//遍歷當前環形鏈表
	public void show()
	{
		if(first == null)
		{
			System.out.println("鏈表爲空~");
			return;
		}
		else
		{
			Boy curBoy = first;
			while(true)
			{
				System.out.println("小孩的編號 : " + curBoy.getNo());
				//說明已經遍歷完畢
				if(curBoy.getNext() == first)
				{
					break;
				}
				curBoy = curBoy.getNext();  //curBoy後移
			}

		}
	}
	
	//約瑟夫環算法
	public void countBoy(int startNo, int countNum, int nums)
	{
		//先對數據進行校驗
		if(first == null || startNo < 1 || startNo > nums)
		{
			System.out.println("參數輸入有誤,請重新輸入~");
			return;
		}
		//創建輔助指針,幫助完成小孩出圈
		Boy helper = first;
		//需要一個輔助指針(變量)helper,事先應該指向環形鏈表的最後一個節點
		while(true)
		{
			if(helper.getNext() == first) {
				break;
			}
			helper = helper.getNext();
		}
		//小孩報數之前,先讓first和helper移動startNo-1次
		for(int j=0;j<startNo-1;j++)
		{
			first = first.getNext();
			helper = helper.getNext();
		}
		//當小孩報數時,讓first和helper指針同時後移m-1次,然後出圈
		//這裏是一個循環操作,直到圈中只有一個節點
		while(true)
		{
			if(helper == first)  //圈中只剩一個節點
			{
				break;
			}
			//first、helper後移countNum-1次
			for(int j=0;j<countNum-1;j++)
			{
				first = first.getNext();
				helper = helper.getNext();
			}
			//這時first指向的節點,即出圈的節點
			System.out.printf("小孩%d出圈\n", first.getNo());
			//first指針後移
			first = first.getNext();
			helper.setNext(first);
		}
		System.out.println("最後留在圈中的小孩編號: " + first.getNo());
		
	}
	
}

//創建一個boy類,表示一個節點
class Boy
{
	private int no; //編號
	private Boy next;  //指向下一個節點
	public Boy(int no)
	{
		this.no = no;
	}
	public int getNo()
	{
		return no;
	}
	public void setNo(int no)
	{
		this.no = no;
	}
	public Boy getNext()
	{
		return next;
	}
	public void setNext(Boy next)
	{
		this.next = next;
	}
	
}

 

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