《数据结构与算法》4-队列

队列(queue)也是一种操作受限的线性表。他的操作特点是先进先出

  • 队列有头节点
  • 队列有尾节点
  • 入队 enQueue(T t)只能增加到尾节点
  • 出队 T dequeue() 只能从头节点出队

上面的四个特性决定了队列的先进先出性。在需要公平排队的情境下适合使用队列

队列也可以根据底层实现分为两种

  • 底层是数组的顺序队列
  • 底层是链表的链式队列

顺序队列的主要构造

  • T[] data 存储数据的数组
  • int size  队列的大小
  • int head  队列的头下标
  • int tail    队列的尾下标

如果要enQueue(T t)操作,把tail下标指定的尾节点的数组位置赋值成T,然后tail+1;

如果要deQueue()操作,返回head下标指定的数据,然后head+1;

上面的两个基本操作会遇到一个问题,如果一直enQueue(T t)tail很快就会到达数组的最大值,这个时候有两种选择:

  1. 拒绝入队
  2. 扩展队列数组

如果选择扩展队列,相当于申请一个1.5倍的数组,然后把head-》tail的数据全部复制过去

如果一直deQueue也会遇到一个问题,head会很快追上tail。这个时候队列又为空。但是head之前的数据位置还能重复使用,

这个时候其实可以用复制的方法,把head->tail的数据一起复制到从0开始的位置。

为了免除上面head->tail之后的复制操作,我们引入循环队列来解决这个问题,但是要注意判断循环队列满的情况

计算公式:(tail+1)%size = head

如果我们使用链式队列,就不会担心这个问题,链表可以无限延长,但是我们也要注意链表的长度,否则会内存被占用的太厉害。

  • 队列为空的时候无法出队
  • 队列满的时候无法入队

当无法操作出队入队的时候,线程阻塞,直到别的线程唤醒阻塞的线程。当操作线程出现阻塞的时候叫阻塞队列

多个线程同时出队入队操作并且线程安全的队列叫 并发队列

在开发中会遇到很多需要用到队列的情况,最主要的场景就是消费者模式,生产者入队,消费者出队

基于消费者模式,有多个实际应用场景,比如mq消费,线程池资源等

猜你喜欢

转载自blog.csdn.net/David_lou/article/details/108608494