- 单链表反转
- 链表中环的检测
- 两个有序的链表合并
- 删除链表倒数第 n 个结点
- 求链表的中间结点
<?php
/**
* 单链表相关算法
*
* reverse 单链表反转
* checkCircle 链表中环的检测
* mergerSortedList 两个有序的链表合并
* deleteLastKth 删除链表倒数第n个结点
* findMiddleNode 求链表的中间结点
*
*/
Class SingleLinkedListAlgo
{
/**
* 单链表
*
* @var
*/
public $list;
/**
* 构造函数设置$list
*
* SingleLinkedListAlgo constructor.
*
* @param SingleLinkedList $list
*/
public function __construct(SingleLinkedList $list = null)
{
$this->list = $list;
}
/**
* 设置单链表
*
* @param SingleLinkedList $list
*/
public function setList(SingleLinkedList $list)
{
$this->list = $list;
}
/**
* 单链表反转
*
* 三个指针反转
* preNode 指向前一个结点
* curNode 指向当前结点
* remainNode 指向当前结点的下一个节点(保存未逆序的链表,为了在断开curNode的next指针后能找到后续节点)
*
* @return bool
*/
public function reverse()
{
if (null == $this->list || null == $this->list->head || null == $this->list->head->next) {
return false;
}
$preNode = null;
$curNode = $this->list->head->next;
$remainNode = null;
// 保存头结点,稍后指向反转后的链表
$headNode = $this->list->head;
// 断开头结点的next指针
$this->list->head->next = null;
while ($curNode != null) {
$remainNode = $curNode->next;
$curNode->next = $preNode;
$preNode = $curNode;
$curNode = $remainNode;
}
// 头结点指向反转后的链表
$headNode->next = $preNode;
return true;
}
/**
* 判断链表是否有环
*
* 快慢指针判断是否有环
* @link http://t.cn/ROxpgQ1
*
* @return bool
*/
public function checkCircle()
{
if (null == $this->list || null == $this->list->head || null == $this->list->head->next) {
return false;
}
$slow = $this->list->head->next;
$fast = $this->list->head->next;
while ($fast != null && $fast->next != null) {
$fast = $fast->next->next;
$slow = $slow->next;
// 如果慢指针跟快指针相遇了说明有环 解释在上面的链接中
if ($slow === $fast) {
return true;
}
}
return false;
}
/**
* 合并两个有序链表
*
* @param SingleLinkedList $listA
* @param SingleLinkedList $listB
*
* @return SingleLinkedList|\Algo_06\SingleLinkedListNode
*/
public function mergerSortedList(SingleLinkedList $listA, SingleLinkedList $listB)
{
if (null == $listA) {
return $listB;
}
if (null == $listB) {
return $listA;
}
$pListA = $listA->head->next;
$pListB = $listB->head->next;
$newList = new SingleLinkedList();
$newHead = $newList->head;
$newRootNode = $newHead;
while ($pListA != null && $pListB != null) {
if ($pListA->data <= $pListB->data) {
$newRootNode->next = $pListA;
$pListA = $pListA->next;
} else {
$newRootNode->next = $pListB;
$pListB = $pListB->next;
}
$newRootNode = $newRootNode->next;
}
// 如果第一个链表未处理完,拼接到新链表后面
if ($pListA != null) {
$newRootNode->next = $pListA;
}
// 如果第二个链表未处理完,拼接到新链表后面
if ($pListB != null) {
$newRootNode->next = $pListB;
}
return $newList;
}
/**
* 删除链表倒数第n个结点
*
* @param $index
*
* @return bool
*/
public function deleteLastKth($index)
{
if (null == $this->list || null == $this->list->head || null == $this->list->head->next) {
return false;
}
$i = 1;
$slow = $this->list->head;
$fast = $this->list->head;
while ($fast != null && $i < $index) {
$fast = $fast->next;
++$i;
}
if ($fast == null) {
return true;
}
$pre = null;
while($fast->next != null) {
$pre = $slow;
$slow = $slow->next;
$fast = $fast->next;
}
if (null == $pre) {
$this->list->head->next = $slow->next;
} else {
$pre->next = $pre->next->next;
}
return true;
}
/**
* 寻找中间节点
*
* 快慢指针遍历
*
* @return \Algo_06\SingleLinkedListNode|bool|null
*/
public function findMiddleNode()
{
if (null == $this->list || null == $this->list->head || null == $this->list->head->next) {
return false;
}
$slow = $this->list->head->next;
$fast = $this->list->head->next;
while ($fast != null && $fast->next != null) {
$fast = $fast->next->next;
$slow = $slow->next;
}
return $slow;
}
}
$list = new SingleLinkedList();
$list->insert(1);
$list->insert(2);
$list->insert(3);
$list->insert(4);
$list->insert(5);
$list->insert(6);
$list->insert(7);
// 单链表反转
echo "单链表反转 \n";
$listAlgo = new SingleLinkedListAlgo($list);
$listAlgo->list->printList();
$listAlgo->reverse();
$listAlgo->list->printList();
// 链表中环的检测
echo "\n链表中环的检测 \n";
$listCircle = new SingleLinkedList();
$listCircle->buildHasCircleList();
$listAlgo->setList($listCircle);
var_dump($listAlgo->checkCircle());
// 两个有序的链表合并
echo "\n两个有序的链表合并 \n";
$listA = new SingleLinkedList();
$listA->insert(9);
$listA->insert(7);
$listA->insert(5);
$listA->insert(3);
$listA->insert(1);
$listA->printList();
$listB = new SingleLinkedList();
$listB->insert(10);
$listB->insert(8);
$listB->insert(6);
$listB->insert(4);
$listB->insert(2);
$listB->printList();
$listAlgoMerge = new SingleLinkedListAlgo();
$newList = $listAlgoMerge->mergerSortedList($listA, $listB);
$newList->printListSimple();
// 删除链表倒数第n个结点
echo "\n删除链表倒数第n个结点 \n";
$listDelete = new SingleLinkedList();
$listDelete->insert(1);
$listDelete->insert(2);
$listDelete->insert(3);
$listDelete->insert(4);
$listDelete->insert(5);
$listDelete->insert(6);
$listDelete->insert(7);
$listDelete->printList();
$listAlgo->setList($listDelete);
$listAlgo->deleteLastKth(3);
var_dump($listAlgo->list->printListSimple());
// 求链表的中间结点
echo "\n求链表的中间结点 \n";
$listAlgo->setList($list);
$middleNode = $listAlgo->findMiddleNode();
var_dump($middleNode->data);
echo "\n";