韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理

时间:2023-02-12 09:57:40
                        <div class="htmledit_views">

文西马龙:http://blog.csdn.net/wenximalong/

现在我们对单链表有了基本的了解,现在学习一下环形链表。
环形链表的内存示意图
韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
环形链表的好处:可以模拟许多实际的情景
如丢手帕问题,就是经典的用环形链表来解决的
韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
现在我们来完成约瑟夫问题的解决方案!
Josephu问题

Josephu问题为:射编号为1,2,…n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。并求出最后出列的人是哪个?
提示:用一个不带头节点的循环链表来处里Josephu问题,先构成一个有n个节点的单循环链表,然后由k节点起从1开始计数,计到m时,对应节点从链表中删除,然后再从被删除节点的下一个节点又从1开始计数,直到最后一个节点从链表中删除算法结束。


思路:
(一)构建一个环形链表,链表上的每个节点,表示一个小朋友(PHP语言实现)

韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
一个小朋友的情况
韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
两个小朋友的情况
韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
当第一个结点做完以后,1号小朋友还有一个新的指向指向它,就是cur。cur的用处,当有2号小朋友的时候,cur就发挥作用了,此时cur还是指向1号小朋友,那么cur-&gt;next=child;则①号线就被搭起来了,然后child-&gt;next=first;则②号线就被搭起来了,2号小朋友结点就指向了1号小朋友结点,环形链表就形成了。 cur= cur->next;则cur就由原来的指向1号小朋友转为指向2号小朋友了,如图中③号线所示,这样就可以再加第3个小朋友了,依次类推。
(二)写一个函数来显示所有的小孩子
josephu.php

  1. <html>  
  2.     <head>  
  3.         <meta http-equiv=”Content-Type” content=“text/html; charset=gb2312” />  
  4.     </head>  
  5.     <body>  
  6.         <h1>约瑟夫问题解决</h1>  
  7.         <?php  
  8.             //先构建一个环形链表,链表上的每个节点,表示一个小朋友  
  9.             //小孩类  
  10.             class Child{  
  11.                 public no</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="vars">;  
  12.                 public next=null;  
  13.                 //构造函数  
  14.                 public function __construct(no</span><span>){&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$this</span><span>-&gt;no=</span><span class="vars">$no</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//定义一个指向第一个小朋友的引用</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//定义一个空头</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">){  
  15.                     $this->no=$no;  
  16.                 }  
  17.             }  
  18.             //定义一个指向第一个小朋友的引用  
  19.             //定义一个空头  
  20.             first=null;  
  21.             n</span><span>=4;&nbsp;</span><span class="comment">//=4; //n表示有几个小朋友  
  22.             //写一个函数来创建一个四个小朋友的环形链表  
  23.             /* 
  24.              addChild函数的作用是:把 n first变量就指向该环形链表的第一个小孩子 
  25.              */  
  26.             function addChild(& first</span><span>,</span><spanclass="vars"> ,n){ //此处要加地址符  
  27.                 //1.头结点不能动 first不能动</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">  
  28.                 cur=first</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>(</span><span class="vars">;  
  29.                 for(i=0;i</span><span>&lt;</span><span class="vars"><n;i</span><span>++){&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$child</span><span>=</span><span class="keyword">new</span><span>&nbsp;Child(</span><span class="vars">$i</span><span>+1);&nbsp;</span><span class="comment">//为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//怎么构成一个环形链表呢</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(</span><span class="vars">$i</span><span>==0){&nbsp;</span><span class="comment">//第一个小孩的情况</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>=</span><span class="vars">$child</span><span>;&nbsp;</span><span class="comment">//让first指向child,但是还没有构建环形链表</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>-&gt;next=</span><span class="vars">$child</span><span>;&nbsp;</span><span class="comment">//自己指向自己</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<span class="keyword">else</span><span>{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>-&gt;next=</span><span class="vars">$child</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$child</span><span>-&gt;next=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//继续指向下一个</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>=</span><span class="vars">$cur</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//遍历所有的小孩,并显示</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">function</span><span>&nbsp;showChild(</span><span class="vars">++){  
  30.                     $child=new Child($i+1); //为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的  
  31.                     //怎么构成一个环形链表呢  
  32.                     if($i==0){ //第一个小孩的情况  
  33.                         $first=$child//让first指向child,但是还没有构建环形链表  
  34.                         $first->next=$child//自己指向自己  
  35.                         $cur=$first;  
  36.                     }else{  
  37.                         $cur->next=$child;  
  38.                         $child->next=$first;  
  39.                         //继续指向下一个  
  40.                         $cur=$cur->next;  
  41.                     }  
  42.                 }  
  43.             }  
  44.             //遍历所有的小孩,并显示  
  45.             function showChild(first){  
  46.                 //遍历 cur变量是帮助我们遍历循环列表的,所以不能动  
  47.                  cur</span><span>=</span><spanclass="vars"> =first;  
  48.                 while(cur</span><span>-&gt;next!=</span><span class="vars">->next!=first){ //cur没有到结尾,就遍历  
  49.                     //显示  
  50.                     echo‘<br/>小孩的编号是’.cur</span><span>-&gt;no;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//继续</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">->no;  
  51.                     //继续  
  52.                     cur=cur</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addChild(<span class="vars">->next;  
  53.                 }  
  54.             }  
  55.             addChild(first,n</span><span>);&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;showChild(<span class="vars">);  
  56.             showChild(first);  
  57.         ?>  
  58.     </body>  
  59. </html>  
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    </head>
    <body>
        <h1>约瑟夫问题解决</h1>
        <?php
            //先构建一个环形链表,链表上的每个节点,表示一个小朋友
            //小孩类
            class Child{
                public $no;
                public $next=null;
                //构造函数
                public function __construct($no){
                    $this-&gt;no=$no;
                }
            }
            //定义一个指向第一个小朋友的引用
            //定义一个空头
            $first=null;
            $n=4; //$n表示有几个小朋友
            //写一个函数来创建一个四个小朋友的环形链表
            /*
             addChild函数的作用是:把$n个小孩在构建成一个环形链表,$first变量就指向该环形链表的第一个小孩子
             */
            function addChild(&$first,$n){ //此处要加地址符
                //1.头结点不能动 $first不能动
                $cur=$first;
                for($i=0;$i<$n;$i++){
                    $child=new Child($i+1); //为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的
                    //怎么构成一个环形链表呢
                    if($i==0){ //第一个小孩的情况
                        $first=$child; //让first指向child,但是还没有构建环形链表
                        $first-&gt;next=$child; //自己指向自己
                        $cur=$first;
                    }else{
                        $cur-&gt;next=$child;
                        $child-&gt;next=$first;
                        //继续指向下一个
                        $cur=$cur->next;
                    }
                }
            }
            //遍历所有的小孩,并显示
            function showChild($first){
                //遍历 cur变量是帮助我们遍历循环列表的,所以不能动
                $cur=$first;
                while($cur-&gt;next!=$first){ //cur没有到结尾,就遍历
                    //显示
                    echo'<br/>小孩的编号是'.$cur->no;
                    //继续
                    $cur=$cur->next;
                }
            }
            addChild($first,$n);
            showChild($first);
        ?>
    </body>
</html>
韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理

为什么现在只显示三个小孩呢,分析一下代码在内存中是怎么运作的

图片大,在新窗口中打开图片,观看完整图片

韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
(1)语句①执行后,cur也指向了1号小朋友;
(2)然后语句②执行,进入while循环,此时cur指向1号小朋友,执行语句③,输出:小孩的编号是1,再执行语句④ cur= cur->next;
(3)此时cur指向2号小朋友,然后语句②执行,进入while循环,此时cur指向2号小朋友,执行语句③,输出:小孩的编号是2,再执行语句④ cur= cur->next;
(4)此时cur指向3号小朋友,,然后语句②执行,进入while循环,此时cur指向3号小朋友,执行语句③,输出:小孩的编号是3,再执行语句④ cur= cur->next;
(5)此时cur指向4号小朋友,然后执行语句②,此时 cur-&gt;next,就指向了1号小朋友,而first也指向1号小朋友,此时 cur->next!=$first;不成立了,为假,就退出了while循环, 因此就少了一个小孩,即4号小朋友。
所以要对josephu.php修改,即josephu2.php
josephu2.php

  1. <html>  
  2.     <head>  
  3.         <meta http-equiv=”Content-Type” content=“text/html; charset=gb2312” />  
  4.     </head>  
  5.     <body>  
  6.         <h1>约瑟夫问题解决</h1>  
  7.         <?php  
  8.             //先构建一个环形链表,链表上的每个节点,表示一个小朋友  
  9.             //小孩类  
  10.             class Child{  
  11.                 public no</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="vars">;  
  12.                 public next=null;  
  13.                 //构造函数  
  14.                 public function __construct(no</span><span>){&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$this</span><span>-&gt;no=</span><span class="vars">$no</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//定义一个指向第一个小朋友的引用</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//定义一个空头</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">){  
  15.                     $this->no=$no;  
  16.                 }  
  17.             }  
  18.             //定义一个指向第一个小朋友的引用  
  19.             //定义一个空头  
  20.             first=null;  
  21.             n</span><span>=4;&nbsp;</span><span class="comment">//=4; //n表示有几个小朋友  
  22.             //写一个函数来创建一个四个小朋友的环形链表  
  23.             /* 
  24.              addChild函数的作用是:把 n first变量就指向该环形链表的第一个小孩子 
  25.              */  
  26.             function addChild(& first</span><span>,</span><spanclass="vars"> ,n){ //此处要加地址符  
  27.                 //1.头结点不能动 first不能动</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">  
  28.                 cur=first</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>(</span><span class="vars">;  
  29.                 for(i=0;i</span><span>&lt;</span><span class="vars"><n;i</span><span>++){&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$child</span><span>=</span><span class="keyword">new</span><span>&nbsp;Child(</span><span class="vars">$i</span><span>+1);&nbsp;</span><span class="comment">//为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//怎么构成一个环形链表呢</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(</span><span class="vars">$i</span><span>==0){&nbsp;</span><span class="comment">//第一个小孩的情况</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>=</span><span class="vars">$child</span><span>;&nbsp;</span><span class="comment">//让first指向child,但是还没有构建环形链表</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>-&gt;next=</span><span class="vars">$child</span><span>;&nbsp;</span><span class="comment">//自己指向自己</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<span class="keyword">else</span><span>{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>-&gt;next=</span><span class="vars">$child</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$child</span><span>-&gt;next=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//继续指向下一个</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>=</span><span class="vars">$cur</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//遍历所有的小孩,并显示</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">function</span><span>&nbsp;showChild(</span><span class="vars">++){  
  30.                     $child=new Child($i+1); //为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的  
  31.                     //怎么构成一个环形链表呢  
  32.                     if($i==0){ //第一个小孩的情况  
  33.                         $first=$child//让first指向child,但是还没有构建环形链表  
  34.                         $first->next=$child//自己指向自己  
  35.                         $cur=$first;  
  36.                     }else{  
  37.                         $cur->next=$child;  
  38.                         $child->next=$first;  
  39.                         //继续指向下一个  
  40.                         $cur=$cur->next;  
  41.                     }  
  42.                 }  
  43.             }  
  44.             //遍历所有的小孩,并显示  
  45.             function showChild(first){  
  46.                 //遍历 cur变量是帮助我们遍历循环列表的,所以不能动  
  47.                  cur</span><span>=</span><spanclass="vars"> =first;  
  48.                 while(cur</span><span>-&gt;next!=</span><span class="vars">->next!=first){ //cur没有到结尾,就遍历  
  49.                     //显示  
  50.                     echo‘<br/>小孩的编号是’.cur</span><span>-&gt;no;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//继续</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">->no;  
  51.                     //继续  
  52.                     cur=cur</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//当退出while循环时,已经到了环形链表的最后,即cur此时指向最后一个小孩,所以还要处里一下最后这个小孩节点</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">echo</span><span class="string">'&lt;br/&gt;小孩的编号是'</span><span>.</span><span class="vars">->next;  
  53.                 }  
  54.                 //当退出while循环时,已经到了环形链表的最后,即cur此时指向最后一个小孩,所以还要处里一下最后这个小孩节点  
  55.                 echo'<br/>小孩的编号是'.cur->no;  
  56.             }  
  57.             addChild( first</span><span>,</span><spanclass="vars"> ,n);  
  58.             showChild($first);  
  59.         ?>  
  60.     </body>  
  61. </html>  
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    </head>
    <body>
        <h1>约瑟夫问题解决</h1>
        <?php
            //先构建一个环形链表,链表上的每个节点,表示一个小朋友
            //小孩类
            class Child{
                public $no;
                public $next=null;
                //构造函数
                public function __construct($no){
                    $this-&gt;no=$no;
                }
            }
            //定义一个指向第一个小朋友的引用
            //定义一个空头
            $first=null;
            $n=4; //$n表示有几个小朋友
            //写一个函数来创建一个四个小朋友的环形链表
            /*
             addChild函数的作用是:把$n个小孩在构建成一个环形链表,$first变量就指向该环形链表的第一个小孩子
             */
            function addChild(&$first,$n){ //此处要加地址符
                //1.头结点不能动 $first不能动
                $cur=$first;
                for($i=0;$i<$n;$i++){
                    $child=new Child($i+1); //为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的
                    //怎么构成一个环形链表呢
                    if($i==0){ //第一个小孩的情况
                        $first=$child; //让first指向child,但是还没有构建环形链表
                        $first-&gt;next=$child; //自己指向自己
                        $cur=$first;
                    }else{
                        $cur-&gt;next=$child;
                        $child-&gt;next=$first;
                        //继续指向下一个
                        $cur=$cur->next;
                    }
                }
            }
            //遍历所有的小孩,并显示
            function showChild($first){
                //遍历 cur变量是帮助我们遍历循环列表的,所以不能动
                $cur=$first;
                while($cur-&gt;next!=$first){ //cur没有到结尾,就遍历
                    //显示
                    echo'<br/>小孩的编号是'.$cur->no;
                    //继续
                    $cur=$cur->next;
                }
                //当退出while循环时,已经到了环形链表的最后,即cur此时指向最后一个小孩,所以还要处里一下最后这个小孩节点
                echo'<br/>小孩的编号是'.$cur->no;
            }
            addChild($first,$n);
            showChild($first);
        ?>
    </body>




</html>韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理


注意:function addChild(& first, n){ //此处$first前面为什么要加地址符&呢


修改的是值还是地址

test.php

  1. <html>  
  2.     <head>  
  3.         <meta http-equiv=”Content-Type” content=“text/html; charset=gb2312” />  
  4.     </head>  
  5.     <body>  
  6.         <h1>function addChild(& first</span><span>,</span><spanclass="vars"> ,n){ //此处first前面为什么要加地址符&amp;呢&lt;/h1&gt;</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;?php&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">class</span><span>&nbsp;Dog{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="vars">$age</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">function</span><span>&nbsp;__construct(</span><span class="vars">$age</span><span>){&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$this</span><span>-&gt;age=</span><span class="vars">$age</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">function</span><span>&nbsp;test(</span><span class="vars">  
  7.         <?php  
  8.             class Dog{  
  9.                 public $age;  
  10.                 public function __construct($age){  
  11.                     $this->age=$age;  
  12.                 }  
  13.             }  
  14.             function test(dog){  
  15.                 dog</span><span>-&gt;age=30;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//创建一个狗对象实例</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">->age=30;  
  16.             }  
  17.             //创建一个狗对象实例  
  18.             dog1=new Dog(100);  
  19.             //调用test(调用函数就会开辟一个新栈)  
  20.             test(dog1</span><span>);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">echo</span><span>&nbsp;</span><span class="vars">);  
  21.   
  22.             echo dog1->age; //为什么会输出30呢  
  23.             echo ‘<br/>’;  
  24.   
  25.             function test2(dog</span><span>){&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$dog</span><span>=</span><span class="keyword">new</span><span>&nbsp;Dog(200);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//创建一个狗对象实例</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">){  
  26.                 $dog=new Dog(200);  
  27.             }  
  28.             //创建一个狗对象实例  
  29.             dog1=new Dog(100);  
  30.             //调用test(调用函数就会开辟一个新栈)  
  31.             test2(dog1</span><span>);&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">echo</span><span>&nbsp;</span><span class="vars">);  
  32.             echo dog1->age; //此时输出100还是200呢,输出100  
  33.             echo ‘<br/>’;  
  34.   
  35.             //& 表示用地址传递  
  36.             function test3(&dog</span><span>){&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$dog</span><span>=</span><span class="keyword">new</span><span>&nbsp;Dog(200);&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//创建一个狗对象实例</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">){  
  37.                 $dog=new Dog(200);  
  38.             }  
  39.             //创建一个狗对象实例  
  40.             dog1=new Dog(100);  
  41.             //调用test(调用函数就会开辟一个新栈)  
  42.             test3(dog1</span><span>);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">echo</span><span>&nbsp;</span><span class="vars">);  
  43.             echo dog1->age; //此时输出100还是200呢,输出200  
  44.   
  45.         ?>  
  46.     </body>  
  47. </html>  
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    </head>
    <body>
        <h1>function addChild(&$first,$n){ //此处$first前面为什么要加地址符&呢</h1>
        <?php
            class Dog{
                public $age;
                public function __construct($age){
                    $this-&gt;age=$age;
                }
            }
            function test($dog){
                $dog->age=30;
            }
            //创建一个狗对象实例
            $dog1=new Dog(100);
            //调用test(调用函数就会开辟一个新栈)
            test($dog1);

            echo $dog1->age; //为什么会输出30呢
            echo '<br/>';

            function test2($dog){
                $dog=new Dog(200);
            }
            //创建一个狗对象实例
            $dog1=new Dog(100);
            //调用test(调用函数就会开辟一个新栈)
            test2($dog1);
            echo $dog1->age; //此时输出100还是200呢,输出100
            echo '<br/>';

            //& 表示用地址传递
            function test3(&$dog){
                $dog=new Dog(200);
            }
            //创建一个狗对象实例
            $dog1=new Dog(100);
            //调用test(调用函数就会开辟一个新栈)
            test3($dog1);
            echo $dog1->age; //此时输出100还是200呢,输出200

        ?>
    </body>
</html>
韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理

内存分析图

图片大,在新窗口中打开图片,观看完整图片

韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
(1)语句①执行完后,主栈里就会有一个dog1变量,dog1变量指向了一个堆,对象实例的数据是放在堆区的;
(2)然后执行语句②,调用函数,不管哪种语言,只要调用函数,就会开辟一个新栈,在新栈test栈中,在test栈区中有一个变量 dog dog变量本身的地址是0x56,面向对象是引用传递的, dog0x34 dog变量也指向堆区的0x34地址,当在test栈中执行 dog>age=30;10030testtest3echo dog1-&gt;age;,在主栈中$dog1指向堆区地址0x34,此时100已经被修改为30了,所以最后输出:30

再加深一下

内存分析图

图片大,在新窗口中打开图片,观看完整图片

韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
(1)语句①执行完后,主栈里就会有一个dog1变量,dog1变量指向了一个堆,对象实例的数据是放在堆区的;
(2)然后执行语句②,调用函数,不管哪种语言,只要调用函数,就会开辟一个新栈,在新栈test2栈中,在test2栈区中有一个变量 dog dog变量本身的地址是0x56,面向对象是引用传递的, dog0x34 dog变量也指向堆区的0x34地址,然后执行 dog=newDog(200);0x88200test2 dog的0x34就会被修改为0x88,此时的 dog0x560x88test2test20x343echo dog1-&gt;age;,在主栈中$dog1指向堆区地址0x34,此时100并没有被修改,所以最后输出:100

现在考虑加入地址符&的情况

内存分析图

图片大,在新窗口中打开图片,观看完整图片

韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
(1)语句①执行完后,主栈里就会有一个dog1变量,dog1变量指向了一个堆,对象实例的数据是放在堆区的;
(2)然后执行语句②,调用函数,不管哪种语言,只要调用函数,就会开辟一个新栈,在新栈test3栈中,在test3栈区中有一个变量 dog dog变量本身的地址是0x56,在传递参数的时候,用的是& dog dog变量存的值就是0x34,然后执行 dog=newDog(200);0x88200test3 dog的0x34就会被修改为0x88,主栈中 dog10x340x88 dog变量和主栈中的 dog10x88test3test33echo dog1-&gt;age;,在主栈中$dog1已经由指向堆区地址0x34转为指向堆区地址0x88,所以最后输出:200
=========

(三)真正来玩游戏
(1)先问题简化,从第一个小孩开始数,数2,看看出列的顺序

分析图
韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
现在我们已经有了环形链表,并且 first1first2 first指向2号小朋友节点,然后让2号小朋友出列,是做不到的,如果是让2号小朋友出列,是形成如下图所示的环形列表,
韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
让1号小朋友的next指向3号小朋友,2号就出列了。但是这个$first是指向了2号本身。所以单链表的麻烦事情: ★★它不能自己把自己删除掉。
因此必须保证 first first的前面添加一个$tail指针
韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
这个时候就可以把2号人物给删除了,先让 first first指向3号小朋友,此时tail指向1号小朋友,让tail的next指向$first,就是1号小朋友指向了3号小朋友,2号小朋友就出列了,如下图所示
韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
就是现在需要一个辅助指针,就是在运行之前,要先拿一个指针指向$first的前面,如下图所示
韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理

————-

韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
josephu3.php

  1. <html>  
  2.     <head>  
  3.         <meta http-equiv=”Content-Type” content=“text/html; charset=gb2312” />  
  4.     </head>  
  5.     <body>  
  6.         <h1>约瑟夫问题解决</h1>  
  7.         <?php  
  8.             //先构建一个环形链表,链表上的每个节点,表示一个小朋友  
  9.             //小孩类  
  10.             class Child{  
  11.                 public no</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="vars">;  
  12.                 public next=null;  
  13.                 //构造函数  
  14.                 public function __construct(no</span><span>){&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$this</span><span>-&gt;no=</span><span class="vars">$no</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//定义一个指向第一个小朋友的引用</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//定义一个空头</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">){  
  15.                     $this->no=$no;  
  16.                 }  
  17.             }  
  18.             //定义一个指向第一个小朋友的引用  
  19.             //定义一个空头  
  20.             first=null;  
  21.             n</span><span>=4;&nbsp;</span><span class="comment">//=4; //n表示有几个小朋友  
  22.             //写一个函数来创建一个四个小朋友的环形链表  
  23.             /* 
  24.              addChild函数的作用是:把 n first变量就指向该环形链表的第一个小孩子 
  25.              */  
  26.             function addChild(& first</span><span>,</span><spanclass="vars"> ,n){ //此处要加地址符  
  27.                 //1.头结点不能动  first cur=first;让cur来帮我们穿针引线</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">  
  28.                 cur=first</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>(</span><span class="vars">;  
  29.                 for(i=0;i</span><span>&lt;</span><span class="vars"><n;i</span><span>++){&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$child</span><span>=</span><span class="keyword">new</span><span>&nbsp;Child(</span><span class="vars">$i</span><span>+1);&nbsp;</span><span class="comment">//为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//怎么构成一个环形链表呢</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(</span><span class="vars">$i</span><span>==0){&nbsp;</span><span class="comment">//第一个小孩的情况</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>=</span><span class="vars">$child</span><span>;&nbsp;</span><span class="comment">//让first指向child,但是还没有构建环形链表</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>-&gt;next=</span><span class="vars">$child</span><span>;&nbsp;</span><span class="comment">//自己指向自己</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>=</span><span class="vars">$first</span><span>;&nbsp;</span><span class="comment">//当$i==0的时候,就让cur和first指向同一个地方</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<span class="keyword">else</span><span>{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>-&gt;next=</span><span class="vars">$child</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$child</span><span>-&gt;next=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//继续指向下一个</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>=</span><span class="vars">$cur</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//遍历所有的小孩,并显示</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">function</span><span>&nbsp;showChild(</span><span class="vars">++){  
  30.                     $child=new Child($i+1); //为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的  
  31.                     //怎么构成一个环形链表呢  
  32.                     if($i==0){ //第一个小孩的情况  
  33.                         $first=$child//让first指向child,但是还没有构建环形链表  
  34.                         $first->next=$child//自己指向自己  
  35.                         $cur=$first//当$i==0的时候,就让cur和first指向同一个地方  
  36.                     }else{  
  37.                         $cur->next=$child;  
  38.                         $child->next=$first;  
  39.                         //继续指向下一个  
  40.                         $cur=$cur->next;  
  41.                     }  
  42.                 }  
  43.             }  
  44.             //遍历所有的小孩,并显示  
  45.             function showChild(first){  
  46.                 //遍历 cur变量是帮助我们遍历循环列表的,所以不能动  
  47.                  cur</span><span>=</span><spanclass="vars"> =first;  
  48.                 while(cur</span><span>-&gt;next!=</span><span class="vars">->next!=first){ //cur没有到结尾,就遍历  
  49.                     //显示  
  50.                     echo‘<br/>小孩的编号是’.cur</span><span>-&gt;no;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//继续</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">->no;  
  51.                     //继续  
  52.                     cur=cur</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//当退出while循环时,已经到了环形链表的最后,即cur此时指向最后一个小孩,所以还要处里一下最后这个小孩节点</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">echo</span><span class="string">'&lt;br/&gt;小孩的编号是'</span><span>.</span><span class="vars">->next;  
  53.                 }  
  54.                 //当退出while循环时,已经到了环形链表的最后,即cur此时指向最后一个小孩,所以还要处里一下最后这个小孩节点  
  55.                 echo'<br/>小孩的编号是'.cur->no;  
  56.             }  
  57.   
  58.             //问题简化,从第一个小孩开始数,数2,看看出拳的顺序  
  59.             function countChild(first</span><span>){&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//思考:因为我们每找到一个小孩,就要把他从环形链表中删除</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//为了能够删除某个小孩,我们需要一个辅助变量,该变量指向的小孩在$first前面,在$first的前面,因为是环形的,就相当于在队尾了。</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$tail</span><span>=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">while</span><span>(</span><span class="vars">$tail</span><span>-&gt;next!=</span><span class="vars">$first</span><span>){&nbsp;</span><span class="comment">//只要tail的next不等于first,就要tail不停的向下走,即$tail=$tail-&gt;next;</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$tail</span><span>=</span><span class="vars">$tail</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//上面的代码,就是生成指向最后一个小孩的$tail</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//当退出while时,我们的$tail就指向了最后这个小孩</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//让$first和$tail向后移动</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//移一下就相当于数了两下,因为还要数自己一下</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//如从1号小朋友到2号小朋友,只移动了一下,那么是1号小朋友数1&nbsp;再数2,因为还数了自己一下。</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//移动2次,相当于数了3下,因为自己数的时候,自己不需要动</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">while</span><span>(</span><span class="vars">$tail</span><span>!=</span><span class="vars">$first</span><span>){&nbsp;</span><span class="comment">//当$tail==$first则说明只有最后一个人了</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>(</span><span class="vars">$i</span><span>=0;</span><span class="vars">$i</span><span>&lt;1;</span><span class="vars">$i</span><span>++){&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$tail</span><span>=</span><span class="vars">$tail</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>=</span><span class="vars">$first</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//把$first指向的节点小孩删除环形链表</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>=</span><span class="vars">$first</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$tail</span><span>-&gt;next=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">echo</span><span class="string">'&lt;br/&gt;最后留在圈圈的人的编号是'</span><span>.</span><span class="vars">$tail</span><span>-&gt;no;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addChild(<span class="vars">){  
  60.                 //思考:因为我们每找到一个小孩,就要把他从环形链表中删除  
  61.                 //为了能够删除某个小孩,我们需要一个辅助变量,该变量指向的小孩在$first前面,在$first的前面,因为是环形的,就相当于在队尾了。  
  62.                 $tail=$first;  
  63.                 while($tail->next!=$first){ //只要tail的next不等于first,就要tail不停的向下走,即$tail=$tail->next;  
  64.                     $tail=$tail->next;  
  65.                 }  
  66.                 //上面的代码,就是生成指向最后一个小孩的$tail  
  67.                 //当退出while时,我们的$tail就指向了最后这个小孩  
  68.   
  69.                 //让$first和$tail向后移动  
  70.                 //移一下就相当于数了两下,因为还要数自己一下  
  71.                 //如从1号小朋友到2号小朋友,只移动了一下,那么是1号小朋友数1 再数2,因为还数了自己一下。  
  72.                 //移动2次,相当于数了3下,因为自己数的时候,自己不需要动  
  73.                 while($tail!=$first){ //当$tail==$first则说明只有最后一个人了  
  74.                     for($i=0;$i<1;$i++){  
  75.                         $tail=$tail->next;  
  76.                         $first=$first->next;  
  77.                     }  
  78.                     //把$first指向的节点小孩删除环形链表  
  79.                     $first=$first->next;  
  80.                     $tail->next=$first;  
  81.                 }  
  82.                 echo'<br/>最后留在圈圈的人的编号是'.$tail->no;  
  83.             }  
  84.   
  85.             addChild(first,n</span><span>);&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;showChild(<span class="vars">);  
  86.             showChild(first);  
  87.   
  88.             //真正来玩游戏  
  89.             countChild($first);  
  90.         ?>  
  91.     </body>  
  92. </html>  
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    </head>
    <body>
        <h1>约瑟夫问题解决</h1>
        <?php
            //先构建一个环形链表,链表上的每个节点,表示一个小朋友
            //小孩类
            class Child{
                public $no;
                public $next=null;
                //构造函数
                public function __construct($no){
                    $this-&gt;no=$no;
                }
            }
            //定义一个指向第一个小朋友的引用
            //定义一个空头
            $first=null;
            $n=4; //$n表示有几个小朋友
            //写一个函数来创建一个四个小朋友的环形链表
            /*
             addChild函数的作用是:把$n个小孩在构建成一个环形链表,$first变量就指向该环形链表的第一个小孩子
             */
            function addChild(&$first,$n){ //此处要加地址符
                //1.头结点不能动 $first不能动,$cur=$first;让cur来帮我们穿针引线
                $cur=$first;
                for($i=0;$i<$n;$i++){
                    $child=new Child($i+1); //为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的
                    //怎么构成一个环形链表呢
                    if($i==0){ //第一个小孩的情况
                        $first=$child; //让first指向child,但是还没有构建环形链表
                        $first-&gt;next=$child; //自己指向自己
                        $cur=$first; //当$i==0的时候,就让cur和first指向同一个地方
                    }else{
                        $cur-&gt;next=$child;
                        $child-&gt;next=$first;
                        //继续指向下一个
                        $cur=$cur->next;
                    }
                }
            }
            //遍历所有的小孩,并显示
            function showChild($first){
                //遍历 cur变量是帮助我们遍历循环列表的,所以不能动
                $cur=$first;
                while($cur-&gt;next!=$first){ //cur没有到结尾,就遍历
                    //显示
                    echo'<br/>小孩的编号是'.$cur->no;
                    //继续
                    $cur=$cur->next;
                }
                //当退出while循环时,已经到了环形链表的最后,即cur此时指向最后一个小孩,所以还要处里一下最后这个小孩节点
                echo'<br/>小孩的编号是'.$cur->no;
            }

            //问题简化,从第一个小孩开始数,数2,看看出拳的顺序
            function countChild($first){
                //思考:因为我们每找到一个小孩,就要把他从环形链表中删除
                //为了能够删除某个小孩,我们需要一个辅助变量,该变量指向的小孩在$first前面,在$first的前面,因为是环形的,就相当于在队尾了。
                $tail=$first;
                while($tail-&gt;next!=$first){ //只要tail的next不等于first,就要tail不停的向下走,即$tail=$tail->next;
                    $tail=$tail->next;
                }
                //上面的代码,就是生成指向最后一个小孩的$tail
                //当退出while时,我们的$tail就指向了最后这个小孩

                //让$first和$tail向后移动
                //移一下就相当于数了两下,因为还要数自己一下
                //如从1号小朋友到2号小朋友,只移动了一下,那么是1号小朋友数1 再数2,因为还数了自己一下。
                //移动2次,相当于数了3下,因为自己数的时候,自己不需要动
                while($tail!=$first){ //当$tail==$first则说明只有最后一个人了
                    for($i=0;$i<1;$i++){
                        $tail=$tail->next;
                        $first=$first->next;
                    }
                    //把$first指向的节点小孩删除环形链表
                    $first=$first->next;
                    $tail-&gt;next=$first;
                }
                echo'<br/>最后留在圈圈的人的编号是'.$tail->no;
            }

            addChild($first,$n);
            showChild($first);

            //真正来玩游戏
            countChild($first);
        ?>
    </body>
</html>

(2)现在把数2做成变量m
韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
josephu4.php

  1. <html>  
  2.     <head>  
  3.         <meta http-equiv=”Content-Type” content=“text/html; charset=gb2312” />  
  4.     </head>  
  5.     <body>  
  6.         <h1>约瑟夫问题解决</h1>  
  7.         <?php  
  8.             //先构建一个环形链表,链表上的每个节点,表示一个小朋友  
  9.             //小孩类  
  10.             class Child{  
  11.                 public no</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="vars">;  
  12.                 public next=null;  
  13.                 //构造函数  
  14.                 public function __construct(no</span><span>){&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$this</span><span>-&gt;no=</span><span class="vars">$no</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//定义一个指向第一个小朋友的引用</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//定义一个空头</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">){  
  15.                     $this->no=$no;  
  16.                 }  
  17.             }  
  18.             //定义一个指向第一个小朋友的引用  
  19.             //定义一个空头  
  20.             first=null;  
  21.             n</span><span>=10;&nbsp;</span><span class="comment">//=10; //n表示有几个小朋友  
  22.             //写一个函数来创建一个四个小朋友的环形链表  
  23.             /* 
  24.              addChild函数的作用是:把 n first变量就指向该环形链表的第一个小孩子 
  25.              */  
  26.             function addChild(& first</span><span>,</span><spanclass="vars"> ,n){ //此处要加地址符  
  27.                 //1.头结点不能动 first不能动</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">  
  28.                 cur=first</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>(</span><span class="vars">;  
  29.                 for(i=0;i</span><span>&lt;</span><span class="vars"><n;i</span><span>++){&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$child</span><span>=</span><span class="keyword">new</span><span>&nbsp;Child(</span><span class="vars">$i</span><span>+1);&nbsp;</span><span class="comment">//为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//怎么构成一个环形链表呢</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(</span><span class="vars">$i</span><span>==0){&nbsp;</span><span class="comment">//第一个小孩的情况</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>=</span><span class="vars">$child</span><span>;&nbsp;</span><span class="comment">//让first指向child,但是还没有构建环形链表</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>-&gt;next=</span><span class="vars">$child</span><span>;&nbsp;</span><span class="comment">//自己指向自己</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<span class="keyword">else</span><span>{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>-&gt;next=</span><span class="vars">$child</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$child</span><span>-&gt;next=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//继续指向下一个</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>=</span><span class="vars">$cur</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//遍历所有的小孩,并显示</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">function</span><span>&nbsp;showChild(</span><span class="vars">++){  
  30.                     $child=new Child($i+1); //为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的  
  31.                     //怎么构成一个环形链表呢  
  32.                     if($i==0){ //第一个小孩的情况  
  33.                         $first=$child//让first指向child,但是还没有构建环形链表  
  34.                         $first->next=$child//自己指向自己  
  35.                         $cur=$first;  
  36.                     }else{  
  37.                         $cur->next=$child;  
  38.                         $child->next=$first;  
  39.                         //继续指向下一个  
  40.                         $cur=$cur->next;  
  41.                     }  
  42.                 }  
  43.             }  
  44.             //遍历所有的小孩,并显示  
  45.             function showChild(first){  
  46.                 //遍历 cur变量是帮助我们遍历循环列表的,所以不能动  
  47.                  cur</span><span>=</span><spanclass="vars"> =first;  
  48.                 while(cur</span><span>-&gt;next!=</span><span class="vars">->next!=first){ //cur没有到结尾,就遍历  
  49.                     //显示  
  50.                     echo‘<br/>小孩的编号是’.cur</span><span>-&gt;no;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//继续</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">->no;  
  51.                     //继续  
  52.                     cur=cur</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//当退出while循环时,已经到了环形链表的最后,即cur此时指向最后一个小孩,所以还要处里一下最后这个小孩节点</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">echo</span><span class="string">'&lt;br/&gt;小孩的编号是'</span><span>.</span><span class="vars">->next;  
  53.                 }  
  54.                 //当退出while循环时,已经到了环形链表的最后,即cur此时指向最后一个小孩,所以还要处里一下最后这个小孩节点  
  55.                 echo'<br/>小孩的编号是'.cur->no;  
  56.             }  
  57.   
  58.             //为了能够删除某个小孩,我们需要一个辅助变量,该变量指向的小孩在 first first的前面,因为是环形的,就相当于在队尾了。  
  59.             m</span><span>=3;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">function</span><span>&nbsp;countChild(</span><span class="vars">=3;  
  60.             function countChild(first,m</span><span>){&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$tail</span><span>=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">while</span><span>(</span><span class="vars">$tail</span><span>-&gt;next!=</span><span class="vars">$first</span><span>){&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$tail</span><span>=</span><span class="vars">$tail</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//当退出while时,我们的$tail就指向了最后这个小孩</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//让$first和$tail向后移动</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//移一下就相当于数了两下,因为还要数自己一下</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//如从1号小朋友到2号小朋友,只移动了一下,那么是1号小朋友数1&nbsp;再数2,因为还数了自己一下。</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//移动2次,相当于数了3下,因为自己数的时候,自己不需要动</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//移动m-1次,相当于数了m下&nbsp;</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">while</span><span>(</span><span class="vars">$tail</span><span>!=</span><span class="vars">$first</span><span>){&nbsp;</span><span class="comment">//当$tail==$first则说明只有最后一个人了</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>(</span><span class="vars">$i</span><span>=0;</span><span class="vars">$i</span><span>&lt;</span><span class="vars">$m</span><span>-1;</span><span class="vars">$i</span><span>++){&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$tail</span><span>=</span><span class="vars">$tail</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>=</span><span class="vars">$first</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//把$first指向的节点小孩删除环形链表</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>=</span><span class="vars">$first</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$tail</span><span>-&gt;next=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">echo</span><span class="string">'&lt;br/&gt;最后留在圈圈的人的编号是'</span><span>.</span><span class="vars">$tail</span><span>-&gt;no;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addChild(<span class="vars">){  
  61.                 $tail=$first;  
  62.                 while($tail->next!=$first){  
  63.                     $tail=$tail->next;  
  64.                 }  
  65.                 //当退出while时,我们的$tail就指向了最后这个小孩  
  66.   
  67.                 //让$first和$tail向后移动  
  68.                 //移一下就相当于数了两下,因为还要数自己一下  
  69.                 //如从1号小朋友到2号小朋友,只移动了一下,那么是1号小朋友数1 再数2,因为还数了自己一下。  
  70.                 //移动2次,相当于数了3下,因为自己数的时候,自己不需要动  
  71.                 //移动m-1次,相当于数了m下   
  72.                 while($tail!=$first){ //当$tail==$first则说明只有最后一个人了  
  73.                     for($i=0;$i<$m-1;$i++){  
  74.                         $tail=$tail->next;  
  75.                         $first=$first->next;  
  76.                     }  
  77.                     //把$first指向的节点小孩删除环形链表  
  78.                     $first=$first->next;  
  79.                     $tail->next=$first;  
  80.                 }  
  81.                 echo'<br/>最后留在圈圈的人的编号是'.$tail->no;  
  82.             }  
  83.   
  84.             addChild(first,n</span><span>);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;showChild(<span class="vars">);  
  85.             showChild(first);  
  86.   
  87.             //真正来玩游戏  
  88.             countChild( first</span><span>,</span><spanclass="vars"> ,m);  
  89.         ?>  
  90.     </body>  
  91. </html>  
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    </head>
    <body>
        <h1>约瑟夫问题解决</h1>
        <?php
            //先构建一个环形链表,链表上的每个节点,表示一个小朋友
            //小孩类
            class Child{
                public $no;
                public $next=null;
                //构造函数
                public function __construct($no){
                    $this-&gt;no=$no;
                }
            }
            //定义一个指向第一个小朋友的引用
            //定义一个空头
            $first=null;
            $n=10; //$n表示有几个小朋友
            //写一个函数来创建一个四个小朋友的环形链表
            /*
             addChild函数的作用是:把$n个小孩在构建成一个环形链表,$first变量就指向该环形链表的第一个小孩子
             */
            function addChild(&$first,$n){ //此处要加地址符
                //1.头结点不能动 $first不能动
                $cur=$first;
                for($i=0;$i<$n;$i++){
                    $child=new Child($i+1); //为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的
                    //怎么构成一个环形链表呢
                    if($i==0){ //第一个小孩的情况
                        $first=$child; //让first指向child,但是还没有构建环形链表
                        $first-&gt;next=$child; //自己指向自己
                        $cur=$first;
                    }else{
                        $cur-&gt;next=$child;
                        $child-&gt;next=$first;
                        //继续指向下一个
                        $cur=$cur->next;
                    }
                }
            }
            //遍历所有的小孩,并显示
            function showChild($first){
                //遍历 cur变量是帮助我们遍历循环列表的,所以不能动
                $cur=$first;
                while($cur-&gt;next!=$first){ //cur没有到结尾,就遍历
                    //显示
                    echo'<br/>小孩的编号是'.$cur->no;
                    //继续
                    $cur=$cur->next;
                }
                //当退出while循环时,已经到了环形链表的最后,即cur此时指向最后一个小孩,所以还要处里一下最后这个小孩节点
                echo'<br/>小孩的编号是'.$cur->no;
            }

            //为了能够删除某个小孩,我们需要一个辅助变量,该变量指向的小孩在$first前面,在$first的前面,因为是环形的,就相当于在队尾了。
            $m=3;
            function countChild($first,$m){
                $tail=$first;
                while($tail-&gt;next!=$first){
                    $tail=$tail->next;
                }
                //当退出while时,我们的$tail就指向了最后这个小孩

                //让$first和$tail向后移动
                //移一下就相当于数了两下,因为还要数自己一下
                //如从1号小朋友到2号小朋友,只移动了一下,那么是1号小朋友数1 再数2,因为还数了自己一下。
                //移动2次,相当于数了3下,因为自己数的时候,自己不需要动
                //移动m-1次,相当于数了m下 
                while($tail!=$first){ //当$tail==$first则说明只有最后一个人了
                    for($i=0;$i<$m-1;$i++){
                        $tail=$tail->next;
                        $first=$first->next;
                    }
                    //把$first指向的节点小孩删除环形链表
                    $first=$first->next;
                    $tail-&gt;next=$first;
                }
                echo'<br/>最后留在圈圈的人的编号是'.$tail->no;
            }

            addChild($first,$n);
            showChild($first);

            //真正来玩游戏
            countChild($first,$m);
        ?>
    </body>
</html>

(3)再考虑从第几个人数的问题,变量k;和出列显示
韩顺平_PHP程序员玩转算法公开课(第一季)05_使用单链表解决约瑟夫问题_学习笔记_源代码图解_PPT文档整理
josephu5.php
  1. <html>  
  2.     <head>  
  3.         <meta http-equiv=”Content-Type” content=“text/html; charset=gb2312” />  
  4.     </head>  
  5.     <body>  
  6.         <h1>约瑟夫问题解决</h1>  
  7.         <?php  
  8.             //先构建一个环形链表,链表上的每个节点,表示一个小朋友  
  9.             //小孩类  
  10.             class Child{  
  11.                 public no</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="vars">;  
  12.                 public next=null;  
  13.                 //构造函数  
  14.                 public function __construct(no</span><span>){&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$this</span><span>-&gt;no=</span><span class="vars">$no</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//定义一个指向第一个小朋友的引用</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//定义一个空头</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">){  
  15.                     $this->no=$no;  
  16.                 }  
  17.             }  
  18.             //定义一个指向第一个小朋友的引用  
  19.             //定义一个空头  
  20.             first=null;  
  21.             n</span><span>=10;&nbsp;</span><span class="comment">//=10; //n表示有几个小朋友  
  22.             //写一个函数来创建一个四个小朋友的环形链表  
  23.             /* 
  24.              addChild函数的作用是:把 n first变量就指向该环形链表的第一个小孩子 
  25.              */  
  26.             function addChild(& first</span><span>,</span><spanclass="vars"> ,n){ //此处要加地址符  
  27.                 //1.头结点不能动 first不能动</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">  
  28.                 cur=first</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>(</span><span class="vars">;  
  29.                 for(i=0;i</span><span>&lt;</span><span class="vars"><n;i</span><span>++){&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$child</span><span>=</span><span class="keyword">new</span><span>&nbsp;Child(</span><span class="vars">$i</span><span>+1);&nbsp;</span><span class="comment">//为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//怎么构成一个环形链表呢</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(</span><span class="vars">$i</span><span>==0){&nbsp;</span><span class="comment">//第一个小孩的情况</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>=</span><span class="vars">$child</span><span>;&nbsp;</span><span class="comment">//让first指向child,但是还没有构建环形链表</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>-&gt;next=</span><span class="vars">$child</span><span>;&nbsp;</span><span class="comment">//自己指向自己</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<span class="keyword">else</span><span>{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>-&gt;next=</span><span class="vars">$child</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$child</span><span>-&gt;next=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//继续指向下一个</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$cur</span><span>=</span><span class="vars">$cur</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//遍历所有的小孩,并显示</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">function</span><span>&nbsp;showChild(</span><span class="vars">++){  
  30.                     $child=new Child($i+1); //为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的  
  31.                     //怎么构成一个环形链表呢  
  32.                     if($i==0){ //第一个小孩的情况  
  33.                         $first=$child//让first指向child,但是还没有构建环形链表  
  34.                         $first->next=$child//自己指向自己  
  35.                         $cur=$first;  
  36.                     }else{  
  37.                         $cur->next=$child;  
  38.                         $child->next=$first;  
  39.                         //继续指向下一个  
  40.                         $cur=$cur->next;  
  41.                     }  
  42.                 }  
  43.             }  
  44.             //遍历所有的小孩,并显示  
  45.             function showChild(first){  
  46.                 //遍历 cur变量是帮助我们遍历循环列表的,所以不能动  
  47.                  cur</span><span>=</span><spanclass="vars"> =first;  
  48.                 while(cur</span><span>-&gt;next!=</span><span class="vars">->next!=first){ //cur没有到结尾,就遍历  
  49.                     //显示  
  50.                     echo‘<br/>小孩的编号是’.cur</span><span>-&gt;no;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//继续</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">->no;  
  51.                     //继续  
  52.                     cur=cur</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//当退出while循环时,已经到了环形链表的最后,即cur此时指向最后一个小孩,所以还要处里一下最后这个小孩节点</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">echo</span><span class="string">'&lt;br/&gt;小孩的编号是'</span><span>.</span><span class="vars">->next;  
  53.                 }  
  54.                 //当退出while循环时,已经到了环形链表的最后,即cur此时指向最后一个小孩,所以还要处里一下最后这个小孩节点  
  55.                 echo'<br/>小孩的编号是'.cur->no;  
  56.             }  
  57.   
  58.             //为了能够删除某个小孩,我们需要一个辅助变量,该变量指向的小孩在 first first的前面,因为是环形的,就相当于在队尾了。  
  59.             m</span><span>=3;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">=3;  
  60.             k=2;  
  61.             function countChild( first</span><span>,</span><spanclass="vars"> ,m,k</span><span>){&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$tail</span><span>=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">while</span><span>(</span><span class="vars">$tail</span><span>-&gt;next!=</span><span class="vars">$first</span><span>){&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$tail</span><span>=</span><span class="vars">$tail</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//考虑是从第几个人开始数的问题,变量k</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//首先要定位</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//因为动一下,就相当于数了两下,算上自己了,所以k-1</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>(</span><span class="vars">$i</span><span>=0;</span><span class="vars">$i</span><span>&lt;</span><span class="vars">$k</span><span>-1;</span><span class="vars">$i</span><span>++){&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$tail</span><span>=</span><span class="vars">$tail</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>=</span><span class="vars">$first</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//当退出while时,我们的$tail就指向了最后这个小孩</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//让$first和$tail向后移动</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//移一下就相当于数了两下,因为还要数自己一下</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//如从1号小朋友到2号小朋友,只移动了一下,那么是1号小朋友数1&nbsp;再数2,因为还数了自己一下。</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//移动2次,相当于数了3下,因为自己数的时候,自己不需要动</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//移动m-1次,相当于数了m下&nbsp;</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">while</span><span>(</span><span class="vars">$tail</span><span>!=</span><span class="vars">$first</span><span>){&nbsp;</span><span class="comment">//当$tail==$first则说明只有最后一个人了</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>(</span><span class="vars">$i</span><span>=0;</span><span class="vars">$i</span><span>&lt;</span><span class="vars">$m</span><span>-1;</span><span class="vars">$i</span><span>++){&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$tail</span><span>=</span><span class="vars">$tail</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>=</span><span class="vars">$first</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//把$first指向的节点小孩删除环形链表</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//出列显示,应该在first没有改变之前先打印输出</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">echo</span><span class="string">'&lt;br/&gt;出圈的人的编号是'</span><span>.</span><span class="vars">$first</span><span>-&gt;no;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$first</span><span>=</span><span class="vars">$first</span><span>-&gt;next;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="vars">$tail</span><span>-&gt;next=</span><span class="vars">$first</span><span>;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="func">echo</span><span class="string">'&lt;br/&gt;最后留在圈圈的人的编号是'</span><span>.</span><span class="vars">$tail</span><span>-&gt;no;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addChild(<span class="vars">){  
  62.                 $tail=$first;  
  63.                 while($tail->next!=$first){  
  64.                     $tail=$tail->next;  
  65.                 }  
  66.   
  67.                 //考虑是从第几个人开始数的问题,变量k  
  68.                 //首先要定位  
  69.                 //因为动一下,就相当于数了两下,算上自己了,所以k-1  
  70.                 for($i=0;$i<$k-1;$i++){  
  71.                     $tail=$tail->next;  
  72.                     $first=$first->next;  
  73.                 }  
  74.   
  75.                 //当退出while时,我们的$tail就指向了最后这个小孩  
  76.   
  77.                 //让$first和$tail向后移动  
  78.                 //移一下就相当于数了两下,因为还要数自己一下  
  79.                 //如从1号小朋友到2号小朋友,只移动了一下,那么是1号小朋友数1 再数2,因为还数了自己一下。  
  80.                 //移动2次,相当于数了3下,因为自己数的时候,自己不需要动  
  81.                 //移动m-1次,相当于数了m下   
  82.                 while($tail!=$first){ //当$tail==$first则说明只有最后一个人了  
  83.                     for($i=0;$i<$m-1;$i++){  
  84.                         $tail=$tail->next;  
  85.                         $first=$first->next;  
  86.                     }  
  87.                     //把$first指向的节点小孩删除环形链表  
  88.                     //出列显示,应该在first没有改变之前先打印输出  
  89.                     echo'<br/>出圈的人的编号是'.$first->no;  
  90.                     $first=$first->next;  
  91.                     $tail->next=$first;  
  92.                 }  
  93.                 echo'<br/>最后留在圈圈的人的编号是'.$tail->no;  
  94.             }  
  95.   
  96.             addChild(first,n</span><span>);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;showChild(<span class="vars">);  
  97.             showChild(first);  
  98.   
  99.             //真正来玩游戏  
  100.             countChild( first</span><span>,</span><spanclass="vars"> ,m,$k);  
  101.         ?>  
  102.     </body>  
  103. </html>  
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    </head>
    <body>
        <h1>约瑟夫问题解决</h1>
        <?php
            //先构建一个环形链表,链表上的每个节点,表示一个小朋友
            //小孩类
            class Child{
                public $no;
                public $next=null;
                //构造函数
                public function __construct($no){
                    $this-&gt;no=$no;
                }
            }
            //定义一个指向第一个小朋友的引用
            //定义一个空头
            $first=null;
            $n=10; //$n表示有几个小朋友
            //写一个函数来创建一个四个小朋友的环形链表
            /*
             addChild函数的作用是:把$n个小孩在构建成一个环形链表,$first变量就指向该环形链表的第一个小孩子
             */
            function addChild(&$first,$n){ //此处要加地址符
                //1.头结点不能动 $first不能动
                $cur=$first;
                for($i=0;$i<$n;$i++){
                    $child=new Child($i+1); //为什么要加1,因为for循环中i是从开始的,但是小朋友的编号是从1开始的
                    //怎么构成一个环形链表呢
                    if($i==0){ //第一个小孩的情况
                        $first=$child; //让first指向child,但是还没有构建环形链表
                        $first-&gt;next=$child; //自己指向自己
                        $cur=$first;
                    }else{
                        $cur-&gt;next=$child;
                        $child-&gt;next=$first;
                        //继续指向下一个
                        $cur=$cur->next;
                    }
                }
            }
            //遍历所有的小孩,并显示
            function showChild($first){
                //遍历 cur变量是帮助我们遍历循环列表的,所以不能动
                $cur=$first;
                while($cur-&gt;next!=$first){ //cur没有到结尾,就遍历
                    //显示
                    echo'<br/>小孩的编号是'.$cur->no;
                    //继续
                    $cur=$cur->next;
                }
                //当退出while循环时,已经到了环形链表的最后,即cur此时指向最后一个小孩,所以还要处里一下最后这个小孩节点
                echo'<br/>小孩的编号是'.$cur->no;
            }

            //为了能够删除某个小孩,我们需要一个辅助变量,该变量指向的小孩在$first前面,在$first的前面,因为是环形的,就相当于在队尾了。
            $m=3;
            $k=2;
            function countChild($first,$m,$k){
                $tail=$first;
                while($tail-&gt;next!=$first){
                    $tail=$tail->next;
                }

                //考虑是从第几个人开始数的问题,变量k
                //首先要定位
                //因为动一下,就相当于数了两下,算上自己了,所以k-1
                for($i=0;$i<$k-1;$i++){
                    $tail=$tail->next;
                    $first=$first->next;
                }

                //当退出while时,我们的$tail就指向了最后这个小孩

                //让$first和$tail向后移动
                //移一下就相当于数了两下,因为还要数自己一下
                //如从1号小朋友到2号小朋友,只移动了一下,那么是1号小朋友数1 再数2,因为还数了自己一下。
                //移动2次,相当于数了3下,因为自己数的时候,自己不需要动
                //移动m-1次,相当于数了m下 
                while($tail!=$first){ //当$tail==$first则说明只有最后一个人了
                    for($i=0;$i<$m-1;$i++){
                        $tail=$tail->next;
                        $first=$first->next;
                    }
                    //把$first指向的节点小孩删除环形链表
                    //出列显示,应该在first没有改变之前先打印输出
                    echo'<br/>出圈的人的编号是'.$first->no;
                    $first=$first->next;
                    $tail-&gt;next=$first;
                }
                echo'<br/>最后留在圈圈的人的编号是'.$tail->no;
            }

            addChild($first,$n);
            showChild($first);

            //真正来玩游戏
            countChild($first,$m,$k);
        ?>
    </body>
</html>

关键是要在脑海中,有一个内存分布和运行的大致图。
一旦人多了,比如4000个人,从第31个人,数20,这时候就发现程序的力量了,你人工去数,可想而知。
用程序来完成你能完成的事情,但是是快速的完成。
找工作的时候,很容易被考的问题:约瑟夫问题,排序和查找,二叉树的遍历,前序遍历后序遍历,霍夫曼数,最小堆等
有档次的公司都喜欢考算法

韩顺平_PHP程序员玩转算法公开课_学习笔记_源代码图解_PPT文档整理_目录