2. 数据结构之LinkedList

发布于:2025-07-17 ⋅ 阅读:(22) ⋅ 点赞:(0)

1. LinkedList简介

LinkedList(链表)是一种线性数据结构,与数组不同,它不要求元素在内存中连续存储。链表由一系列节点组成,每个节点包含数据和指向下一个节点的引用(指针)。

基本特性

  1. 动态大小:链表可以动态增长和缩小,不需要预先指定大小

  2. 内存效率:只在需要时分配内存,不像数组需要连续内存空间

  3. 插入/删除效率:在已知位置插入或删除节点的复杂度为O(1)

  4. 访问效率:随机访问效率低(O(n)),必须从头开始遍历

链表类型

1. 单向链表(Singly Linked List)

每个节点包含:

  • 数据部分

  • 指向下一个节点的指针(最后一个节点指向null)

代码实现:

private static class Node<E>{
    E item;
    Node<E> next;

    Node(E element, Node<E> next){
        this.item = element;
        this.next = next;
    }
}

链表结构:

查询节点:

  • 只有在查询头节点的时候不需要遍历链表,时间复杂度是O(1)。
  • 查询其他结点需要遍历链表,时间复杂度是O(n)。

插入删除节点:

  • 只有在添加和删除头节点的时候不需要遍历链表,时间复杂度是O(1)。
  • 添加或删除其他结点需要遍历链表找到对应节点后,才能完成新增或删除节点,时间复杂度是O(n)。


2. 双向链表(Doubly Linked List)

每个节点包含:

  • 数据部分

  • 指向前一个节点的指针

  • 指向下一个节点的指针

代码实现:

private static class Node<E>{
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next){
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

查询节点: 

  • 查询头尾结点的时间复杂度是O(1)
  • 平均的查询时间复杂度是O(n)
  • 给定节点找前驱节点的时间复杂度为O(1)

增删节点:

  • 头尾结点增删的时间复杂度为O(1)
  • 其他部分结点增删的时间复杂度是 O(n)
  • 给定节点增删的时间复杂度为O(1)

3. 循环链表(Circular Linked List)

  • 单向循环链表:最后一个节点指向第一个节点

  • 双向循环链表:第一个节点的prev指向最后一个节点,最后一个节点的next指向第一个节点

基本操作复杂度

操作 时间复杂度 备注
访问元素 O(n) 必须从头节点开始遍历
插入/删除头节点 O(1) 直接操作头指针
插入/删除尾节点 O(1) 双向链表;单向链表为O(n)
在中间插入 O(n) 需要先找到位置
搜索元素 O(n) 需要遍历

链表 vs 数组

特性 链表 数组
内存分配 动态,不连续 静态,连续
大小 可动态增长 固定大小
访问元素 O(n) O(1)
插入/删除 O(1)(已知位置) O(n)(需要移动元素)
内存开销 每个节点需要额外存储指针 只有数据

2. 问题总结

2.1 单向链表和双向链表的区别是什么?

  • 单向链表只有一个方向,结点只有一个后继指针 next。
  • 双向链表它支持两个方向,每个结点不止有一个后继指针next指的结点,还有一个前驱指针prev指向前面的结点。

破旧的船帆总有一天会到达彼岸

鲜红的花蕊绽放在蓝色的海洋边缘

未来的憧憬随时间的流逝渐行渐远

长大的我们现身处低谷却仰望顶端 


网站公告

今日签到

点亮在社区的每一天
去签到