PHP实现的单向链表,实现了迭代器接口和数组访问接口

#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]);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值