4-队列

受限的线性结构:
我们已经学习一种受限的线性结构:栈结构。
并且已经知道这种受限的数据结构对于解决某些特定问题,会有特别的效果。
下面,我们再来学习另外一个受限的数据结构:队列。

队列(Queue),它是一种受限的线性表,先进先出(FIFO First In First Out)
受限之处在于它只允许在表的前端(fromt)进行删除操作。
而在表的后端(rear)进行插入操作。

队列示意图:

4 队列 - 图1


队列的应用

  • 打印队列:

    • 有五份文档需要打印,这些文档会按照次序放入到打印队列中。
    • 打印机会依次从队列中取出文档,优先放入的文档,优先被取出,并且对该文档进行打印。
    • 以此类推,直到队列中不再有新的文档。
  • 线程队列:

    • 在开发中,为了让任务可以并行处理,通常会开启多个线程。
    • 但是,我们不能让大量的线程同时运行处理任务。(占用过多的资源)
    • 这个时候,如果有需要开启线程处理任务的情况,我们就会使用线程队列。
    • 线程队列会依照次序来启动线程,并且处理对应的任务。

队列类的创建

  • 队列实现和栈一样,有两种:
    • 基于数组实现
    • 基于链表实现

队列常见操作

  • enqueque(element):向队列尾部添加一个(或多个)新的项。
  • dequeue():移除队列第一(即排在队列最前面的)项,并返回被移除的元素。
  • front():返回队列第一个元素—-最先被添加,也将是最先被移除的元素。队列不做任何变动(不移除元素,只返回元素信息—-与Stack类的peek方法非常类似)。
  • isEmpty():如果队列不包含任何元素,返回true,否则返回false。
  • size():返回队包含的元素个数,与数组的length属性类似。
  • toString():将队列中的内容,转换成字符串形式

代码示例:
class QueueClass {
constructor() {
this.items = [];
}
// 方法
//向队列尾部添加一个(或多个)新的项。
enqueue(element) {
this.items.push(element)
}
//移除队列第一(即排在队列最前面的)项,并返回被移除的元素。
dequeue() {
return this.items.shift();
}
//返回队列第一个元素—-最先被添加,也将是最先被移除的元素。队列不做任何变动。
front() {
if (this.isEmpty()) {
console.error(“items is Emoty”)
return
}
return this.items[0];
}
//如果队列不包含任何元素,返回true,否则返回false。
isEmpty() {
return this.items.length == 0;
}
//返回队包含的元素个数,与数组的length属性类似。
size() {
return this.items.length;
}
//将队列中的内容,转换成字符串形式
toString() {
return this.items.join(“ “);
}
}

案例-击鼓传花:
function passGame(elementArray, num) {
let flowerArray = new QueueClass();

  1. for (let i = 0; i < elementArray.length; i++) {<br /> flowerArray.enqueue(elementArray[i]);<br /> }
  2. while (flowerArray.size() > 1) {<br /> for (let i = 0; i < num - 1; i++) {<br /> // console.log(i);<br /> flowerArray.enqueue(flowerArray.dequeue());<br /> }<br /> console.log(flowerArray.dequeue())<br /> }
  3. console.log("长度是:", flowerArray.size())<br /> console.log("最后留下的是:", flowerArray.items)<br /> }
  4. let elementArray = [1, 2, 3, 4, 5, 6];<br /> passGame(elementArray, 5);

优先级队列
优先级队列特点:

  • 我们知道,普通的队列插入一个元素,数据会被放在后端,并且需要前面所有的元素都处理完成后才会处理前面的数据。
  • 但是优先级队列,在插入一个元素的时候会考虑该数据的优先级。
  • 和其他数据优先级 进行比较。
  • 比较完成后,可以得出这个元素在队列中正确位置。
  • 其他处理方式,和基本队列的处理方式一样。

优先级队列主要考虑的问题:

  • 每个元素不再只是一个数据,而且包含数据的优先级。
  • 在添加方式中,根据优先级放入正确的位置。

优先级队列的应用:
计算机中,我们也可以通过优先级队列来重新排序队列中的任务顺序。
比如每个线程处理的任务重要性不同,我们可以通过优先级的大小,来决定该线程在队列中被处理的次序。

优先级队列的实现
实现优先级对立相对队列主要有两方面需要考虑:

  1. 封装元素和优先级放在一起(可以封装一个新的构造函数)
  2. 添加元素时,将新插入元素的优先级和队列中已经存在的元素优先级进行比较,以获得自己正确的位置。

数字小者优先进入:
// 封装优先级队列
function PriorityQueue() {
// 在PriorityQueue 重写创建一个类:可以理解成内部类
function QueueElement(element, priority) {
this.element = element;
this.priority = priority;
}
// 封装属性
this.items = []
// 实现插入方法
PriorityQueue.prototype.enqueue = function (element, priority) {
// 1.创建QueueElement 对象
let queueElement = new QueueElement(element, priority);

  1. // 2.判断队列是否为空<br /> if (this.items.length == 0) {<br /> this.items.push(queueElement)<br /> } else {<br /> var added = false;<br /> for (let i = 0; i < this.items.length; i++) {<br /> if (queueElement.priority < this.items[i].priority) {<br /> this.items.splice(i, 0, queueElement);<br /> added = true;<br /> break;<br /> }<br /> }<br /> if (!added) {<br /> this.items.push(queueElement)<br /> }<br /> }<br /> }<br /> }

数字小者优先进入:
class PriorityQueueClass {
constructor() {
this.items = [];
this.QueueElementClass = class QueueElementClass {
constructor(element, priority) {
this.element = element;
this.priority = priority;
}
}
}

  1. enqueue(element, priority) {<br /> let queueElement = new this.QueueElementClass(element, priority);<br /> if (this.items.length == 0) {<br /> this.items.push(queueElement);<br /> } else {<br /> var flag = false;<br /> for (let i = 0; i < this.items.length; i++) {<br /> if (queueElement.priority > this.items[i].priority) {<br /> this.items.splice(i, 0, queueElement);<br /> flag = true;<br /> break;<br /> }<br /> }<br /> if (!flag) {<br /> this.items.push(queueElement);<br /> }<br /> }<br /> }<br /> }

bugBase/queryByCcAndBugname