# 介绍

栈和队列都属于操作受限的线性表,仅支持有限的操作。特定的数据结构主要是对特定使用场景的抽象,所以从功能上讲,数组和链表可以替代栈和队列(本质上栈和队列都有数组或链表的实现方式),但是相比之下,数组和链表暴露了更多的操作接口,操作更灵活的同时,也更容易出错

# 栈的介绍

特点:先进后出(First in, last out)

两个基本操作:通过均摊时间分析,操作复杂度都为 O(1)

  • 入栈(push)
  • 出栈(pop)

入栈时,如果栈已满,将进行栈的扩容和数据的复制,因此最坏复杂度是 O(n),但是通过均摊时间分析,可知平均复杂度还是O(1)

栈的实现

  • 顺序栈(数组实现):支持动态扩容的顺序栈: 与数组动态扩容类似
  • 链式栈(链表实现):天然支持动态扩容,但是需要消耗额外的内存空间储存 next 指针

常见应用

  • 函数调用,栈帧
  • 表达式求值(使用两个栈,分别存储运算数和运算符)
  • 括号匹配
  • 浏览器前进后退(使用两个栈)

# 队列介绍

特点:先进先出(First in, first out)

两个基本操作:通过均摊时间分析,操作复杂度都为 O(1)

  • 入队(enqueue)
  • 出队(dequeue)

队列的实现:栈只需要一个栈顶指针,而队列需要两个,分别指向队首(head)和队尾(tail)

  • 顺序队列(数组实现):在不断的入队出队操作中,头尾指针都将持续向后移动
    • 解决方案1: 数据搬迁,在进行入队操作时,如果没有空闲空间,则触发数据搬迁
    • 解决方案2: 循环队列,避免了数据搬迁,更加高效,关键是要区分队空和队满的条件
  • 链式队列(链表实现):无限制的队列,但是同样需要额外的内存空间

常见应用

  • CPU 调度
  • 线程池处理请求

队列变种

  • 阻塞队列
    • 队列为空时,出队操作会被阻塞,直到队列中有了数据再返回数据
    • 队列已满时,入队操作会被阻塞,直到队列中有了空闲位置再插入数据
  • 并发队列:线程安全的队列
Last Updated: 9/4/2020, 4:36:00 AM