链表的php实现


class Node
{
    public $data;
    public $next;

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

class singleLinkList{

    /**
     * 头插法创建链表
     */
    public function headInsert($n)
    {
        $head = new node(null,null);

        for($i=0;$i<$n;$i++)
        {
            $newNode = new node($i,null);

            $newNode->next = $head->next;

            $head->next=$newNode;
        }

        return $head;
    }

    /**
     * 尾插法创建链表
     * @param $n int 链表元素个数
     * @return $rear  返回链表对象
     */
    public function rearInsert($n)
    {
        //指向表尾节点的指针
        $head = $rear = new Node(null,null);
        for($i=0;$i<$n;$i++)
        {
            $newNode = new Node($i+1,null);

            //将表尾节点的指针指向新节点
            $rear->next = $newNode;

            //将当前的新节点定义为表尾终端节点
            $rear = $newNode;
        }

        //循环结束后最终的尾节点的指针赋值null
        $rear->next = null;
        return $head;
    }

    /**
     * 读取第i个元素
     * @param $list
     * @param $i
     */
    public function readNode($list,$i)
    {
        if ($list == null || $i <= 0)
        {
            return;
        }

        $p = $list->next;

        $j=0;

        while($p && $j<$i)
        {
            $p = $p->next;
            $j++;
        }
        if($p == null)
        {
            echo 'i长度大于链表长度';
            return;
        }else{
            $e = $p->data;
            return $e;
        }
    }

    /**
     * 删除链表的第i个元素 并返回该节点的值
     * @param $list
     * @param $i
     * @return mixed
     */
    public function delete($list,$i)
    {
        if ($list == null || $i < 0)
        {
            echo '参数不合法';
            exit;
        }

        $p = $list->next;

        $j = 1;

        while($p && $j<$i)
        {
            $p = $p->next;
            $j++;
        }

        if($p == null)
        {
            echo '不存在节点i';
        }else{
            $q = $p->next;
            $p->next = $q->next;
            $e = $q->data;

            unset($q);
            return $e;
        }
    }

    /**
     * 删除整张链表
     */
    public function deleteAll($list)
    {
        if ($list == null)
        {
            echo '参数不合法';
            return;
        }

        $p = $list->next;

        while ($p != null)
        {
            //保证节点在向后移动
            $q = $p->next;
            unset($p);
            $p = $q;
        }

        return;
    }

    /**
     * 输出倒数第K个节点
     */
    public function findNodeToTail($list,$k)
    {
        if($list == null || $k<0)
        {
            echo '参数不合法';
            return;
        }

        /*    这里采用了复杂度为O(n)的算法,需要准备两个节点    */
        $behind = $list;#指向链表的第一个节点

        /*
         *  算法思路:准备两个指针,假如第一个指针走到n-1(即链表末尾),
         *  第二个指针走到倒数k的位置,两者之间相差(n-1)-(n-k) = k-1
         */
        for($i=0;$i<$k-1;$i++)
        {
            /*
             * 让第一个指针先走k-1个单位 如果不为空 则指针向后移动
             * 注意 这里有个隐藏条件 就是链表的长度有可能小于k ,所以不遍历整个链表是不知道其长度的
             */
            if($list->next != null)
            {
                $list = $list->next;
            }else{
                return;
            }
        }

        while($list->next != null)
        {
            $list = $list->next;
            $behind = $behind->next;
        }

        return $behind;
    }

    /**
     * 反转链表
     *
     *  a-->b-->c-->d-->e-->f
     *
     * 将e的next指向d :
     * 当把e的next指针指向d的同时,原先指向的f就不能被正常访问了
     * 为了避免断链,我们必须在更改指向之前,保存修改节点的下一个节点。
     * 同时我们也必须存储上一个节点,因为next域即将修改指向该节点。
     * 因此定义三个指针,分别指向
     * 当前遍历的节点,
     * 前一个节点,
     * 后一个节点
     */
    public function reverseList($list)
    {
        if($list == null)
        {
            echo '参数不合法';
            return ;
        }

        //前一节点 这里是根节点
        $pre = null;

        //当前节点
        $cur = $list->next;
        //后一节点
        $next = null;
        /*
         * 链表存在且不为空
         */

        while($cur->next)
        {
            $next = $cur->next;   //用一个变量暂时存放后一个节点 因为一旦前面反转,就断链了
            $cur->next = $pre;    //将前一个节点作为当前节点的后一节点 是为反转

            #指针后移
            $pre = $cur;
            $cur = $next;
        }

        $cur->next = $pre;
        return $cur;
    }

}
$linkIns = new singleLinkList();
$arr2 = $linkIns->headInsert(5);print_r($arr2);

//$nodeData = $linkIns->readNode($arr2,2);
//$deleteNode = $linkIns->delete($arr2,2);
//print_r($deleteNode);
//$knode = $linkIns->findNodeToTail($arr2,3);

$arr3 = $linkIns->reverseList($arr2);

print_r($arr3);

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值