2. 数据结构之LinkedList


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指向前面的结点。

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

惊骇世俗王某人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值