0

0

LinkedList实现队列和栈的技巧

P粉602998670

P粉602998670

发布时间:2025-09-22 16:45:01

|

360人浏览过

|

来源于php中文网

原创

使用LinkedList可高效实现栈和队列:栈利用addFirst()/removeFirst()实现LIFO,队列通过addLast()/removeFirst()实现FIFO,操作均O(1)时间复杂度,无需扩容且内存动态分配。

linkedlist实现队列和栈的技巧

LinkedList
实现队列和,核心在于巧妙利用其双向链表的特性,通过在头部或尾部进行高效的添加和删除操作,从而精确模拟这两种数据结构各自的先进先出(FIFO)和后进先出(LIFO)行为。这避免了数组在中间插入或删除元素时可能带来的高昂开销,也省去了扩容的烦恼。

直接输出解决方案即可

解决方案

LinkedList
作为一种双向链表,在Java等语言中,天然提供了在链表两端进行操作的方法,例如
addFirst()
removeFirst()
addLast()
removeLast()
等。正是这些方法,使得它成为实现队列和栈的理想基石。

对于栈(Stack),其核心是LIFO(Last In, First Out)原则,即最后进入的元素最先出去。我们可以将

LinkedList
的一端(比如头部或尾部)固定作为栈的“顶部”。

  • 入栈 (Push):将元素添加到链表的“顶部”。如果选择链表头部作为栈顶,则使用
    addFirst(E e)
    。如果选择链表尾部作为栈顶,则使用
    addLast(E e)
    。我个人倾向于使用
    addFirst()
    ,感觉更直观,就像往一叠盘子顶部放盘子。
  • 出栈 (Pop):从链表的“顶部”移除元素。对应
    removeFirst()
    (如果栈顶是头部)或
    removeLast()
    (如果栈顶是尾部)。
  • 查看栈顶元素 (Peek):查看但不移除链表“顶部”的元素。对应
    getFirst()
    getLast()

对于队列(Queue),其核心是FIFO(First In, First Out)原则,即最先进入的元素最先出去。这通常意味着元素从一端进入,从另一端离开。

  • 入队 (Enqueue):将元素添加到队列的“尾部”。使用
    addLast(E e)
  • 出队 (Dequeue):从队列的“头部”移除元素。使用
    removeFirst()
  • 查看队首元素 (Peek):查看但不移除队列“头部”的元素。使用
    getFirst()

这种利用

LinkedList
两端操作的策略,使得入队、出队、入栈、出栈操作的时间复杂度都保持在O(1),非常高效。

为什么LinkedList是实现队列和栈的理想选择?

在我看来,

LinkedList
在实现队列和栈时,简直是“量身定制”的。它之所以被认为是理想选择,主要有几个深层原因。首先,最直接的就是它的O(1)时间复杂度特性。无论是向链表头部还是尾部添加或删除元素,都只需要修改少数几个节点的指针,这与数组在中间插入或删除元素时需要移动大量元素的开销形成了鲜明对比。想象一下,如果用数组实现队列,每次出队都要将所有后续元素向前移动一位,那效率可想而知。而
LinkedList
则完全避免了这个问题。

其次,

LinkedList
动态扩容特性也是一个巨大的优势。数组在容量不足时需要进行扩容,这涉及创建一个更大的新数组并将旧数组的元素复制过去,这个过程是耗时的。而
LinkedList
则没有固定容量的限制,它会根据需要动态地创建和销毁节点,天然支持动态增长,这在处理不确定大小的数据流时尤其方便,避免了预估容量的烦恼。

SEEK.ai
SEEK.ai

AI驱动的智能数据解决方案,询问您的任何数据并立即获得答案

下载

再者,从内存使用的角度看,虽然每个节点会额外存储前后节点的引用,导致单个元素占用内存稍多于数组,但在某些场景下,这种分散的内存分配反而更灵活。它不会像数组那样要求一块连续的内存空间,这对于内存碎片化严重的系统来说,可能更容易分配到所需空间。当然,这也不是绝对的,具体还得看应用场景和数据量。但总体来说,

LinkedList
在处理头部和尾部操作的效率上,确实是无与伦比的。

使用LinkedList实现栈:具体操作与考量

当我们需要一个栈时,

LinkedList
提供了一个非常简洁且高效的实现途径。我通常会这样操作:

1. 入栈 (Push) 将元素压入栈顶。在

LinkedList
中,我们可以选择
addFirst(E e)

// 假设有一个LinkedList实例
LinkedList stack = new LinkedList<>();
stack.addFirst("Element A"); // 栈:[A]
stack.addFirst("Element B"); // 栈:[B, A]
stack.addFirst("Element C"); // 栈:[C, B, A]

这里,链表的头部被我们定义为栈的“顶部”。

2. 出栈 (Pop) 从栈顶移除并返回元素。对应

removeFirst()

String poppedElement = stack.removeFirst(); // 移除并返回 "C",栈:[B, A]
// 如果栈为空,调用removeFirst()会抛出NoSuchElementException。
// 实际使用时,通常会先检查isEmpty()。

3. 查看栈顶元素 (Peek) 查看栈顶元素,但不移除。对应

getFirst()

String topElement = stack.getFirst(); // 返回 "B",栈:[B, A]
// 同样,如果栈为空,会抛出NoSuchElementException。

4. 判断栈是否为空 (isEmpty) 直接使用

isEmpty()
方法。

boolean isEmpty = stack.isEmpty(); // 返回false

考量点:

  • 异常处理
    removeFirst()
    getFirst()
    在链表为空时会抛出
    NoSuchElementException
    。在实际应用中,我们通常会在调用这些方法之前先检查
    isEmpty()
    ,或者使用
    pollFirst()
    /
    peekFirst()
    等返回
    null
    而非抛出异常的方法(这些方法通常用于队列接口,但
    LinkedList
    也提供了)。
  • 线程安全
    LinkedList
    本身不是线程安全的。如果在多线程环境中使用,需要外部同步机制,或者考虑使用
    Collections.synchronizedList(new LinkedList<>())
    ,或者直接使用
    java.util.concurrent
    包下的并发数据结构。这其实是一个普遍的问题,不仅仅是
    LinkedList

使用LinkedList实现队列:具体操作与性能分析

对于队列,

LinkedList
同样表现出色,尤其是在处理大量元素的入队和出队操作时。

1. 入队 (Enqueue) 将元素添加到队列的尾部。使用

addLast(E e)

// 假设有一个LinkedList实例
LinkedList queue = new LinkedList<>();
queue.addLast(10); // 队列:[10]
queue.addLast(20); // 队列:[10, 20]
queue.addLast(30); // 队列:[10, 20, 30]

这里,链表的尾部是新元素的入口,头部是元素的出口。

2. 出队 (Dequeue) 从队列的头部移除并返回元素。使用

removeFirst()

Integer dequeuedElement = queue.removeFirst(); // 移除并返回 10,队列:[20, 30]
// 同样,如果队列为空,removeFirst()会抛出NoSuchElementException。

3. 查看队首元素 (Peek) 查看队首元素,但不移除。使用

getFirst()

Integer frontElement = queue.getFirst(); // 返回 20,队列:[20, 30]

4. 判断队列是否为空 (isEmpty) 直接使用

isEmpty()
方法。

boolean isEmpty = queue.isEmpty(); // 返回false

性能分析:

  • 时间复杂度:如前所述,所有核心操作(入队、出队、查看)都是O(1)。这是
    LinkedList
    作为队列实现的最大优势。
  • ArrayDeque
    的比较
    :虽然
    LinkedList
    在理论上提供了O(1)的性能,但在实际应用中,
    java.util.ArrayDeque
    在很多情况下可能表现更好。
    ArrayDeque
    是基于数组实现的双端队列,它在内部使用循环数组,避免了
    LinkedList
    每个节点额外的内存开销,并且由于数据在内存中是连续存储的,CPU缓存命中率更高。对于基本数据类型,
    ArrayDeque
    避免了装箱拆箱的开销。所以,如果对性能有极致要求,并且数据量不是特别巨大以至于频繁扩容成为瓶颈,
    ArrayDeque
    往往是更优的选择。但对于需要频繁在中间进行插入删除操作,或者内存分配不敏感的场景,
    LinkedList
    的灵活性依然有其价值。我个人在选择时,如果不是特别明确需要链表的特性,通常会先考虑
    ArrayDeque
    ,因为它在大多数常见场景下,综合性能更胜一筹。
  • 内存开销
    LinkedList
    的每个节点除了存储元素本身,还需要存储指向前一个和后一个节点的引用。这意味着对于相同数量的元素,
    LinkedList
    通常会比
    ArrayDeque
    占用更多的内存。这是一个需要权衡的因素。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

309

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

222

2025.10.31

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

236

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

458

2024.03.01

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

539

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

17

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

28

2026.01.06

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1133

2023.10.19

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

1

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

PHP自制框架
PHP自制框架

共8课时 | 0.6万人学习

PHP入门到实战消息队列RabbitMQ
PHP入门到实战消息队列RabbitMQ

共22课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号