<?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();