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 相关文章推荐
基于文本的访客签到簿
Oct 09 PHP
发布一个迷你php+AJAX聊天程序[聊天室]提供下载
Jul 21 PHP
php 获取mysql数据库信息代码
Mar 12 PHP
dhtmlxTree目录树增加右键菜单以及拖拽排序的实现方法
Apr 26 PHP
PHP 登录记住密码实现思路
May 07 PHP
浅析ThinkPHP中的pathinfo模式和URL重写
Jan 06 PHP
Codeigniter购物车类不能添加中文的解决方法
Nov 29 PHP
PHP闭包函数详解
Feb 13 PHP
PHP封装XML和JSON格式数据接口操作示例
Mar 06 PHP
PHP 7.4中使用预加载的方法详解
Jul 08 PHP
php array 转json及java 转换 json数据格式操作示例
Nov 13 PHP
PHP 计算至少是其他数字两倍的最大数的实现代码
May 26 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 include_path设置技巧分享
2011/07/03 PHP
PHP遍历数组的几种方法
2012/03/22 PHP
ie与session丢失(新窗口cookie丢失)实测及解决方案
2013/07/15 PHP
PHP原生函数一定好吗?
2014/12/08 PHP
php判断对象是派生自哪个类的方法
2015/06/20 PHP
分享微信扫码支付开发遇到问题及解决方案-附Ecshop微信支付插件
2015/08/23 PHP
PHP使用Http Post请求发送Json对象数据代码解析
2020/07/16 PHP
jquery判断RadioButtonList和RadioButton中是否有选中项示例
2013/09/29 Javascript
JS两个数组比较,删除重复值的巧妙方法(推荐)
2016/06/03 Javascript
详解js的异步编程技术的方法
2017/02/09 Javascript
Node.js 使用命令行工具检查更新
2017/06/08 Javascript
JavaScript 通过Ajax 动态加载CheckBox复选框
2017/08/31 Javascript
修改UA在PC中访问只能在微信中打开的链接方法
2017/11/27 Javascript
angularJS开发注意事项
2018/05/26 Javascript
解决layer 关闭当前弹窗 关闭遮罩层 input值获取不到的问题
2019/09/25 Javascript
python3序列化与反序列化用法实例
2015/05/26 Python
Python脚本实现Web漏洞扫描工具
2016/10/25 Python
老生常谈Python基础之字符编码
2017/06/14 Python
python多线程抽象编程模型详解
2019/03/20 Python
Pytorch 实现冻结指定卷积层的参数
2020/01/06 Python
python 装饰器的使用示例
2020/10/10 Python
html5开发之viewport使用
2013/10/17 HTML / CSS
HEMA英国:荷兰原创设计
2018/08/28 全球购物
芭比波朗加拿大官方网站:Bobbi Brown Cosmetics CA
2020/11/05 全球购物
瀑布模型都有哪些优缺点
2014/06/23 面试题
学前教育学生自荐信范文
2013/12/31 职场文书
雷锋精神演讲稿
2014/05/13 职场文书
给市场的环保建议书
2014/05/14 职场文书
2015年教师党员公开承诺书
2015/01/22 职场文书
幼儿教师师德师风自我评价
2015/03/05 职场文书
交通安全温馨提示语
2015/07/14 职场文书
离婚协议书范文2016
2016/03/18 职场文书
2016年党员创先争优公开承诺书
2016/03/25 职场文书
详解Nginx 工作原理
2021/03/31 Servers
PostGIS的安装与入门使用指南
2022/01/18 PostgreSQL
什么是css原子化,有什么用?
2022/04/24 HTML / CSS