單向環形連結串列
阿新 • • 發佈:2020-10-10
單向環形連結串列介紹
單向環形連結串列可以理解為單鏈表首尾相連的連結串列.
建立環形連結串列
- 構建一個單向環形連結串列思路
- 先建立第一個節點,讓first指向該節點,並形成環形 first.next = first
- 新增輔助指標curBoy = first 待新增的節點為boy
- 新增節點 curBoy.next = boy;boy.next = first;(成環) curBoy = boy;(指向下一個節點)
- 遍歷
- 先讓一個輔助針織curBoy指向first節點
- 然後通過while迴圈遍歷該環形連結串列即可,結束條件為:curBoy.next == first
josephu問題
設編號為1,2,3......n的n個人圍坐一圈,約定編號為k(1<=k<=n)的人從1開始報數,數到m的那個人出列,他的下一位從1開始報數,數到m的那個人又出列,以此類推,知道所有人出列為止,由此產生一個出隊編號的序列.
-
提示:用一個不帶頭結點的迴圈連結串列來處理josephu問題:先構建一個有n和節點的單迴圈連結串列,然後由k節點起從1開始計數,計數到m,對應節點從連結串列中刪除,然後被刪除的下一個節點又從1開始計數,知道最後一個節點從連結串列中刪除.
-
需要建立一個輔助指標helper,事先應該指向環形連結串列的最後一個節點 (遍歷實現 結束條件 helper.next = first)
-
報數前,先讓first和helper移動k-1次 (這是題中的從第k個人開始報數)
-
當小孩報數時,讓first和helper指標同時移動m-1次
-
這時就將first指向的小孩出圈.
- first = first.next;
- helper.next = first
程式碼實現
public class circleLinkedList { public static void main(String[] args) { CircleLinked circleLinked = new CircleLinked(); // 測試新增 circleLinked.add(5); circleLinked.list(); System.out.println("測試出圈----------------"); //測試出圈 circleLinked.countBoy(5,1,2); } } //迴圈連結串列 class CircleLinked{ //第一個節點 設定為null 是因為下面會進行復制 private Boy first = null; /** * * @param num 向環形連結串列新增的節點數目 */ public void add(int num){ if (num < 1){ System.out.println("輸入無效資料!!"); return; } Boy curBoy = null; // 新增輔助指標 for (int i = 1;i <= num;i++){ Boy boy = new Boy(i); //第一個節點 if (first == null){ first = boy; first.setNext(first); curBoy = first; //讓輔助指標指向first }else { curBoy.setNext(boy); boy.setNext(first); //尾節點指向頭結點,成環 curBoy = boy; //指向下一個節點 } } } //顯示連結串列 public void list(){ if (first == null){ System.out.println("連結串列為空!!"); return; } Boy curBoy = first; while (true){ System.out.printf("小孩編號為%d\n",curBoy.getNo()); if (curBoy.getNext() == first){ break; } curBoy = curBoy.getNext(); } } /** * * @param n 總共有多少和小孩 * @param k 從第幾個人開始報數 * @param m 數幾下 */ public void countBoy(int n,int k,int m){ //校驗資料 if (first == null || k < 1 || k > n){ System.out.println("資料有誤"); return; } Boy helper = first; //helper指向環形連結串列的最後一個節點 while (true){ if (helper.getNext() == first){ break; } helper = helper.getNext(); } ///小孩報數前,先讓 first 和 helper 移動 k - 1 次 for (int i = 0;i < k-1;i++){ first = first.getNext(); helper = helper.getNext(); } while (true){ if (helper == first){ //圈中只有一個節點 break; } //first 和 helper 移動m-1此 for (int i = 0;i < m-1;i++){ first = first.getNext(); helper = helper.getNext(); } //出圈小孩 System.out.printf("出圈編號為%d\n",first.getNo()); first = first.getNext(); helper.setNext(first); } System.out.printf("出圈編號為%d\n",first.getNo()); } } class Boy{ private int no; private Boy next; public Boy(int no){ this.no = no; } public int getNo() { return no; } public Boy getNext() { return next; } public void setNext(Boy next) { this.next = next; } }