4. 队列(queue))
4.1 简介
- 队列是先进先出(FIFO, First In, First Out)的线性表
- 常由链表或数组实现:
- 顺序队列:数组实现的队列
- 链式队列:链表实现的对她
- 队列只允许在后端(raer)进行插入操作(入队,enqueue);在前端(front)进行删除操作(出队,dequeue)
- 执行复杂度
- 访问:O(n)
- 插入/删除:O(1),后端插入前端删除
4.2 分类
4.2.1单队列
单队列就是常见队列,元素添加到队尾。分为顺序队列和链式队列。
- ”假溢出”问题:顺序队列存在明明有位置却不能添加的情况
在进行入队和出队操作时,front和rear都会持续向后移动,当rear移动到最后时,无法添加数据(即使数组在最前还有空余空间)
- “越界”问题:添加元素时,rear移动到数组之外
为了避免当只有一个元素的时候,队头和队尾重合使处理变得麻烦,所以引入两个指针,front 指针指向对头元素,rear 指针指向队列最后一个元素的下一个位置,这样当 front 等于 rear 时,此队列不是还剩一个元素,而是空队列。——From 《大话数据结构》
4.2.2 循环队列
循环队列可以解决假溢出和越界问题。
循环队列的rear移动到数组的最后时,下一次移动至数组下表为0
循环队列的 front=rear
时循环队列可能为空也可能为满,解决方法:
- 可以设置一个标志变量
flag
,当front==rear
并且flag=0
的时候队列为空,当front==rear
并且flag=1
的时候队列为满。- 队列为空的时候就是
front==rear
,队列满的时候,我们保证数组还有一个空闲的位置,rear 就指向这个空闲位置,如下图所示,那么现在判断队列是否为满的条件就是:(rear+1) % QueueSize= front
4.3 常见应用场景
处理需要按一定顺序进行时
- 阻塞队列:在队列基础上加入阻塞操作。队列为空时,出队阻塞;队列为满时,入队阻塞
- 线程池中的请求/任务队列:线程池没有空闲线程时将请求放在队列中,有空闲时从队列中获取任务执行。
- 无界队列(链表):一直入列,除非系统资源耗尽
- 有界队列(数组):队列满后会拒绝请求
- Linux内核进程队列(按优先级排列)
- 播放列表
- 消息队列
- ……