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

栈和队列的奇妙冒险:用栈实现队列

栈和队列的奇妙冒险:用栈实现队列

大家好,欢迎来到代码的奇幻世界!今天我们要探讨一个有趣的问题:如何用栈来实现队列?这就像是用咖啡杯来当茶壶用 —— 虽然有点奇怪,但只要方法正确,也能倒出好茶!

问题背景

在编程的世界里,栈和队列是两种基本的数据结构。栈就像是一叠盘子,只能从顶部取盘子(后进先出,LIFO);而队列则像是排队买奶茶,先来的人先拿到奶茶(先进先出,FIFO)。现在,我们要用栈这种 “盘子堆” 来实现队列这种 “奶茶排队”,这可真是个有趣的挑战!

实现思路

想象一下,你有两个栈(盘子堆),一个用来放新加入的元素(栈 1),另一个用来按顺序取出元素(栈 2)。当需要取出元素时,如果栈 2 是空的,就把栈 1 中的所有元素一个个弹出并压入栈 2,这样栈 2 中的元素顺序就和队列的顺序一样了!

下面是具体的实现代码:

static class SQueue {// 栈1负责存储新元素,栈2负责按顺序提供元素private final Stack<Integer> stack1 = new Stack<>();private final Stack<Integer> stack2 = new Stack<>();public SQueue() {}// 入队操作:直接把元素压入栈1public void offer(int value) {stack1.push(value);}// 查看队首元素public Integer peek() {// 如果栈2空了,就从栈1中 reload 元素if (stack2.isEmpty()) {reload();}// 如果 reload 后还是空,说明队列里没元素了if (stack2.isEmpty()) {throw new EmptyStackException();}return stack2.peek();}// 出队操作public Integer poll() {if (stack2.isEmpty()) {reload();}if (stack2.isEmpty()) {throw new EmptyStackException();}return stack2.pop();}// 重新装载:把栈1的元素全部倒入栈2private void reload() {while (!stack1.isEmpty()) {stack2.push(stack1.pop());}}
}

代码解释

这个实现中有几个关键点:

  1. 两个栈的分工
    • 栈 1(stack1):只负责接收新加入的元素,就像一个 “仓库”,只进不出。
    • 栈 2(stack2):只负责按顺序提供元素,就像一个 “商店货架”,元素从这里被顾客(程序)取走。
  2. 元素的流动
    • 当需要取元素时,如果栈 2(货架)是空的,就从栈 1(仓库)中把所有元素搬到栈 2 中。
    • 搬运的过程会把元素的顺序反转两次(从栈 1 弹出时反转一次,压入栈 2 时再反转一次),最终得到正确的顺序。
  3. 效率分析
    • 入队操作(offer):时间复杂度是 O (1),就像把盘子放到堆顶上一样快。
    • 出队操作(poll)和查看队首(peek):平均时间复杂度是 O (1)。虽然在需要 reload 时会比较慢,但每个元素最多只会被 reload 一次,所以总体上还是很快的!

测试代码

让我们来测试一下这个神奇的 “栈变队列”:

public static void main(String[] args) {SQueue sQueue = new SQueue();// 让 0 到 9 这 10 个元素排好队for (int i = 0; i < 10; i++) {sQueue.offer(i);}// 看看是不是按顺序出来for (int i = 0; i < 10; i++) {System.out.println(sQueue.poll());}
}

运行这段代码,你会看到输出是:

0
1
2
3
4
5
6
7
8
9

完美!就像真正的队列一样,先来的元素先出队。

总结

通过使用两个栈,我们成功地实现了队列的功能。这种实现方式不仅巧妙,而且效率也很高。就像用咖啡杯当茶壶一样,虽然不是最常规的方法,但只要能倒出好茶,又有什么关系呢?

下次当你遇到只能用栈的场景,却需要队列的功能时,不妨试试这个方法,说不定会给你带来惊喜哦!

好了,今天的代码奇幻冒险就到这里,我们下次再见!

http://www.xdnf.cn/news/12898.html

相关文章:

  • 6个月Python学习计划 Day 17 - 继承、多态与魔术方法
  • 快速上手Linux文本流编辑器sed
  • 智慧城市项目总体建设方案(Word700页+)
  • 基于深度强化学习的智能机器人导航系统
  • 黑马Javaweb Request和Response
  • 05.查询表
  • 【无人机】地面站crazyfile-cfclient免安装方法,Python3.10的整体环境配置打包
  • OCS2库及其在足式机器人上的应用
  • RK3568项目(七)--uboot系统之外设与PMIC详解
  • 真实案例分享,Augment Code和Cursor那个比较好用?
  • PDF 转 Word 工具 拖拽秒转可编辑文档,批量处理保留原格式
  • 用通俗的话解释下MCP是个啥?
  • android 模拟器如何进行单模块更新
  • 【设计模式】1.简单工厂、工厂、抽象工厂模式
  • ORACLE 修改端口号之后无法启动?
  • 港理工:LLM推理与推荐能力集成
  • ElGamal加密算法:离散对数难题的安全基石
  • (五)Linux性能优化-CPU-性能优化
  • GitOps 核心思想 - 当 Git 成为唯一信源
  • 2025-04-22-X86 架构与 Arm 架构异同及应用
  • Keil Mdk新建stm32工程找不到对应芯片开发包的解决方法
  • LeetCode - 148. 排序链表
  • Jupyter notebook的文章结构目录查看方式和汉化方法
  • 基于Matlab肺结节分割(肺结节提取)源程序,也有GUI人机界面版本。使用传统图像分割方法,非深度学习方法。使用LIDC-IDRI数据集。
  • RoseMirrorHA 双机热备全解析
  • Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
  • Unity VR/MR开发-开发环境准备
  • JS设计模式(5): 发布订阅模式
  • 矩阵详解:从基础概念到实际应用
  • 词法分析和词性标注 自然语言处理