日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构:循环链表解决约瑟夫问题

發(fā)布時間:2025/3/21 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构:循环链表解决约瑟夫问题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

    • 約瑟夫問題
      • 問題來歷
      • 循環(huán)鏈表進行模擬
      • 思路

約瑟夫問題

問題來歷

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

循環(huán)鏈表進行模擬

因為約瑟夫問題是一個環(huán)狀,因此又被稱為約瑟夫環(huán),結構與循環(huán)鏈表相似,因此可以用循環(huán)鏈表進行模擬。

思路

  • 創(chuàng)建節(jié)點

    class Person {//序號private int num;//后繼指針,指向下一個節(jié)點private Person next;public Person(int num) {this.num = num;}public int getNum() {return num;}public void setNum(int num) {this.num = num;}public Person getNext() {return next;}public void setNext(Person next) {this.next = next;} }
  • 創(chuàng)建一個單向的環(huán)形鏈表

  • 先創(chuàng)建第一個頭節(jié)點,并讓first指針指向該節(jié)點,next指針指向本身,形成環(huán)狀。

  • 后面每創(chuàng)建一個新的節(jié)點,就把其加到已有的環(huán)形鏈表中。

  • /*** 單向的環(huán)形鏈表*/ class CircleSingleLinkedList {/*** 創(chuàng)建一個first節(jié)點*/private Person first;/*** 添加節(jié)點構建環(huán)形鏈表* @param nums 要創(chuàng)建的節(jié)點個數(shù)*/public void addPerson(int nums){if (nums < 1){System.out.println("nums值不正確!");return;}//幫助構建環(huán)形鏈表Person temp = null;//使用for來創(chuàng)建我們的環(huán)形鏈表for (int i = 1; i <= nums ; i++){//根據(jù)編號創(chuàng)建節(jié)點Person person = new Person(i);//頭節(jié)點if (i == 1){first = person;//構成環(huán)狀first.setNext(first);//讓指針指向第一個節(jié)點temp = first;continue;}temp.setNext(person);person.setNext(first);temp = person;}} }
  • 遍歷環(huán)形鏈表

  • 先讓一個輔助指針temp指向first頭節(jié)點
  • 通過while循環(huán)遍歷該環(huán)形鏈表
  • public void list() {if (first == null){System.out.println("空鏈表");return;}//頭節(jié)點不能動,用輔助指針來實現(xiàn)遍歷Person temp = first;while (true){System.out.printf("編號:%d\n",temp.getNum());//遍歷完畢if (temp.getNext() == first){break;}//指針后移temp = temp.getNext();} }
  • 計算各個節(jié)點出表順序

  • 創(chuàng)建一個輔助指針end指向鏈表的最后一個節(jié)點

  • 根據(jù)起始報數(shù)位置startNum,讓first和end指針同時移動startNum-1次

  • 開始報數(shù),每次報數(shù)讓first和end指針向后移動countNums-1次

  • 最后first指針指向的節(jié)點就是要出表的節(jié)點

  • 移出該節(jié)點,重復34步驟。

  • /*** 根據(jù)用戶的輸入計算出人出圈的順序* @param startNum 表示從第幾個人開始報數(shù)* @param countNums 表示每次數(shù)幾次* @param personNums 表示最初有多少人*/ public void play(int startNum,int countNums,int personNums) {if (first == null || startNum < 1 || startNum > personNums){System.out.println("參數(shù)輸入有誤,請重新輸入");return;}//創(chuàng)建輔助指針Person end = first;//開始報數(shù)之前讓end指針指向最后一個節(jié)點while (true){if (end.getNext() == first){break;}end = end.getNext();}//報數(shù)前讓first和end根據(jù)startNum進行校準for (int i = 0; i < startNum - 1; i++){first = first.getNext();end = end.getNext();}//報數(shù)時,讓first和end指針同時移動(countNums-1)次while (true){//圈中只有一個節(jié)點if (end == first){break;}for (int i = 0; i < countNums - 1; i++){first = first.getNext();end = end.getNext();}System.out.printf("出圈號碼:%d\n",first.getNum());first = first.getNext();end.setNext(first);}System.out.printf("最后留在圈中的號碼是:%d\n",first.getNum()); }

測試

public class Josephu {public static void main(String[] args) {CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();//添加節(jié)點circleSingleLinkedList.addPerson(6);//遍歷鏈表circleSingleLinkedList.list();//計算出圈順序并輸出circleSingleLinkedList.play(1,5,6);} } ------------------------------------------------------------------------------------------------------------------- //輸出結果: 編號:1 編號:2 編號:3 編號:4 編號:5 編號:6 出圈號碼:5 出圈號碼:4 出圈號碼:6 出圈號碼:2 出圈號碼:3 最后留在圈中的號碼是:1 5->4->6->2->3->1

如有錯誤或不足歡迎評論指正。

總結

以上是生活随笔為你收集整理的数据结构:循环链表解决约瑟夫问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。