<html> <head> <meta http-equiv='content-type' content='text/html;charset=utf-8' /> </head> <body> <h1>約瑟夫問題解決</h1> <?php class Child { public $no; public $next = null; public function __construct($no=''){ $this->no = $no; } } // 定義一個指向第一個小朋友的引用 $first = null; $n = 4; // 表示有幾個小朋友 // 寫一個函數來建立4個小朋友的環形鏈表 // 深刻分析下$first參數爲何加地址符& // 做用:把n個小孩構建出一個環形鏈表 // $first變量指向了第一個小朋友 function addChild(&$first,$n){ // 1.頭結點不能動 $cur = null; for ($i = 0; $i < $n; $i++) { $child = new Child($i+1); // 怎麼構成一個環形鏈表 if ($i==0) { $first = $child; $first->next = $child; $cur = $first; }else { $cur->next = $child; $child->next = $first; $cur = $cur->next; } } } // 顯示環形鏈表中的全部小朋友 // 必需要把頭給出來 function showChild($first){ // 遍歷 $cur = $first; while($cur->next!=$first){ // 顯示 echo '小孩的編號是'.$cur->no.'<br />'; $cur = $cur->next; } // 當退出while循環時,已經到了環形鏈表的最後 // 因此還要處理下最後這個小孩節點 echo '小孩的編號是'.$cur->no.'<br />'; } $m = 3; // 數3下 $k = 2; // 從第2個開始數 // 問題簡化,從第一個小孩開始數,數2 // 看看出圈的順序 function countChild($first,$m,$k){ if ($k>$m) { exit('數據設定不對'); } // 思考:找到一個小孩,就要把他從環形鏈表踢出去 // 爲了可以刪除某個小孩,須要一個輔助變量 // 該變量指向的小孩在$first前面 $tail = $first; while($tail->next!=$first){ $tail = $tail->next; } // 考慮是從第幾我的開始數數 for ($i = 0; $i < $k-1; $i++) { $tail = $tail->next; $first = $first->next; } // 當退出while循環時候 $tail就指向了最後這個小孩 // 讓$first和$tail向後移動 // 每移動1次,至關於數了2下 // 移動2次,至關於數了3下 // 由於本身數的時候是不須要動的 // 當$tail==$first說明只有一我的 while($tail!=$first){ for ($i = 0; $i < $m-1; $i++) { $tail = $tail->next; $first = $first->next; } // 打印出出列小孩編號 echo '出圈人的編號是'.$first->no.'<br />'; // 把$first指向的節點小孩刪除環形鏈表 $first = $first->next; $tail->next = $first; } echo '最後留在圈圈的人的編號是'.$tail->no; } addChild($first,4); showChild($first); // 真正的來玩兒遊戲 if ($m<$n) { countChild($first,$m,$k); } ?> </body> </html>