java环形链表_数据结构和算法(四)Java实现环形链表
1. 數據結構和算法(四)Java實現環形鏈表
1.1 約瑟夫問題
約瑟夫問題:公元66年,約瑟夫不情愿地參與領導了猶太同胞反抗羅馬統治的起義,后來起義失敗,他和一些寧死不降的起義者被困于一個山洞之中。羅馬將軍韋斯巴薌(Vespasian)派人來勸降,他主張投降,其余的人不答應,并以死相逼。最后,約瑟夫提議,與其死在自己的手上,不如死在彼此的手上。因此他便將游戲規則告知眾人:N個人圍成一圈,從第一個人開始報數,報到m的人被殺,剩下的人繼續從1開始報數,報到m的人繼續被殺;如此往復,直到剩下最后一個人。他就是運用這個游戲規則最終活了下來,被后人稱為約瑟夫環問題。
圖解1:
假設n=6,總共有6個人,k=1,從第一個人開始報數,m=5,每次數五個。
圖解2:
第一次報數:從一號開始,數五個數,1->2->3->4->5,數完五個數,五號被殺死,第一次報數后,剩余人數如
下。
圖解3:
第二次報數: 從被殺死的五號的下一位開始報數,也就是六號,數五個數,6->1->2->3->4,數數完畢,四號被殺死,第二次報數后,剩余人數如下。
圖解4:
第三次報數: 從被殺死的四號的下一位開始報數,同樣是六號,數五個數,6->1->2->3->6,數數完畢,六號被殺死,第三次報數后,剩余人數如下。
圖解5:
第四次報數: 從被殺死的六號的下一位開始報數,也就是一號,數五個數,1->2->3->1->2,數數完畢,二號被殺死,第四次報數后,剩余人數如下。
圖解6:
第五次報數: 從被殺死的二號的下一位開始報數,也就是三號,數五個數,3->1->3->1->3,數數完畢,三號被殺死,只剩下一號,最后活下來的是1號。
1.2 約瑟夫JAVA實現
現實思路:
創建出n個節點的環形鏈表,即n = 5。代表生成5個人。
需要創建兩個變量,分別為first和last分別指向,第一個人和第一個的上一個人。在報數前,先讓first和last分別移動k-1次。
將first指向的人殺死,并打印殺死的人號碼。當前first == last時,說明游戲結束最后一個人活了下來。
數據結構-代碼:
package com.yuanxw.datastructure.chapter4;
/**
* 環形鏈表
*/
public class Person {
// 編號
private int number;
// 下一個報數的人
private Person next;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public Person getNext() {
return next;
}
public void setNext(Person next) {
this.next = next;
}
}
環形鏈表-代碼:
package com.yuanxw.datastructure.chapter4;
/**
* 自定義 環形鏈表
*/
public class CustomCyclicLinkedList {
public Person first = null;
public Person last = null;
private int size = 0;
/**
* 生成人員環形列表
*
* @param n
* @return
*/
public boolean builder(int n) {
if (n < 1) {
throw new RuntimeException("參數n必須大于1。");
}
for (int i = 1; i <= n; i++) {
Person person = new Person();
person.setNumber(i);
if (i == 1) {
first = person;
first.setNext(first);
last = first;
} else {
last.setNext(person);
person.setNext(first);
last = person;
}
}
size = n;
return true;
}
/**
* @param n 從第n個人開始報數
* @param m 每次隔幾個人
* @return
*/
public String kill(int n, int m) {
StringBuilder builder = new StringBuilder();
if (first == null) {
throw new RuntimeException("約瑟夫環中沒有人員,殺人結束!");
}
if (n <= 0 || n > size) {
throw new RuntimeException(String.format("報數開始的位置,必須在1-%s之間!", size));
}
if (m <= 0 || m > size) {
throw new RuntimeException(String.format("約瑟夫環隔數,必須在1-%s之間!", size));
}
// 設置從位置n做為起點進行:報數
for (int i = 0; i < n-1; i++) {
first = first.getNext();
last = last.getNext();
}
while (true){
// first == last 說明只剩下一個人了
if(first == last){
break;
}
// 移動到 m-1的位置。自已本身也需要報數。所以m-1
for (int i = 0; i < m-1; i++) {
first = first.getNext();
last = last.getNext();
}
builder.append(first.getNumber()).append("->");
// 直接殺死移動后first位置
first = first.getNext();
last.setNext(first);
}
return builder.substring(0,builder.length()-2);
}
/**
* 獲得 幸存者
* @return
*/
public int getSurvivor(){
return first.getNumber();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
Person current = first;
builder.append("[");
do {
builder.append(current.getNumber()).append(",");
current = current.getNext();
} while (current != first);
builder.deleteCharAt(builder.length() - 1);
builder.append("]");
return builder.toString();
}
}
測試部分-代碼
package com.yuanxw.datastructure.chapter4;
public class JosephusProblem {
public static void main(String[] args) {
CustomCyclicLinkedList customCyclicLinkedList = new CustomCyclicLinkedList();
customCyclicLinkedList.builder(6);
System.out.println("列出約瑟夫環列表:" + customCyclicLinkedList);
System.out.println("殺人的順序:" + customCyclicLinkedList.kill(1,5));
System.out.println("最后幸存者是:" + customCyclicLinkedList.getSurvivor());
}
}
執行結果:
列出約瑟夫環列表:[1,2,3,4,5,6]
殺人的順序:5->4->6->2->3
最后幸存者是:1
– 以上為《數據結構和算法(四)Java實現環形鏈表》,如有不當之處請指出,我后續逐步完善更正,大家共同提高。謝謝大家對我的關注。
——厚積薄發(yuanxw)
總結
以上是生活随笔為你收集整理的java环形链表_数据结构和算法(四)Java实现环形链表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: XSL-FO 简介
- 下一篇: java 反射 构造方法_Java反射之