php链表笔记:链表的检测

<?php
/**
 * Created by PhpStorm.
 * User: huizhou
 * Date: 2018/12/2
 * Time: 11:48
 */

/**
 * 链表的检测
 * Class CheckCirclesList
 */

/**
 * 单链表类
 */
class Node{
    private $next;
    private $value;

    public function __construct($value = null)
    {
        $this->value = $value;
    }

    public function getValue(){
        return $this->value;
    }

    public function setValue($value){
        $this->value = $value;
    }

    public function getNext(){
        return $this->next;
    }

    public function setNext($next){
        $this->next = $next;
    }

}



/**
 * 找出带环链表的环的入口结点
 * @param Node $pHead
 * @return Node
 */
function entryNodeOfLoop(Node $pHead){
    $slow = $pHead;
    $fast = $pHead;

    while ($fast != null && $fast->getNext() !=null ){

        /**
            单链表中环的检测
            首先设置两个指针,分别命名为fast和slow,fast指针每次向后移2步,slow指针每次向后移1步。
            如果,fast指针最后走到尾结点,则没有环。
            如果,fast指针和slow指针相遇,则证明有环。
        **/
        $slow = $slow->getNext(); // 慢指针走一步
        $fast = $fast->getNext()->getNext(); // 快指针走两步

        // 快慢指针环内相遇
        if($slow === $fast){
            // 快指针回到头结点
            $fast = $pHead;
            // 同一速度再同时走
            while ($slow != $fast){
                $slow = $slow->getNext();
                $fast = $fast->getNext();
            }

            /**
                环的起始结点的查询
                当fast与slow相遇之后,
                fast指针从头结点开始走,每次走1步
                当fast再次与slow相遇以后,相遇处的结点为环的入口结点
            **/
            // 两个相遇的点一定是环的入口
            if ($slow == $fast){
                return $fast;
            }
        }
    }
}


function test(){
    // 创建一个带环的链表
    $linkList = new Node();
    $temp = $linkList;

    $node1 = new Node('1');
    $temp->setNext($node1);
    $temp = $node1;


    $node2 = new Node('2');
    $temp->setNext($node2);
    $temp = $node2;

    $node3 = new Node('3');
    $temp->setNext($node3);
    $temp = $node3;

    $node4 = new Node('4');
    $temp->setNext($node4);
    $node4->setNext($node2); // 尾节点指向第二个节点

    //打印环
    var_dump($linkList);

    //打印入口节点
    $result = entryNodeOfLoop($linkList);
    var_dump($result);

}

test();

 

posted @ 2018-12-02 14:36  QinXiao.Shou  阅读(284)  评论(0编辑  收藏  举报