• 数据结构:链表(单链表)


    一、链表

      概念:链表[Linked List]是由一组不必相连(可连续可不连续)的内存结构(节点),按照特定的顺序链接在一起的抽象数据类型;

      分类:链表常用的大概有三类:单链表、双向链表、循环链表(这篇文章主要讲单链表)

      操作:链表的核心操作主要有三个(查找遍历、插入、删除)

    二、单链表

      

      上图就是一个单链表的数据结构了,从上图可以看出,每个节点包含两个重要的元素(data、next),那么什么是单链表呢?

      概念:各个内存结构通过一个Next指针链接在一起,每个内存结构都存在后续的内存结构(链尾除外);内存域由两部分组成(Data数据域Next指针域

    三、操作

      

      上图展示了单链表的插入和删除的过程,很清楚的能够知道是怎么一回事,针对我这样的小白来说,至少我看懂了;

      下面是本人结合上面的图写的代码(随便写的,将就着看,代码只是验证你是否真的了解 该数据结构,所以理解了即可,没有必要在意代码的好坏,谢谢!):

    <?php
    /***
     * 单链表数据结构
     * 链表是一种递归的数据结构,它或为空(Null),或指向一个结点的引用,该结点还有一个元素和指向下一个链表的引用
     * 单链表的每个节点由两个元素组成:data、next
     */
    class Node{
        public $data;
        public $next=null;
        public $linkedSize = 0; // 记录链表的大小(每个节点都保存了这个值为0,其实也可以保持个id,看个人习惯)
        public function __construct($data){
            $this->data = $data;
        }
    }
    
    class LinkedList{
    
        /***
         * 创建链表
         * @param array $data
         * @return Node|string
         */
        public static function createLinked($data=array())
        {
            if(empty($data))
                return '参数为空';
            $header = new Node('');
            $headerObj = $header;
            foreach ($data as $key=>$val)
            {
                $nextHeader = new Node($val);
                $headerObj->next = $nextHeader;
                $headerObj = $nextHeader;
                $header->linkedSize++;
            }
    
            return $header;
        }
    
        /***
         * 遍历链表数据
         * @param Node $header
         * @return bool
         */
        public static function selectLinkedList(Node $header)
        {
            $linkedObj = $header;
            $i = 0;
            while($linkedObj->next != null)
            {
                echo $i.' Node data:'.$linkedObj->next->data."
    ";
                $linkedObj = $linkedObj->next;
                $i++;
            }
            return true;
        }
    
        /***
         * @param Node $header
         * @param $key
         * @param $data
         * @param string $lmr l 指定key的前边插入 m 指定位置插入 r 指定位置的后边插入
         * @return bool|string
         */
        public static function insertKeyLinkedList(Node $header, $key, $data, $lmr='r')
        {
            // 链表可能为空(添加一个节点)
            if($header->linkedSize < 1)
            {
                $newHeader = new Node($data);
                $header->next = $newHeader;
                $header->linkedSize++;
                return true;
            }
    
            # 配置插入方向和位置
            $lmrKey = array('l', 'm', 'r');
            $lmrConfig = array(
                'l' => $key - 1,// 往指定位置的前边插入数据
                'm' => $key, // 往指定位置插入数据
                'r' => $key + 1 // 往指定位置的后边插入数据
            );
    
            // 验证key的合法性
            if(!preg_match('/^[0-9]{1,}$/si', $key) || !in_array(trim($lmr), $lmrKey))
                return '请输入正确的key和lmr方向';
    
            # 获取真实的位置
            if(!isset($lmrConfig[trim($lmr)]))
                return '计算位置错误(可能参数有误)';
            $positionKey = $lmrConfig[trim($lmr)];
            $maxSize = $header->linkedSize-1;
            if(trim($lmr) == 'r')
                $maxSize = $header->linkedSize;
            if($positionKey > $maxSize)
                return '未知的位置';
    
            $i = 0;
            $headerObj = $header;
            while($headerObj->next != null)
            {
                // 这里有点类似咱们经常用的冒泡排序,交换位置
                if($positionKey == $i || $positionKey < 0)
                {
                    $newHeader = new Node($data);
                    $temp = $headerObj->next;
                    $headerObj->next = $newHeader;
                    $newHeader->next = $temp;
                    $header->linkedSize++;
                    return true;
                }
                if(trim($lmr) == 'r' && ($i+1) == $maxSize) // 插入到末尾
                {
                    $newHeader = new Node($data);
                    $headerObj->next->next = $newHeader;
                    $header->linkedSize++;
                    return true;
                }
    
                $headerObj = $headerObj->next;
                $i++;
            }
    
            return true;
        }
    
        /***
         * @param Node $header
         * @param int $key
         * @return bool|string
         */
        public static function deleteKeyLinkedList(Node $header, $key=0)
        {
            if(!preg_match('/^[0-9]{1,}$/si', $key) || $key > ($header->linkedSize-1) || $key < 0)
                return '输入的key不合法/当前位置没有数据';
    
            if($header->next == null || $header->linkedSize < 1)
                return '链表中暂无数据';
    
            $i = 0;
            $position = $key;
            $headerObj = $header;
            while($headerObj->next != null)
            {
                if($i == $position)
                {
                    $tmp = $headerObj->next->next;
                    unset($headerObj->next);
                    $headerObj->next = $tmp;
                    $header->linkedSize--;
                    return true;
                }
                $headerObj = $headerObj->next;
                $i++;
            }
            return true;
        }
    }
    
    # 创建链表
    $data = array(22, 2, 90, 6, 43, 76, 89);
    $header = LinkedList::createLinked($data);
    
    # 遍历单向链表
    LinkedList::selectLinkedList($header);
    echo "
    ";
    
    # 插入一个元素
    $header = new Node('');
    LinkedList::insertKeyLinkedList($header,6, 250, 'l');
    
    # 插入后遍历单向链表
    LinkedList::selectLinkedList($header);
    //var_dump($header);
    
    // 删除指定的节点
    LinkedList::deleteKeyLinkedList($header, 1);
    
    # 删除后遍历单向链表
    LinkedList::selectLinkedList($header);

    博客内容出自:https://www.jianshu.com/p/73d56c3d228c

  • 相关阅读:
    XP下关于快速切换用户功能的相关编程
    CRC原理及其逆向分析方法
    爱的十个秘密4.给予的力量
    爱的十个秘密1.序幕
    隐式链接无.LIB动态链接库
    电影图标黑客帝国(The Matrix)
    手机图标
    圣斗士图标:十二星座黄金圣衣
    MAC风格图标
    GB码与BIG5
  • 原文地址:https://www.cnblogs.com/zengguowang/p/9425948.html
Copyright © 2020-2023  润新知