当前位置: 首页 > news >正文

数据结构:链表

1. 链表

1.1 链表的概念

我们知道顺序表的缺点很明显,那就是当频繁的插入和删除时,会导致大量的频繁的移动元素,这显然就会消耗时间。

那么链表就很好的解决了这个问题,链表也称为线性表的链式存储结构,其特征就是其中的元素不需要考虑相邻位置,每个元素都知道下一个元素的位置,这样,我们只需要知道第一个元素的地址就能遍历所有元素。

1.2 链表的结构

如图所示,常见的链表是这样表示的,一个元素会存放下个元素的地址,这样就不需要在空间上相邻排序,也能找到下个点。

1.3 链表的表示方法

如图,用Java可以这样表示一个链表,每个节点存放一个值val和下一个点的地址next。

当我们要指定一个点为头节点时,可以让head = next,比如这样:

ListNode head = next;

这样一来,我们就算确定了头节点,然后就可以进行插入和删除,修改查找等工作了。

我们以插入节点为例:

使用头插法,就是当我们插入数据时,先让该数据的下一个数据的地址指向head,更新 head 为 newNode,使新节点成为新的头节点,这样就完成了一个点的插入。接下来再插入的时候就同理,把新的点的next地址指向head,再把整个节点给head。这样一来每次插入点点都在head处,也就是最前面。

通过debug可以看到整个插入的过程。

当我们明白了链表的结构,除了实现头插法,我们还可以写出其他的方法实现,比如尾插法,任意位置插入,查找,删除等等。

1.4 其他链表

我们前面说的链表是有头的单向非循环链表,其实链表还分很多种情况,比如,单向双向,有头无头,循环非循环等等。

其实常用到的也就两种:

无头单向非循环链表:结构简单,一般不会单独用来存数据

无头双向链表:其在Java的集合框架库中LinkedList底层实现就是无头双向循环链表

这些我们可以自己实现也可以直接使用Java中的LinkedList。

2. LinkedList的结构

LinkedList的底层是双向链表结构,由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。

其结构如下:

在集合框架中LinkedList实现了List接口。

3. LinkedList的使用

我们可以直接调用LinkedList类来直接使用其接口

方法对应解释
boolean add(E e)尾插e
void add(int index, E element)尾插e到index位置
boolean addAll(Collection<? extends E> c)尾插c中的元素
E remove(int index)删除index位置元素
boolean remove(Object o)删除遇到的第一个o
E get(int index)获取index位置元素
E set(int index, E element)将index位置元素设为elem
void clear()清空
boolean contains(Object o)o是否在表中
int indexOf(Object o)返回第一个o所在的下标
int lastIndexOf(Object o)返回最后一个o所在的下标
List<E> subList(int fromIndex, int toIndex)截取部分list

4. ArrayList 和 LinkedList的区别

在区别方面:

1. 遍历:ArrayList的遍历方式有三种:for循环下标,for each循环,迭代器;而LinkedList的遍历方式有两种,没有for循环下标,因为其存放地址的特性,无法获取下标。

2. 存储空间上:ArrayList物理上一定连续;而LinkedList逻辑上连续,但物理上不一定连续。

3. 随机访问:ArrayList 支持O(1);LinkedList 不支持:O(N)。

4. 头插:ArrayList需要搬移元素,效率低O(N);LinkedList只需修改引用的指向,时间复杂度为O(1)。

5. 插入:ArrayList空间不够时需要扩容;LinkedList没有容量的概念。

6. 应用场景:ArrayList元素高效存储+频繁访问;LinkedList任意位置插入和删除频繁。

5. 总结

通过ArrayList 和 LinkedList,我们知道了顺序表在物理结构上存在两种不同的存储方式,两种方式各有千秋。本质是要理解链表的底层结构,在空间上不需要相邻,只需要知道下一个元素的位置就能找到。

http://www.lqws.cn/news/589627.html

相关文章:

  • 认识 Spring AI
  • 华为云Flexus+DeepSeek征文|基于华为云Flexus云服务的Dify 快速构建联网搜索助手
  • Zookeeper安装使用教程
  • 产品背景知识——API、SDK、Library、Framework、Protocol
  • guava限流器RateLimiter源码详解
  • SpringBoot -- 自动配置原理
  • 基于Python的GIS-RS多源数据处理(TIF/SHP/NC/...)【20250630】
  • P1967 [NOIP 2013 提高组] 货车运输
  • Spring生态:云原生与AI的革新突破
  • C++ 快速回顾(五)
  • 编程新手之环境搭建:node python
  • Excel转pdf实现动态数据绑定
  • 「Java案例」计算矩形面积
  • Linux随记(十九)
  • python+uniapp基于微信小程序的食堂菜品查询系统
  • [springboot系列] 探秘JUnit 5: Java单元测试利器
  • Spring 依赖注入:官方推荐方式及最佳实践
  • hono+postgresql+CURD
  • YOLOv13:最新的YOLO目标检测算法
  • Windows11系统中安装docker并配置docker镜像到pycharm中
  • 文旅数字孪生交付生态链:集成-交付-运维“三位一体”,100+案例助力行业数字化转型
  • 腾讯云空间,高性能显卡云,安装xinference报错,pip install 空间不够用了
  • WOLA(Weighted Overlap-Add)方法详解
  • 实战避坑:MyBatis中${}拼接如何优雅又安全?
  • Python 数据分析与机器学习入门 (二):NumPy 核心教程,玩转多维数组
  • Redis 集群
  • SQLite 安装使用教程
  • 长短期记忆网络(LSTM):让神经网络拥有 “持久记忆力” 的神奇魔法
  • 反射,枚举和lambda表达式
  • Bessel位势方程求解步骤