#PHP实现的单向链表,实现了迭代器接口和数组访问接口
<?php
/**
* Created by PhpStorm.
* Author: xinu x-php@outlook.com
* Coding Standard: PSR2
* DateTime: 2020-09-08 17:50
* php版本链表 实现迭代器,数组访问接口
*/
/**
* Class LinkedList
*/
class LinkedList implements Iterator, ArrayAccess
{
private ?ListNode $head = null; // 头节点
private int $currentPosition = 0; // 迭代器定位
private ?ListNode $currentNode = null; // 迭代器当前节点
private int $len = 0; // 链表长度
private function checkIndex($index): ?bool
{
if ($index < 0 || $index >= $this->len) {
throw new LogicException(sprintf('无效偏移量,偏移量的有效范围为 0-%d', $this->len() - 1));
}
return true;
}
public function push($value): bool
{
return $this->insert($value, $this->len());
}
public function pop()
{
if (0 === $this->len) {
return false;
}
$index = $this->len - 1;
$node = $this->getHead();
$value = null;
if (0 === $index) {
$value = $node->val;
$this->setHead($node->next);
$this->lenAdd(-1);
return $value;
}
$oriIndex = 1;
while ($node) {
if ($index === $oriIndex) {
break;
}
++$oriIndex;
$node = $node->next;
}
$value = $node->next->val;
$node->next = $node->next->next ?? null;
$this->lenAdd(-1);
return $value;
}
public function get(int $index)
{
$this->checkIndex($index);
$node = $this->getHead();
$oriIndex = 0;
while ($node) {
if ($index === $oriIndex) {
return $node->val;
}
++$oriIndex;
$node = $node->next;
}
return false;
}
public function set(int $index, $value): bool
{
$this->checkIndex($index);
$node = $this->getHead();
$oriIndex = 0;
while ($node) {
if ($index === $oriIndex) {
$node->val = $value;
return true;
}
++$oriIndex;
$node = $node->next;
}
return false;
}
/**
* Desc:
* Author: xinu
* Time: 2020-09-09 14:09
* @param $value
* @return false|int
*/
public function search($value)
{
$node = $this->getHead();
$index = 0;
while ($node) {
if ($value === $node->val) {
return $index;
}
++$index;
$node = $node->next;
}
return false;
}
public function delete(int $index): bool
{
$this->checkIndex($index);
$node = $this->getHead();
if (0 === $index) {
$this->setHead($node->next);
$this->lenAdd(-1);
return true;
}
$oriIndex = 1;
while ($node) {
if ($index === $oriIndex) {
break;
}
++$oriIndex;
$node = $node->next;
}
$node->next = $node->next->next ?? null;
$this->lenAdd(-1);
return true;
}
/**
* Desc: 获取链表头节点
* Author: xinu
* Time: 2020-09-09 11:23
* @return ListNode|null
*/
public function getHead(): ?ListNode
{
return $this->head;
}
public function setHead(?ListNode $node): void
{
$this->head = $node;
}
/**
* Desc: 判断是否为空链表
* Author: xinu
* Time: 2020-09-09 11:29
*/
public function isEmpty(): bool
{
return empty($this->head);
}
public function len(): int
{
return $this->len;
}
/**
* Desc: 向链表中插入元素
* Author: xinu
* Time: 2020-09-09 11:22
* @param $value
* @param int $index
* @return bool
*/
public function insert($value, int $index = 0): bool
{
if ($index < 0 || $index > $this->len) {
throw new LogicException('无效偏移量' . $index . $this->len());
}
$node = $this->getHead();
if (0 === $index) {
$this->setHead(new ListNode($value, $node));
$this->lenAdd();
return true;
}
$originalIndex = 1;
while ($node->next !== null) {
if ($originalIndex === $index) {
break;
}
$originalIndex++;
$node = $node->next;
}
$node->next = new ListNode($value, $node->next);
$this->lenAdd();
return true;
}
private function lenAdd($step = 1): void
{
$this->len += $step;
}
public function print(): void
{
echo "====开始打印===\n";
$node = $this->getHead();
while ($node) {
echo $node->val . ',';
$node = $node->next;
}
}
public function current()
{
return $this->currentNode->val;
}
public function next(): void
{
$this->currentNode = $this->currentNode->next;
$this->currentPosition++;
}
public function key()
{
return $this->currentPosition;
}
public function valid(): bool
{
return $this->currentPosition < $this->len;
}
public function rewind(): void
{
$this->currentNode = $this->getHead();
$this->currentPosition = 0;
}
public function offsetExists($offset): ?bool
{
return $this->checkIndex($offset);
}
public function offsetGet($offset)
{
$this->checkIndex($offset);
return $this->get($offset);
}
public function offsetSet($offset, $value): void
{
$this->checkIndex($offset);
$this->set($offset, $value);
}
public function offsetUnset($offset): void
{
$this->checkIndex($offset);
$this->delete($offset);
}
}
/**
* Class ListNode
*/
class ListNode
{
public $next;
public ?int $val = '';
public function __construct($val, $next = null)
{
$this->val = $val;
$this->next = $next;
}
}
$linklist = new LinkedList();
var_dump($linklist->pop());
$linklist->push(1);
$linklist->push(2);
$linklist->push(3);
$linklist->push(4);
$linklist->push(5);
var_dump($linklist->pop());
var_dump($linklist->len());
var_dump($linklist[2]);