「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战
前言
之前的文章,认识栈结构,并用数组的相关方法,实现了一个栈的类结构,并提供了增、删、改、查的相关方法。接下来就来认识一下队列结构!
认识队列
什么是队列(Queue)
-
也是一种受限的线性表,先进先出
-
受限之处在于它只允许在表的 前端 进行删除操作
-
只能在表的 后端 进行插入操作
生活中的队列结构
-
排队
-
WC
开发中的队列结构
1、打印队列:
-
有五份文档需要打印,这些文档会按照顺序放入打印队列中
-
打印机会依次从队列中取出文档,先放入的先取出,然后打印文档
-
依次打印五分文档
2、线程队列
-
在开发中,为了让任务可以并行处理,通常会开启多个线程
-
但是,我们不能让大量线程同时运行处理任务(导致占用过多资源)
-
这时,在有需要开启线程处理任务的情况下,我们需要开启线程队列
-
线程队列会按顺序来启动线程,并处理对应的任务
队列的实现
这里也使用数组,来实现一个队列的类
队列的常见操作
-
enqueue:向队列尾部添加一个(或多个)新的项
-
dequeue:移除队列的第一项,并返回这一被删除的项
-
front:返回队列中的第一个元素,并且不修改队列
-
isEmpty:判断这个队列中是否为空
-
size:返回队列里的元素个数
-
toString:将队列的内容以字符串的形式返回
代码
class Queue {
items = []
enqueue(element) {
this.items.push(element)
}
dequeue() {
return this.items.shift()
}
front() {
return this.items[0]
}
isEmpty() {
return this.items.length === 0
}
size() {
return this.items.length
}
toString() {
return this.items.join('')
}
}
测试代码
const queue = new Queue()
queue.items = ['a', 'b', 'c', 'd']
console.log(queue.dequeue()) // 'a'
console.log(queue.front()) // 'b'
console.log(queue.enqueue(1)) // undefined
console.log(queue.size()) // 5
console.log(queue.isEmpty()) // false
console.log(queue.toString()) // 'bcd12'
队列的常见面试题
击鼓传花
规则:
1、班级中玩一个游戏,所有学生围成一圈,从某位学生开始向旁边同学传递一朵花
2、裁判在击鼓,鼓声停下时,花在谁手上就要表演节目
3、将表演节目修改为直接淘汰!
4、最后剩下的人获得胜利,请问这个胜利者是哪个位置的人?
封装一个基于队列的函数:
-
参数:所有参与者的姓名、间隔的数字
-
结果:胜利者的姓名
const Queue = require('./queue-demo')
function passFlowerGame(nameList, number) {
const queue = new Queue()
for (let i = 0; i < nameList.length; i++) {
queue.enqueue(nameList[i])
}
while (queue.size() > 1) {
for(let i = 0; i < number - 1; i++) {
queue.enqueue(queue.dequeue())
}
queue.dequeue()
}
console.log(queue.toString())
return queue.front()
}
console.log(passFlowerGame([11,22,33,44,55], 2)) // 33
关于优先级队列
特点
-
普通队列插入一个元素时,该元素会被放入到后端,并且需要等之前的元素处理完,才会处理这个数据
-
但是优先级队列,在插入一个元素时会考虑该数据的优先级,与其他数据的优先级进行比较
-
比较完成后,得出这个元素应该在队列中的正确位置
优先级队列主要考虑的问题
-
每个元素不再只是一个数据,而且包含了该数据的优先级
-
根据数据的优先级来放入正确的位置
现实例子
1、登机顺序:
-
头等舱、商务舱乘客优先级大于经济舱;
-
在部分国家,老人、孕妇、儿童登机,也享有更高的优先级
2、医院急诊科排队
- 医生会优先处理病情更严重的患者
3、计算机中,也是通过优先级队列来重新排序队列中任务的顺序
- 根据每个线程的重要性不同,通过优先级的大小,来决定该线程在队列中被处理的次序
优先级队列的实现
由于优先级队列与普通队列结构之间,只有插入数据时,需要考虑他的优先级,因此只需要修改上文实现的 Queue 类的 enqueue方法即可
代码
class PriorityQueueElement {
element = undefined;
priority = undefined;
constructor(element, priority) {
this.element = element;
this.priority = priority;
}
}
class PriorityQueue extends Queue{ // 继承上文实现的 Queue 类
items: PriorityQueueElement[] = [];
constructor() {
super();
}
enqueue(element, priority) {
const queueElement = new PriorityQueueElement(element, priority);
if (this.isEmpty()) {
this.items.push(queueElement);
} else {
let added = false
for (let i = 0; i < this.items.length; i++) {
if(queueElement.priority < this.items[i].priority) {
this.items.splice(i, 0, queueElement)
added = true
break
}
}
if (!added) {
this.items.push(queueElement)
}
}
}
}
测试代码
const priorityQueue = new PriorityQueue();
priorityQueue.enqueue('aaa', 29)
priorityQueue.enqueue('bbb', 21)
priorityQueue.enqueue('ccc', 10)
priorityQueue.enqueue('ddd', 14)
console.log(priorityQueue.items)
//[
// PriorityQueueElement { element: 'ccc', priority: 10 },
// PriorityQueueElement { element: 'ddd', priority: 14 },
// PriorityQueueElement { element: 'bbb', priority: 21 },
// PriorityQueueElement { element: 'aaa', priority: 29 }
//]