🎨
Notes
  • 持续更新中...
  • articles
    • browser
      • 深入理解现代浏览器 - 导航
      • 深入理解现代浏览器 - 架构
      • 深入理解现代浏览器 - 交互
      • 深入理解现代浏览器 - 渲染器进程
    • dsa
      • DSA - 并查集
      • DSA - 哈希表
      • DSA - AVL 树
      • DSA - 二叉树
      • 快速选择
      • Big O 算法复杂度
      • DSA - 栈和队列
      • DSA - 前缀树 Trie
      • DSA - 图
      • DSA - 链表
      • DSA - 递归
    • typescript
      • TypeScript 学习笔记 - 任意属性 (Indexable Types)
      • 力扣的 TypeScript 面试题
      • TypeScript 学习笔记 - as const
      • TypeScript 学习笔记 - infer
    • network
      • Internet Protocol (IP)
      • 计算机网络基础
      • 如何分辨同源和同站
      • DNS 如何查询 IP 地址?
    • vue
      • Nuxt.js 入门
      • 从零实现一个 Mini Vue
      • 从零实现一个简单的 VDOM 引擎
      • 从零实现一个响应式状态管理
    • sorting
      • 排序 - 归并排序
      • 排序 - 冒泡排序
      • 排序 - 选择排序
      • 排序 - 计数排序
      • 排序 - 插入排序
    • compile
      • Compiler and Interpreter
      • Just-In-Time (JIT) Compilers
      • 编译流程
    • others
      • 什么是上下文无关语法
      • 如何在终端打印出有颜色的字
    • dev-ops
      • github-actions
        • GitHub Action 简介
        • GitHub Actions for CI
    • workflow
      • 用 Node 写一个 cli
      • 如何规范 git commit 信息
      • 如何监听 git hooks
      • 如何规范代码风格 - prettier
      • 如何发布一个 npm package
      • 如何规范代码质量 - eslint
    • design-pattern
      • 代理模式
      • 单例模式
      • 策略模式
    • security
      • 点击劫持
      • CSP 内容安全策略
    • javascript
      • 尾调用优化
      • 4种常见的内存泄漏及解决方法
    • unit-test
      • Test Vuejs Application - Chapter 2
      • Test Vuejs Application - Chapter 1
      • Vue Unit Test Intro
    • performance
      • HTTP 缓存
      • 如何优化图片资源
Powered by GitBook
On this page
  • 栈
  • 概念
  • 应用
  • 实现
  • 队列
  • 概念
  • 实现
  • 应用
  • 分类
  • 循环队列

Was this helpful?

  1. articles
  2. dsa

DSA - 栈和队列

PreviousBig O 算法复杂度NextDSA - 前缀树 Trie

Last updated 4 years ago

Was this helpful?

数组是 random access 的数据结构,读取数组数据的时间复杂度是 $O(1)$,就好像翻开一页书,想翻开哪一页就翻开哪一页,没有“打开第 250 页必须先打开第 249 页”这种限制。

链表是 sequential access 数据结构,数组读取操作是线性的,就好像一个竹简,你想要知道竹简最后写了什么,必须先卷开它前面的部分。

而栈和队列都属于 sequentail access 数据结构下的一个分支 limited access 数据结构。

栈

概念

简单复习一下,栈是一种后进先出(LIFO)的数据结构。它是一种受限的数据结构,也就是说,元素只能往栈顶添加,也只能从栈顶移除。就好像一摞盘子,只能往顶部加盘子,也只能从顶部拿走盘子,如果想拿最底下的盘子,就得先把它上面的盘子都移走。

应用

  • 反转字符串

  • 实现“撤销”操作功能时,可以把所有操作都存在栈中

  • 在编译中,将 infix 表达式转换成 prefix 或者 postfix 形式再进行计算。 语法检查的过程中也用到栈来检查括号的有效性。

  • 在代码执行过程中,参数和变量都是存放在调用栈中的。能够使用递归也是因为调用栈使用了栈这种数据结构。

  • 在浏览器中,“后退”按钮的实现也是因为历史记录被存在栈中。

  • 回溯算法中,比如迷宫问题,我们是通过尝试不同路径来寻找问题的解,当遇上 deadend 时,我们就要回溯,回到上一步的位置,这其实有点像“撤销”操作。

  • DFS

  • 内存管理

实现

栈是一种 adapter class,意思是栈是基于其他数据结构实现的,它内部使用的数据结构可以是数组,也可以是链表,等等。虽然底层使用的数据结构不固定,但栈的实现必须提供统一的 API:

  • push()

  • pop()

  • peek()

  • isEmpty()

关于栈的实现还有一个要求,就是各个 API 操作都必须是 $O(1)$ 时间复杂度的。

队列

概念

队列是一种先进先出(FIFO)的数据结构,可以想一下饭堂排队打饭的同学们,先来的同学可以先打饭离开,后来的同学只能排在队伍后面等着。

实现

队列也是一种 adapter class,队列的 API:

  • enqueue()

  • dequeue()

  • isEmpty()

  • getFront()

  • clear()

各操作的时间复杂度都必须是 $O(1)$。

应用

  • BFS

  • CPU 调度、Disk 调度

  • 两个进程之间进行异步传输数据时,队列 is used for synchronization。eg: IO Buffers, pipes, file IO...

  • handling of iterrupts in real-time systems

  • call center phone systems uses queues to hold people calling them in an order

分类

  1. 简单队列

  2. 循环队列:最后一个元素会执行第一个元素。循环队列相对普通队列的优势是它更好地利用了内存,如果队列尾部空间满了而队列头部还有空间的话,使用循环队列我们可以充分利用队头的空间。

  3. 优先队列:每个元素都有一个优先级,元素出列顺序取决于它们的优先级。

  4. Double Ended Queue or Deque:入列和出列操作可以发生在队头也可以在队尾,这种数据结构就不遵循 FIFO 原则了。

循环队列

在一个用数组实现的普通队列中,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们就能使用这些空间去储存新的值。

循环队列的实现

  • 用两个指针,一个表示队头 front,一个表示队尾 rear。

  • 初始化时,把两个指针都设为 -1。

  • 入列时,先检查队列是否满了;接着对 rear 指针进行循环递增操作 rear = (rear + 1) % k, k 是队列元素总数,再把新元素放到 rear 的位置。

  • 出列时,先检查队列是否空了;接着将 front 指针的元素出列,再对 front 指针进行循环递增。

  • 入列第一个元素时还需要将 front 指针更新为 0。

  • 出列最后一个元素时需要将 front 和 rear 指针都重置为 -1。

  • 判断队列是否满了有两种情况:

    • front === 0 && rear === size - 1

    • front === rear + 1

  • 判断队列是否为空:front === -1 && rear === -1

循环队列的应用

  • CPU 调度

  • 内存管理

  • 交通管理

相关题目:

more on this topic.
622. 设计循环队列