單向環裝鏈表操作以及約瑟夫問題求解

1. 節點構建

//構建節點

class Item{
	private int no;
	private Item next;
	
	public Item(int no) {
		this.no = no;
	}
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public Item getNext() {
		return next;
	}
	public void setNext(Item next) {
		this.next = next;
	}
	@Override
	public String toString() {
		return "item [no=" + no + "]";
	}
}

2、約瑟夫鏈表構建

  • 代碼
//構建josephu鏈表
class JosephuLinkList{
	//創建first指針,用於指向第一個節點
	Item first = null;
	
	//添加nums個節點
	public void add(int nums) {
		//對nums進行校驗
		if(nums < 1) {
			System.out.println("添加個數不正確!");
		}else {
			//輔助指針,用於指向當前的節點
			Item curItem = null;
			for (int i = 1; i <= nums; i++) {
				Item item = new Item(i);
				if(i == 1) {//第一次添加
					first = item;
					item.setNext(item);
					curItem = item;
				}else {
					curItem.setNext(item);
					item.setNext(first);
					curItem = item;
				}
			}
		}
		
	}
	
	//遍歷
	public void list() {
		if(first == null) {
			System.out.println("尚無節點!");
			return;
		}
		Item curItem = first;
		while (true) {
			System.out.printf("打印環裝鏈表數據:item的no:%d\n",curItem.getNo());
			if(curItem.getNext() == first) {
				break;
			}else {
				curItem = curItem.getNext();
			}
		}
		
	}
	/**
	 * 
	 * @param startItem 第幾個開始
	 * @param count 樹幾下
	 * @param nums  一共幾個人
	 */
	public void countItems(int startItem,int count,int nums ) {
		//首先對數字進行校驗
		if(startItem < 1||startItem > nums||nums < 1) {
			System.out.println("輸入格式不正確!");
			return;
		}
		//定義輔助變量,指向環狀鏈表尾部
		Item helper = first;
		while(true) {
			if(helper.getNext() == first) {
				break;
			}
			helper = helper.getNext();
		}
		
		//第幾個開始 firse和helper 一起移動(startItem-1)下
		for(int i = 0; i < startItem-1; i++) {
			first = first.getNext();
			helper = helper.getNext();			
		}
		//開始循環數數並打印
		while(true) {
			if(first == helper) {
				break;
			}
			//數count下 firse和helper 一起移動(count-1)下
			for(int i = 0; i < count-1; i++) {
				first = first.getNext();
				helper = helper.getNext();			
			}
			
			//打印節點數據並刪除節點
			System.out.printf("josephu打印數據:%d\n",first.getNo());
			//並刪除節點
			first = first.getNext();
			helper.setNext(first);	
		}
		//打印最後一個節點
		System.out.printf("josephu打印數據:%d\n",first.getNo());
	}
}
  • 思路
1、首先定義輸入參數:一共幾個同學nums,從第幾個開始startItem,每次數幾下count;
2、定義輔助變量/指針:helper指向尾部,即first指針的前一個節點,作用:用於刪除節點(helper指向待刪除節點的前一個節點)
3、先讓helper和firse指針同時移動(startItem-1)下,到開始同學的位置。
4、開始玩遊戲,讓同學數count下,同時first和helper指針移動(count-1)下,然後打印first指針指向節點的信息,然後刪除first指針指向的節點:
first = first.next;
helper.next = first;
5、first指向的同學繼續玩遊戲,重複第四步驟,直到剩下最後一個同學。

3. 測試

  • 代碼:
public class JosephuLinkListDemo {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JosephuLinkList josephuLinkList = new JosephuLinkList();
		josephuLinkList.add(15);
		josephuLinkList.list();
		
		josephuLinkList.countItems(1,2,15);
	}
}
  • 測試結果:
打印環裝鏈表數據:item的no:1
打印環裝鏈表數據:item的no:2
打印環裝鏈表數據:item的no:3
打印環裝鏈表數據:item的no:4
打印環裝鏈表數據:item的no:5
打印環裝鏈表數據:item的no:6
打印環裝鏈表數據:item的no:7
打印環裝鏈表數據:item的no:8
打印環裝鏈表數據:item的no:9
打印環裝鏈表數據:item的no:10
打印環裝鏈表數據:item的no:11
打印環裝鏈表數據:item的no:12
打印環裝鏈表數據:item的no:13
打印環裝鏈表數據:item的no:14
打印環裝鏈表數據:item的no:15
josephu打印數據:2
josephu打印數據:4
josephu打印數據:6
josephu打印數據:8
josephu打印數據:10
josephu打印數據:12
josephu打印數據:14
josephu打印數據:1
josephu打印數據:5
josephu打印數據:9
josephu打印數據:13
josephu打印數據:3
josephu打印數據:11
josephu打印數據:7
josephu打印數據:15
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章