您好、欢迎来到现金彩票网!
当前位置:众彩 > 分支限界 >

以后再也不怕别人问「单链表」的问题啦

发布时间:2019-05-25 21:16 来源:未知 编辑:admin

  在程序设计里,我们经常需要将同为某个类型的一组数据元素作为一个整体来使用,需要创建这种元素组,用变量来记录它们或者传入函数等等等等,「线性表」就是这样一组元素的抽象,它是某类元素的集合并且记录着元素之间一种顺序关系,是最基本的数据结构之一,在实际程序中运用非常广泛,比如

  基于各种实际操作等方面的综合考虑,我们提出了两种实现线性表的形式:「顺序表」和「链表」。

  「顺序表」是将表中的元素顺序存放在一大块连续的存储区间里,所以在这里元素间的顺序是由它们的存储顺序来表示的。「链表」则是将表中元素存放在一系列的结点中(结点的存储位置可以是连续的,可以是不连续的,也就意味着它们可以存在任何内存未被占用的位置),这些结点通过连接构造起来,结点分为「数据域」和「指针域」。这次我们要学习的「单链表」就是「链表」的一种实现形式,「数据域」保存着作为表元素的数据项,「指针域」保存同一个表里的下一个结点的标识。

  在正式说「单链表」之前,我先来说一下很多人在学习链表之初都傻傻分不清的两个东西:「头结点」和「头指针」。

  「头结点」的设立是为了操作的统一和方便,是放在第一个元素的节点之前,它的数据域一般没有意义,并且它本身也不是链表必须要带的。那设立头节点的目的是什么呢?其实就是为了在某些时候可以更方便的对链表进行操作,有了头结点,我们在对第一个元素前插入或者删除结点的时候,它的操作与其它结点的操作就统一了。

  「头指针」顾名思义,是指向链表第一个结点的指针,如果有头结点的话,那么就是指向头结点的指针。它是链表的必备元素且无论链表是否为空,头指针都不能为空,因为在访问链表的时候你总得知道它在什么位置,这样才能通过它的指针域找到下一个结点的位置,也就是说知道了头指针,整个链表的元素我们都是可以访问的,所以它必须要存在,这也就是我们常说的「标识」,这也就是为什么我们一般用头指针来表示链表。

  n 个结点链接成一个链表,这也就是平时书上所说的「链式存储结构」,因为这个链表中的每个结点中只包含一个指针域,所以又叫「单链表」。单链表正是通过每个结点的指针域将线性表的数据元素按其逻辑次序链接在一起。单链表的第一个结点的存储位置叫做「头指针」,最后一个结点的指针为「空」,一般用 “^” 表示。

  通过上面 3 个图我们发现无论单链表是否为空,是否有头结点,头指针都是存在的,这就很好的印证了之前我们所说的「头指针是链表的必备元素且无论链表是否为空,头指针都不能为空」。

  创建单链表的过程其实就是一个动态生成链表的过程,说简单点就是从一个「空链表」开始,依次建立各个元素的结点,并把它们逐个插入链表,时间复杂度为 O(n):

  在使用链表的时候,经常需要求表的长度,为此我们可以创建一个球表长的函数,这个函数就是从左到右扫描,遍历表中的所有结点并完成计数,时间复杂度为 O(n):

  假设我们要将结点 s 插入到 结点 p 的后面,只需要将结点 s 插入到结点 p 和 结点 p.next 之间即可,说起来简单,那么到底如何插入呢?请看下图:

  由上图我们可以看到,单链表结点的插入根本不需要惊动其它结点,只需要让 s.next 和 p.next 的指针稍作改变即可。让 p 的后继结点改为 s 的后继结点,再把 s 的后继结点变成 p 的后继结点。这里一定要切记,插入操作的顺序不能改变,至于为什么,你可以拿起纸笔手动的画一下,结果一下子就会出来(对于单链表的表头和表尾的特殊情况,操作是相同的)。

  看完插入,我们现在再来看看单链表的删除。假设我们想要删除一个结点 q,其实就是将它的前继结点 p 的指针绕过 q,直接指向 q 的后继结点即可,具体操作如下图所示:

  由 p = None 可以看出,在 Python 中,只需要简单的将指针赋值为 None,就抛弃了链表原有的结点,Python 解释器的存储管理系统会自动回收不用的存储。

  在顺序结构中,我们想要获取任意一个元素的存储位置是很容易的,但是在单链表中,第 i 个元素到底在哪我们一开始没办法知道,只能傻傻的从头开始找,所以在对于单链表获取第 i 个元素的操作,算法上相对麻烦一些。

  从上面的代码我们可以很清楚的看出,单链表获取第 i 个元素就是从头开始找,知道第 i 个元素为止,所以我们可以很容易的估算出它的时间复杂度是 O(n)。任何事物都不是完美的,有好的地方就有坏的地方,元素的读取就是单链表美中不足的地方之一。

  单链表的操作其实还有不少,我只是写了其中常用的几种,希望大家能自己动手尝试一下,把这几个搞懂搞透。碰到这样的问题从哪个方面去思考,如何去做才是最重要的,只有学会了这些,你在日后碰到相关问题的时候就知道如何去下手。

  我在上面每个操作的讲解中大多数给出了图,通过图来看解法题目了然。算法这个东西其实就是这样,多动手实现以下,想不明白了就动手画一下,画着画着思路就出来了。

  最后我们就来总结一下链表操作的时间复杂度,如果你还不会估算算法的时间复杂度,请看我的 循序渐进带你学习时间复杂度和空间复杂度。

  插入元素:首端插入为 O(1);尾端插入为 O(n),因为还要找到表的最后结点;定位插入 为O(n)。

  删除元素:首端删除为 O(1);尾端删除为 O(n),理由如上;定位删除为 O(n)。

  文章出处:【微信号:TheAlgorithm,微信公众号:算法与数据结构】欢迎添加关注!文章转载请注明出处。

  Linux 内核提供一套双向链表的实现,你可以在 include/linux/list.h 中找到。....

  双向链表的灵活处就是知道链表中的一个元素结构就可以向左或者向右开始遍历查找需要的元素结构。因此对于一....

  [table] [tr][td]C语言是必学的一个课程,不管你是单片机还是嵌入式物联网,都是基础,所以还是要好好学习的 今天推荐的资料...

  Linux Kernel数据结构:链表 原创 2016年10月20日 22:58:25 标签:LINUX /kernel /链表 数据结构 ...

  单链表的查找、插入与删除。设计算法,实现线性结构上的单链表的产生以及元素的查找、插入与删除。具体实现....

  链表通常由一组代表一个序列的节点组成。 每个节点包含存储的任意类型实际数据以及指向序列中下一个节点的....

  针对共享资源矩阵法在系统隐蔽通道检测过程中存在的算法时间复杂度高的问题,提出了一种基于双十字链表存储....

  针对PrePost算法中需要建立复杂的前序和后序编码树(PPC-tree)和节点链表(N-list)....

  数据在许多研究领域都可采用图形来表示,图形和图形理论为人工智能决策提供了有效的可视化工具、体系化准则....

  用单链表编写的模拟学生成绩管理系统,索要进行的项目可以再菜单中进行选择

  用单链表,键盘输入城市名称和城市的坐标,可以在菜单中选择你要进行的内容

  所谓链表,就是用一组任意的存储单元存储线性表元素的一种数据结构。链表又分为单链表、双向链表和循环链表....

http://jigsawesl.com/fenzhixianjie/309.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有