当前位置:首页 > PHP教程 > php高级应用 > 列表

php使用环形链表解决约瑟夫问题完整示例

发布:smiling 来源: PHP粉丝网  添加日期:2021-10-22 10:00:20 浏览: 评论:0 

本文实例讲述了php使用环形链表解决约瑟夫问题,分享给大家供大家参考,具体如下:

约瑟夫问题:

Josephu问题为:设编号为1,2,...n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。并求出最后出列的人是哪个?

PHP实现环形链表以及约瑟夫问题的解决:

  1. /** 
  2.  * 链表结构 
  3.  */ 
  4. class Child{ 
  5.   public $no
  6.   public $next=null; 
  7.   public function __construct($no=null){ 
  8.     $this->no = $no
  9.   } 
  10. /** 
  11.  * 链表操作 
  12.  */ 
  13. class CycleLink{ 
  14.   private $nodeNum = 0; 
  15.   /** 
  16.    * 添加节点 
  17.    */ 
  18.   public function addNode($head,$node
  19.   { 
  20.     $currentNode = $head
  21.     while ($currentNode->next!=null && $currentNode->next!=$head) { 
  22.       $currentNode = $currentNode->next; 
  23.     } 
  24.     $currentNode->next = $node
  25.     $currentNode->next->next = $head
  26.     $this->nodeNum++; 
  27.   } 
  28.   /** 
  29.    * 删除节点 
  30.    */ 
  31.   public function delNode($head,$no
  32.   { 
  33.     $currentNode = $head
  34.     while ($currentNode->next!=$head) { 
  35.       if($currentNode->next->no==$no){ 
  36.         $currentNode->next = $currentNode->next->next; 
  37.         $this->nodeNum--; 
  38.         break
  39.       } 
  40.       $currentNode = $currentNode->next; 
  41.     } 
  42.   } 
  43.   /** 
  44.    * 获取节点数量 
  45.    */ 
  46.   public function getNodeNum(){ 
  47.     return $this->nodeNum; 
  48.   } 
  49.   /** 
  50.    * 查找节点 
  51.    */ 
  52.   public function findNode($head,$no){ 
  53.     $node = null; 
  54.     $currentNode = $head
  55.     while ($currentNode->next!=$head) { 
  56.       if($currentNode->next->no==$no){ 
  57.         $node = $currentNode->next; 
  58.         break
  59.       } 
  60.       $currentNode = $currentNode->next; 
  61.     } 
  62.     return $node
  63.   } 
  64.   public function getNextNode($head,$node){ 
  65.     if($node->next==$head){ 
  66.       return $node->next->next; 
  67.     } 
  68.     return $node->next; 
  69.   } 
  70.   /** 
  71.    * 显示节点 
  72.    */ 
  73.   public function showNode($head
  74.   { 
  75.     echo "<br/><br/>"
  76.     $currentNode = $head
  77.     while ($currentNode->next!=$head){ 
  78.       $currentNode = $currentNode->next; 
  79.       echo '第 '.$currentNode->no.' 名小孩<br/>'
  80.     } 
  81.   } 
  82. /* 
  83. //创建一个head头,该head 只是一个头,不放入数据 
  84. $head     = new Child(); 
  85. $childList   = new CycleLink(); 
  86. $child_1   = new Child(1); 
  87. $child_2   = new Child(2); 
  88. $child_3   = new Child(3); 
  89. $child_4   = new Child(4); 
  90. $childList->addNode($head,$child_1); 
  91. $childList->addNode($head,$child_2); 
  92. $childList->addNode($head,$child_3); 
  93. $childList->addNode($head,$child_4); 
  94. $childList->showNode($head); 
  95. echo "<pre>"; 
  96. var_dump($head); 
  97. $findNode = $childList->findNode($head,3); 
  98. echo "<pre>"; 
  99. var_dump($findNode); 
  100. $childList->delNode($head,2); 
  101. $childList->showNode($head); 
  102. echo $childList->getNodeNum(); 
  103. exit(); 
  104. */ 
  105. /** 
  106.  * 约瑟夫问题 
  107.  * 设编号为1,2,...n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列, 
  108.  * 它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。 
  109.  * 并求出最后出列的人是哪个? 
  110.  */ 
  111. class Josephu{ 
  112.   private $head
  113.   private $childList
  114.   private $k
  115.   private $m
  116.   private $n
  117.   public function __construct($n,$k,$m){ 
  118.     $this->k = $k
  119.     $this->m = $m
  120.     $this->n = $n
  121.     $this->createList($n);  // 创建小孩 
  122.     echo "<br/><br/>当前有 {$n} 个小孩,从第 {$k} 个小孩开始报数,数到 {$m} 退出<br/><br/>"
  123.   } 
  124.   // 数数 
  125.   public function exec(){ 
  126.     $currentNode = $this->childList->findNode($this->head,$this->k);  // 获取第一个开始报数的人 
  127.     $_num = 0;  // 当前数到的值 
  128.     $surplus_num = $this->n; 
  129.     // 开始报数 
  130.     while ($surplus_num>1) {  // 只要人数大于1,就继续报数 
  131.       // 当前报数值 
  132.       $_num++; 
  133.       $nextNode = $this->childList->getNextNode($this->head,$currentNode); 
  134.       // 数至第m个数,然后将其移除。报数恢复到0,重新循环。 
  135.       if$_num==$this->m ){ 
  136.         $_num = 0; 
  137.         $surplus_num--; 
  138.         // 当前小孩退出 
  139.         $this->childList->delNode($this->head,$currentNode->no); 
  140.         echo '<br/>退出小孩编号:' . $currentNode->no; 
  141.       } 
  142.       // 移动到下一个小孩 
  143.       $currentNode = $nextNode
  144.     } 
  145.     echo '<br/>最后一个小孩编号:' . $currentNode->no; 
  146.   } 
  147.   // 创建小孩 
  148.   private function createList($n){ 
  149.     $this->childList = new CycleLink(); 
  150.     $this->head = new Child(); 
  151.     for ($i=1;$i<=$n;$i++){ 
  152.       $node = new Child($i); 
  153.       $this->childList->addNode($this->head,$node); 
  154.     } 
  155.     $this->childList->showNode($this->head); 
  156.   } 
  157. $josephu = new Josephu(4, 1, 2); 
  158. $josephu->exec(); 

运行结果:

第 1 名小孩

第 2 名小孩

第 3 名小孩

第 4 名小孩

当前有 4 个小孩,从第 1 个小孩开始报数,数到 2 退出

Tags: php环形链表 php约瑟夫

分享到: