2 PHP实现单向链表相关操作

<?php
// 节点
class Node {
    public $data = null;
    public $next = null;

    public function __construct($value = 0, $next = null) {
        $this->data = $value;
        $this->next = $next;
    }
}

// 单链表
class LinkList {

    public $head;// 头结点用于存储链表长度和指向后面结点

    public function __construct() {
        $this->head = new Node();
        $this->head->data = 0;
    }

    // 批量创建新节点
    public function CreateManyLinkList($size) {
        //在当前链表后面创建多个
        if ($size <= 0 ) {
            throw new Exception("创建范围不合法");
        }

        $prev = $this->head;

        // 处理之前已经有元素的链表
        while ($prev->next != null ) {
            $prev = $prev->next;//这样就一直移动到了最后一位
        }

        for ($i=1; $i <= $size; $i++) {
            $prev->next = new Node(0, null);
            $prev = $prev->next;
        }

        $this->head->data += $size;
    }

    public function ListInsert($index, $value) {
        if ($index > $this->head->data || $index <= 0) {
            throw new Exception("添加位置超出了链表范围");
        }

        $prev = $this->head;// 如果添加的位置为0就是这个  如果不为0 就是下面的循环
        for ($i=1; $i < $index; $i++) { 
            $prev = $prev->next;
        }

        // 这里的$prev->next为原来的下一个节点 现在通过new添加了一个新的 而新的节点被赋值到了$prev->next变量中 换句话说就是替换了原来指向的数据,而原来节点的数据被新建的节点所使用 用来给自己的next属性赋值 相当于新的节点的next指向了原来$prev->next所指向的位置
        $prev->next = new Node($value, $prev->next);

        // 因为添加了新的节点 所以链表长度加1
        $this->head->data++;
    }

    public function ListDelete($index) {
        if ($index > $this->head->data || $index <= 0) {
            throw new Exception("超出链表范围");
        }

        $prev = $this->head;
        for ($i=1; $i <= $index; $i++) {
            if ($i == $index) {
                $q = $prev->next;
                $prev->next = $q->next;
                //$prev->next = $prev->next->next;
            } else {
                $prev = $prev->next;// 每一次迭代都要更新$prev的值为下一个元素的值
            }
        }

        $this->head->data--;// 删除了之后对节点数量减一
    }

    public function ListEmpty() {
        if ($this->head->data == 0) {
            return true;
        } else {
            return false;
        }
    }

    public function ClearList() {
        $this->head->next = new Node();
        $this->head->data = 0;
    }

    public function GetElem($index) {
        if ($index > $this->head->data || $index <= 0) {
            throw new Exception("超出链表范围");
        }

        $prev = $this->head->next;
        for ($i=1; $i <= $index; $i++) { 
            if ($i == $index) {
                return $prev->data;
            } else {
                $prev = $prev->next;// 一直向后迭代
            }
        }
    }

    public function LocateElem($value) {
        $prev = $this->head->next;
        while ($prev) {// 最后一个的next将为null
            if ($prev->data == $value) {
                return true;
            } else {
                $prev = $prev->next;
            }
        }

        return false;
    }

    // 根据索引设置元素值
    public function setElem($index, $value) {
        if ($index > $this->head->data || $index <= 0) {
            throw new Exception("超出链表范围");
        }

        $prev = $this->head->next;
        for ($i=1; $i <= $index; $i++) { 
            if ($i == $index) {
                $prev->data = $value;
            } else {
                $prev = $prev->next;
            }
        }
    }

    public function ListLenght() {
        return $this->head->data;
    }

}

$linkList = new LinkList();
$linkList->CreateManyLinkList(3);
$linkList->ListInsert(1,999);
$linkList->setElem(1,555);
$linkList->ListInsert(3,44);
$linkList->ListInsert(4,66);
$linkList->ListInsert(5,77);
var_dump($linkList->LocateElem(66));
var_dump($linkList->GetElem(5));
$linkList->ListDelete(5);
$linkList->setElem(6,999);
print_r($linkList);
// var_dump($linkList->ListLenght());

单向链表总结

优点

单向链表在确定元素位置时时间复杂度为O(n),确定后在添加和删除元素时的时间复杂度为O(1)

在内存中不必预先申请一整块内存,可以使用分散的内存进行存储

缺点

如果要查询元素,时间复杂度为O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值