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

一、链表

  概念:链表[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."\n";
            $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 "\n";

# 插入一个元素
$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

原文地址:https://www.cnblogs.com/zengguowang/p/9425948.html

时间: 2024-08-29 13:44:18

数据结构:链表(单链表)的相关文章

C#数据结构-单链表

理论基础: 链表是用一组任意的存储单元来存储线性表中的数据元素. 如果结点的引用域只存储该结点直接后继结点的存储地址,则该链表叫单链表(Singly Linked List). 单链表由头引用H唯一确定.头引用指向单链表的第一个结点,也就是把单链表第一个结点的地址放在H中. C#实现: 1接口 引用线性表的接口IListDS<T> 2实现 首先,必须定义一个单链表的节点类.  1 public class Node<T> 2    { 3        private T data

数据结构之单链表(C++实现)

有一段时间没有写一些关于数据结构的程序了,正好算法导论这门课学到红黑树,感觉数据结构都忘得差不多了,而且考研还要考,故再拿来复习一下. 一.C++实现单链表 #include<iostream> using namespace std; typedef struct LNode { int data; struct LNode *next; }LNode,*LinkList; void CreateList_L(LinkList &L, int n) { L = new LNode()

数据结构之——单链表

今天闲来无事,就打算把大一的时候写过的数据结构重温一遍,基本上我在大一之后只在单片机上用过几次顺序表和循环队列之外再就很少使用过数据结构了. 并且乘着写一下数据结构也可以熟悉熟悉vim. 首先定义单链表节点: 1 #define DataType int 2 3 struct node{ 4 DataType data; 5 struct node *next; 6 }; 7 struct node list,*p_list; 单链表这个数据结构需要一些函数来对她操作,一般需要有这些: 1.初始

数据结构(一) 单链表的实现-JAVA

数据结构还是很重要的,就算不是那种很牛逼的,但起码得知道基础的东西,这一系列就算是复习一下以前学过的数据结构和填补自己在这一块的知识的空缺.加油.珍惜校园中自由学习的时光.按照链表.栈.队列.排序.数组.树这种顺序来学习数据结构这门课程把. -WH 一.单链表的概念 链表是最基本的数据结构,其存储的你原理图如下图所示 上面展示的是一个单链表的存储原理图,简单易懂,head为头节点,他不存放任何的数据,只是充当一个指向链表中真正存放数据的第一个节点的作用,而每个节点中都有一个next引用,指向下一

Java数据结构之单链表

链表的组成:链表头+结点 ? ?链表头一般只存储下一个节点的引用 ? ?节点:存数据+下一个节点的引用 链表头代码: package?com.xingej.algorithm.datastructure.linkedList.singleLinkedList; /** ?*?声明一个链表的头部 ?*? ?*?从链表头的使用,联想到hadoop,spark,netty中都有上下文context ?*? ?*[email protected]?erjun?2017年12月8日?上午8:45:08 ?

java数据结构:单链表常见操作代码实现

一.概述: 本文主要总结单链表常见操作的实现,包括链表结点添加.删除:链表正向遍历和反向遍历.链表排序.判断链表是否有环.是否相交.获取某一结点等. 二.概念: 链表: 一种重要的数据结构,HashMap等集合的底层结构都是链表结构.链表以结点作为存储单元,这些存储单元可以是不连续的.每个结点由两部分组成:存储的数值+前序结点和后序结点的指针.即有前序结点的指针又有后序结点的指针的链表称为双向链表,只包含后续指针的链表为单链表,本文总结的均为单链表的操作. 单链表结构: Java中单链表采用No

数据结构之单链表

1. 链表的特点 链表是一种非线性.非顺序的物理结构,是由若干个节点组成. 链表采用的是“见缝插针”的存储方法,不要求内存连续,靠next指针关联起来. 链表的物理存储方式为随机存储,访问方式为顺序访问. 查找节点的时间复杂度为O(n),插入.删除节点的时间复杂度为O(1). 链表适用于写操作多,读操作少的场景. 1 //单向链表节点的数据结构 2 struct SingleListNode 3 { 4 int nData;//当前节点的数据 5 Node* pNext;//指向下一个节点的指针

数据结构 线性结构(数组[列表] ,链表 单链表的增删改查**, 线性结构的应用 队列 栈[函数的调用**]),非线性结构 树

数据结构 参考:http://lupython.gitee.io/ 线性结构 就是能够用一根线串起来的数据结构 数组 (列表) 问:申请数组的前提条件是啥? a[12]?内存需要满足的条件? 答:内存必须有一块连续的内存空间 int a[7] : 声明一个数组,这个数组的数组名是 a, 数组的大小是 7, 数组元素的类型是整型. int a[7] = array(1,2,3,4,5,6,7) 问:如何申请内存? 答:C,C++语言,申请:mallco (28).释放:free(28) 问:int

数据结构关于单链表的一些操作的源代码

单链表的可以有许多问题,这是我特意整理一下的有关他的相关操作,给出代码,有需要的可以自己调试,重要的就是关于环的一些操作: #include <iostream>#include <cstdio>#include <cstdlib>#include <ctime>using namespace std;typedef int Elemtype;typedef struct Node{ Elemtype data; struct Node *next;}Nod

数据结构:单链表结构字符串(python版)

1 #!/urs/bin/env python 2 # -*- coding:utf-8 -*- 3 4 #异常类 5 class stringTypeError(TypeError): 6 pass 7 8 #节点类 9 class Node(object): 10 def __init__(self, elem, next_ = None): 11 self.elem = elem 12 self.next = next_ 13 #单链表类 14 class single_list(obje