跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

Java 栈与队列数据结构及代码实现

综述由AI生成Java 中栈(Stack)和队列(Queue)两种线性数据结构的概念与特性。栈遵循后进先出(LIFO),通过数组模拟实现,支持 push、pop、peek 等操作。队列遵循先进先出(FIFO),提供了双链表和循环数组两种实现方式。此外,文章还详细讲解了如何利用两个队列模拟栈的功能,以及如何利用两个栈模拟队列的功能,并附带了完整的 Java 代码示例。

PhpPioneer发布于 2026/3/28更新于 2026/5/2932 浏览
Java 栈与队列数据结构及代码实现

Java 栈和队列

栈的概念(Stack)

栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,分为栈底和栈顶。栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等。 例如这把枪,第一发子弹是最后发射的,第一发子弹在栈底,而最新安装上去的子弹在栈的顶部,只有将上面的子弹打完(栈顶的数据走完),最后一发子弹才会射出。

栈的实现

栈的实现是基于简单的数组形成的,我们可以将它想象成连续的数组,而栈的顺序是由后放到前放。

模拟实现栈的方法:push(放入一个元素到栈中)、pop(提取栈顶的一个元素,并将在其栈中消除)、peek(查看栈顶的元素)、size(查看栈中的大小)、empty(栈中是否为空)、full(栈是否满了)。

import java.util.Arrays;

public class MyStack implements IStack {
    private int[] elem;
    private int top; // 数组的栈顶,以及数组栈中存放元素的数量
    private static final int DEFAULT_CAPACITY = 10; // 这里是初始容量

    public MyStack() {
        elem = new int[DEFAULT_CAPACITY];
        top = -1; // 数组下标从 0 开始
    }

    @Override
    public void push(int item) {
        if (full()) { // 如果满了就扩容
            elem = Arrays.copyOf(elem, 2 * elem.length);
        }
        elem[++top] = item;
    }

    @Override
    public int pop() throws RuntimeException {
        try {
            if (empty()) {
                throw new RuntimeException("栈为空");
            }
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
        return elem[top--]; // return 返回后删除栈顶的元素
    }

    @Override
    public int peek() {
        if (empty()) {
            throw new RuntimeException("栈为空");
        }
        return elem[top]; // 返回栈顶元素
    }

    @Override
    public int size() {
        return top + 1; // 去除数组 0
    }

    @Override
    public boolean empty() {
        return top == -1;
    }

    @Override
    public boolean full() {
        return top == elem.length; // count==当前的 elem 的总长度为 true
    }
}

队列(Queue)

队列是由先进先出的线性数据结构,采用的是先进先出,后进后出。如果要插入元素的话就是从入队尾巴方向插入,而删除作为出队要在头尾删除。

队列的方法包括 offer、poll、peek、size 等。

模拟实现队列 (双链表实现)

public class MyQueue implements IQueue {
    static class QueueNode {
        public int elem;
        public QueueNode next;
        public QueueNode prev;

        public QueueNode(int elem) {
            this.elem = elem;
        }
    }

    public QueueNode head;
    public QueueNode last;
    public int size = 0;

    @Override
    public void offer(int val) {
        QueueNode queue = new QueueNode(val);
        if (this.head == null) {
            this.head = queue;
            this.last = queue;
            ++size;
            return;
        }
        this.last.next = queue;
        queue.prev = this.last;
        this.last = queue;
        ++size;
    }

    @Override
    public int poll() {
        if (this.head == null) {
            throw new RuntimeException("没有要丢掉的队列");
        }
        QueueNode cur = this.head;
        if (this.head.next == null) {
            this.head = null;
            this.last = null;
            size--;
            return cur.elem;
        }
        this.head = this.head.next;
        this.head.prev = null;
        size--;
        return cur.elem;
    }

    @Override
    public int peek() {
        if (this.head != null) {
            return this.head.elem;
        }
        return 0;
    }

    @Override
    public int size() {
        return size;
    }
}

循环队列(循环数组实现)

数组实现队列的循环需要引入一个公式(目前的下标值 +1)% 当前数组的长度 (index+1)%array.length。下标值从 0 开始少一个数,当 index+1 就是当前的总长度时,公式后的值一定为下标 0。

private int[] array;
private int front;
private int rear;

public MyCircularQueue(int k) {
    array = new int[k + 1];
    front = 0; // 初始位置
    rear = 0;
}

public boolean enQueue(int value) {
    // 入列
    if (isFull()) { // 这里如果容量已经满了,需要先删除后在进行插入
        return false;
    }
    array[rear] = value; // rear 下标获取元素
    rear = (rear + 1) % array.length; // rear 最终循环为 0 下标
    return true;
}

public boolean deQueue() {
    // 出列
    if (isEmpty()) { // 为空返回 false
        return false;
    }
    front = (front + 1) % array.length; // front 只需要往后走
    return true;
}

public int Front() {
    if (isEmpty()) {
        return -1;
    }
    return array[front];
}

public int Rear() {
    if (isEmpty()) {
        return -1;
    }
    // 这里三目操作符判断是否为 0 如果为 0,将 rear 回退到最后一个位置,不为 0 则 -1
    int temp = (rear == 0) ? array.length - 1 : rear - 1;
    return array[temp];
}

public boolean isEmpty() {
    return front == rear;
}

public boolean isFull() {
    return (rear + 1) % array.length == front;
}

用队列实现栈

因为队列是先进先出的,而我们的栈是先进后出的,两种线性结构的关系是颠倒的,一个队列是不能完成的,我们需要两个队列互相工作来完成。 辅助队列先获取数值,保证辅助队列是最后一个拿到值的,然后将主队列的值给到辅助队列,在交换两个队列的数值。因为队列关系先进先出,每一次最后一个值就是队列先出的数值。 主队列不为空,将主队列的元素都 poll 出放到辅助栈中,使用一个 tmp 来将主队列(这里主队列已经遍历完)和辅助队列交换。

import java.util.LinkedList;
import java.util.Queue;

public class MyStack {
    Queue<Integer> q1; // 主队列
    Queue<Integer> q2; // 辅助队列

    public MyStack() {
        q1 = new LinkedList<>(); // 构造方法
        q2 = new LinkedList<>();
    }

    public void push(int x) {
        q2.offer(x);
        while (!q1.isEmpty()) { // 主队列不为空,则将主队列出列给到辅助队列
            q2.offer(q1.poll());
        }
        // 走到这里主队列是为空
        Queue<Integer> tmp = q1;
        q1 = q2;
        q2 = tmp; // 将两个队列交换
    }

    public int pop() {
        return q1.poll();
    }

    public int top() {
        return q1.peek();
    }

    public boolean empty() {
        return q1.isEmpty();
    }
}

用栈来实现队列

栈来实现队列,栈是先进后出的顺序,而队列是先进先出的顺序。将 push 都放到 a 栈中,当我们 peek 或者是要删除的时候,我们都将 a 栈的元素 pop 给 b 栈,这样 b 栈已经有了我们的元素。

但是我们还需要考虑的是丢掉元素后如果在一起添加元素到 a 栈呢,这里我们给一个条件,如果 b 的栈不为空时,我们仍然用 b 栈的队列。如果 a 为空,这两个栈都是空的说明没有元素直接返回 -1,如果 a 不为空的话且 b 没有新的元素 b 继续捕获新的 a 栈中所有的元素。

import java.util.Stack;

class MyQueue {
    Stack<Integer> A;
    Stack<Integer> B;

    public MyQueue() {
        A = new Stack<>();
        B = new Stack<>();
    }

    public void push(int x) {
        A.push(x);
    }

    public int pop() {
        int check = peek();
        B.pop();
        return check;
    }

    public int peek() {
        // 先判断 b 是否是空的,如果不是空的直接返回,是空才可以往下走
        if (!B.isEmpty()) return B.peek();
        // 因为 b 还不是空的,所以不需要将 a 栈放到 b 中
        if (A.isEmpty()) return -1;
        while (!A.isEmpty()) {
            B.push(A.pop()); // 将所有的 a 放到 b 中
        }
        return B.peek();
    }

    public boolean empty() {
        return A.isEmpty() && B.isEmpty(); // a 和 b 都为空才为空
    }
}

总结

栈分为栈顶和栈底,最先进的为栈底,最后进的为栈顶。 队列分为队头和队尾,最先进的为队头,最后进的为队尾。

目录

  1. Java 栈和队列
  2. 栈的概念(Stack)
  3. 栈的实现
  4. 队列(Queue)
  5. 模拟实现队列 (双链表实现)
  6. 循环队列(循环数组实现)
  7. 用队列实现栈
  8. 用栈来实现队列
  9. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 滑动窗口算法详解:水果成篮问题
  • Linux 常用命令大全:系统管理与安全运维
  • Ollama 模型管理与 Open-WebUI 大模型交互配置
  • Java Lambda 表达式详解
  • MATLAB 智能代码生成工具 Copilot_AI 功能介绍
  • Git 2.53.0 Windows 安装与 SSH 免密配置详解
  • 数据结构:快速排序分区逻辑与冒泡排序性能深度评测
  • Python 数据库操作指南:使用 SQLAlchemy ORM 实现高效开发
  • Cherry Studio 本地 AI 模型远程访问配置指南
  • 2023年12月GESP C++七级真题:商品交易
  • OpenClaw 高级配置:模型容灾、多 Agent 协作与远程 macOS 控制
  • 二叉树算法实战:美国血统重建与深度宽度计算
  • 2026 年 AI 学习路线:从入门到精通的系统指南
  • Python JSON 库深度对比:json、simdjson 与 orjson
  • 通义万相 Wan2.2 开源:270 亿参数视频生成模型支持消费级显卡运行
  • 基于协同过滤算法的理财产品推荐系统 Flask 实现
  • 算法实战:位运算求解两数之和、唯一数字及缺失数字
  • C++ STL 容器适配器详解:Stack、Queue 与 Priority Queue 的本质与实现
  • 五大主流远程桌面软件实测对比与选购指南
  • 基于 Q-learning 的无人机三维路径规划算法原理与 MATLAB 实现

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online