如何实现单链表?
这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战
笔者最近在学习《数据结构与算法之美》,正好借着这个机会边练习边记录一下自己学习的知识点。不啰嗦,直接开始。
一、什么是链表
链表和数组一样都是线性的数据结构。
链表由一个一个的结点连接组成,结点又由数据域和指针域两部分组成。数据域存储数据,指针域存储指向下一个结点的指针(或者叫引用)。
正是因为使用指针指向下一个结点,所以链表可以将零散的内存空间串联起来。
常见的链表有:单链表、循环链表、双链表和双向循环链表等等。
二、链表的特点
- 链表查询时间复杂度 O(n),删除插入时间复杂度 O(1) :因为链表使用指针指向下一个结点,所以当想要查询某个结点时,只能从第一个结点依次进行遍历,直到目标结点。但删除和插入只需要将指针指向新结点即可。
- 链表与数组相比,需要额外的内存空间:因为除了数据存储的空间之外,还存储了指向下一结点指针。
三、单链表实现
单链表的实现有两个难点:一个是插入结点操作,另一个是删除结点操作。
3.1 插入
单链表的插入有三种方式,一个是插入到链表头部、二是插入到链表尾部、三是在链表两个结点直接插入新结点。
插入到链表头部只需要将新结点的指针指向头结点,再将新结点设置为头结点即可。
插入到链表尾部,需要先遍历到链表的尾结点,在将尾结点的指针指向新结点即可。
链表两个结点直接插入新结点,例如将结点 p 插入到结点 a 和 结点 b之间,先将结点 p.next 指向结点 b,在将结点 a.next 结点 p。
3.2 删除
删除链表中的某个结点,例如删除结点 c 。先找到结点 c 的前驱结点 b,将 b.next = b.next.next即可。
3.3 具体实现
1 | java复制代码/** |
四、数组 or 链表
数组和链表是常见的基本数据结构,两者经常放在一起进行比较,同样是线性数据结构我们如何进行选择?
4.1 随机访问、插入、删除时间复杂度
随机访问 | 删除、插入 | |
---|---|---|
数组 | O(1) | O(n) |
链表 | O(n) | O(1) |
4.2 数组存储 vs 链表存储
数组需要连续的内存空间,比如你需要申请 99 M 大小的内存空间,但没有 99 M 的连续内存空间了,数组创建就会失败。
数组连续的内存空间可以利用 CPU 的缓存机制,使得数据访问更快。
数组的大小固定,虽然我们可以实现动态扩容的数组,但是频繁的数据搬移也是非常耗时的。
链表使用指针将不连续的内存空间连接在一起,但这就需要使用额外的内存空间存储指向下一结点的指针。链表频繁的创建对象也可能产生内存碎片。
综上根据你的需要,具体问题具体分析。
传送门:如何实现动态扩容的数组
XDM,动动小手点赞评论,求求了。
本文转载自: 掘金