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


Posted in PHP onAugust 07, 2018

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

约瑟夫问题:

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

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

/**
 * 链表结构
 */
class Child{
  public $no;
  public $next=null;
  public function __construct($no=null){
    $this->no = $no;
  }
}
/**
 * 链表操作
 */
class CycleLink{
  private $nodeNum = 0;
  /**
   * 添加节点
   */
  public function addNode($head,$node)
  {
    $currentNode = $head;
    while ($currentNode->next!=null && $currentNode->next!=$head) {
      $currentNode = $currentNode->next;
    }
    $currentNode->next = $node;
    $currentNode->next->next = $head;
    $this->nodeNum++;
  }
  /**
   * 删除节点
   */
  public function delNode($head,$no)
  {
    $currentNode = $head;
    while ($currentNode->next!=$head) {
      if($currentNode->next->no==$no){
        $currentNode->next = $currentNode->next->next;
        $this->nodeNum--;
        break;
      }
      $currentNode = $currentNode->next;
    }
  }
  /**
   * 获取节点数量
   */
  public function getNodeNum(){
    return $this->nodeNum;
  }
  /**
   * 查找节点
   */
  public function findNode($head,$no){
    $node = null;
    $currentNode = $head;
    while ($currentNode->next!=$head) {
      if($currentNode->next->no==$no){
        $node = $currentNode->next;
        break;
      }
      $currentNode = $currentNode->next;
    }
    return $node;
  }
  public function getNextNode($head,$node){
    if($node->next==$head){
      return $node->next->next;
    }
    return $node->next;
  }
  /**
   * 显示节点
   */
  public function showNode($head)
  {
    echo "<br/><br/>";
    $currentNode = $head;
    while ($currentNode->next!=$head){
      $currentNode = $currentNode->next;
      echo '第 '.$currentNode->no.' 名小孩<br/>';
    }
  }
}
/*
//创建一个head头,该head 只是一个头,不放入数据
$head     = new Child();
$childList   = new CycleLink();
$child_1   = new Child(1);
$child_2   = new Child(2);
$child_3   = new Child(3);
$child_4   = new Child(4);
$childList->addNode($head,$child_1);
$childList->addNode($head,$child_2);
$childList->addNode($head,$child_3);
$childList->addNode($head,$child_4);
$childList->showNode($head);
echo "<pre>";
var_dump($head);
$findNode = $childList->findNode($head,3);
echo "<pre>";
var_dump($findNode);
$childList->delNode($head,2);
$childList->showNode($head);
echo $childList->getNodeNum();
exit();
*/
/**
 * 约瑟夫问题
 * 设编号为1,2,...n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,
 * 它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
 * 并求出最后出列的人是哪个?
 */
class Josephu{
  private $head;
  private $childList;
  private $k;
  private $m;
  private $n;
  public function __construct($n,$k,$m){
    $this->k = $k;
    $this->m = $m;
    $this->n = $n;
    $this->createList($n);  // 创建小孩
    echo "<br/><br/>当前有 {$n} 个小孩,从第 {$k} 个小孩开始报数,数到 {$m} 退出<br/><br/>";
  }
  // 数数
  public function exec(){
    $currentNode = $this->childList->findNode($this->head,$this->k);  // 获取第一个开始报数的人
    $_num = 0;  // 当前数到的值
    $surplus_num = $this->n;
    // 开始报数
    while ($surplus_num>1) {  // 只要人数大于1,就继续报数
      // 当前报数值
      $_num++;
      $nextNode = $this->childList->getNextNode($this->head,$currentNode);
      // 数至第m个数,然后将其移除。报数恢复到0,重新循环。
      if( $_num==$this->m ){
        $_num = 0;
        $surplus_num--;
        // 当前小孩退出
        $this->childList->delNode($this->head,$currentNode->no);
        echo '<br/>退出小孩编号:' . $currentNode->no;
      }
      // 移动到下一个小孩
      $currentNode = $nextNode;
    }
    echo '<br/>最后一个小孩编号:' . $currentNode->no;
  }
  // 创建小孩
  private function createList($n){
    $this->childList = new CycleLink();
    $this->head = new Child();
    for ($i=1;$i<=$n;$i++){
      $node = new Child($i);
      $this->childList->addNode($this->head,$node);
    }
    $this->childList->showNode($this->head);
  }
}
$josephu = new Josephu(4, 1, 2);
$josephu->exec();

运行结果:

第 1 名小孩
第 2 名小孩
第 3 名小孩
第 4 名小孩

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

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
php之字符串变相相减的代码
Mar 19 PHP
windows的文件系统机制引发的PHP路径爆破问题分析
Jul 28 PHP
php获取从html表单传递数组的方法
Mar 20 PHP
php中ob函数缓冲机制深入理解
Aug 03 PHP
php实现可逆加密的方法
Aug 11 PHP
PHP基于单例模式实现的mysql类
Jan 09 PHP
thinkphp表单上传文件并将文件路径保存到数据库中
Jul 28 PHP
php封装一个异常的处理类
Jun 08 PHP
php curl批处理实现可控并发异步操作示例
May 09 PHP
Laravel5.4框架使用socialite实现github登录的方法
Mar 20 PHP
PHP之多条件混合筛选功能的实现方法
Oct 09 PHP
Thinkphp极验滑动验证码实现步骤解析
Nov 24 PHP
postman的安装与使用方法(模拟Get和Post请求)
Aug 06 #PHP
PHP实现的解汉诺塔问题算法示例
Aug 06 #PHP
PHP实现普通hash分布式算法简单示例
Aug 06 #PHP
PHP实现的无限分类类库定义与用法示例【基于thinkPHP】
Aug 06 #PHP
PHP常用字符串函数小结(推荐)
Aug 05 #PHP
PHP使用标准库spl实现的观察者模式示例
Aug 04 #PHP
PHP设计模式之观察者模式定义与用法示例
Aug 04 #PHP
You might like
php设计模式 Decorator(装饰模式)
2011/06/26 PHP
PHP连接MySQL的2种方法小结以及防止乱码
2014/03/11 PHP
PHP中对各种加密算法、Hash算法的速度测试对比代码
2014/07/08 PHP
jQuery 各种浏览器下获得日期区别
2008/12/22 Javascript
JavaScript实现多维数组的方法
2013/11/20 Javascript
jsPDF导出pdf示例
2014/05/02 Javascript
js实现图片从左往右渐变切换效果的方法
2015/02/06 Javascript
轻松实现js图片预览功能
2016/01/18 Javascript
AngularJS ng-bind 指令简单实现
2016/07/30 Javascript
web打印小结
2017/01/11 Javascript
深入理解Angular.JS中的Scope继承
2017/06/04 Javascript
vue.js提交按钮时进行简单的if判断表达式详解
2018/08/08 Javascript
vue中使用v-model完成组件间的通信
2019/08/22 Javascript
详解Vue 换肤方案验证
2019/08/28 Javascript
ES6对象操作实例详解
2020/05/23 Javascript
jQuery实现二级导航菜单的示例
2020/09/30 jQuery
jQuery实现简单评论区功能
2020/10/26 jQuery
vue element el-transfer增加拖拽功能
2021/01/15 Vue.js
学习python的几条建议分享
2013/02/10 Python
Python SQLAlchemy基本操作和常用技巧(包含大量实例,非常好)
2014/05/06 Python
Python实现学校管理系统
2018/01/11 Python
将TensorFlow的模型网络导出为单个文件的方法
2018/04/23 Python
matplotlib subplots 设置总图的标题方法
2018/05/25 Python
python对list中的每个元素进行某种操作的方法
2018/06/29 Python
OpenCV 模板匹配
2019/07/10 Python
基于keras输出中间层结果的2种实现方式
2020/01/24 Python
Python使用os.listdir和os.walk获取文件路径
2020/05/21 Python
Python本地及虚拟解释器配置过程解析
2020/10/13 Python
HTML5和以前HTML4的区别整理
2013/10/20 HTML / CSS
HTML5本地存储localStorage、sessionStorage基本用法、遍历操作、异常处理等
2014/05/08 HTML / CSS
连卡佛中国官网:Lane Crawford中文站
2018/01/27 全球购物
机修工岗位职责
2013/11/24 职场文书
司法局群众路线教育实践活动整改措施思想汇报
2014/10/13 职场文书
师德师风个人整改措施
2014/10/27 职场文书
2016春季小学开学寄语
2015/12/03 职场文书
分析mysql中一条SQL查询语句是如何执行的
2021/06/21 MySQL