一、什么是队列
队列是一种先进先出(FIFO)的有序结构,它在队尾添加新元素,在顶部移除元素。在生活中我们最常见的就是排队了,谁在前就先服务谁。在程序中也可以经常看到它的身影,比如JS的事件队列。所以,学习队列对我们理解生活和计算机十分有帮助。
二、实现队列
我们根据队列先进先出的特征,在JS中来模拟实现这个结构。我会创建一个Queue
类,里面会包含以下方法:
- enqueue:进入队列
- dequeue:从队列移除,返回这个被移除的元素
- peek:返回队列第一个元素
- size:返回队列的长度
- isEmpty:队列是否为空
- clear:清空队列
- toString:返回队列的字符串
接下来我会使用ES6的语法来实现它们。
实现Queue
类
首先创建一个Queue
类,使用一个对象来模拟队列。在构造函数中,会有一个count
属性和lowestCount
属性,它们的作用分别是控制队列的长度以及追踪当前队列的第一个元素。
class Queue {
constructor () {
this.count = 0;
this.lowestCount = 0;
this.items = {
};
}
}
实现 enqueue
方法
这个方法实现很简单,就是往队列的后一项增加一个元素,使用count
作为下标。
enqueue (element) {
this.items[this.count++] = element
}
实现 isEmpty
方法
我们使用一个对象来实现的队列,就那么不能简单像数组那样直接返回this.count
的值,因为这个下标是代表的一个元素,比如从前面移除了一个元素,我们需要让lowestCount
往后移一位来跟踪第一个元素,后面的元素的序号是不能变的。如果当前lowestCount
和count
相等的话说明当前队列为空了。可能不是很容易理解,我画张图吧。
为了容易理解,我画一个类似数组的结构。这下我们可以很容易看到,只要this.lowest和this.count相等就表明队列已经空了(好好理解一下)。这下代码就出来了:
isEmpty () {
return this.count - this.lowestCount === 0;
}
(我相信会有人看出来,其实我本人就是不容易理解所以画了图,嘿嘿。)
实现 size
方法
有了上面的理解,这个实现就简单了。
size () {
return this.count - this.lowestCount;
}
实现 dequeue
方法
要删除一个元素需要先判断队列是否为空,有了上面的方法作铺垫就好说了。分三步走:
- 通过
this.lowestCount
返回当前第一个元素,并且存储到一个变量result
中 - 使用
delete
操作符来删除一个对象中的属性 this.lowestCount
往后一位,并且返回这个result
dequeue () {
if (this.isEmpty()) {
return undefiend;
}
const result = this.items[this.lowestCount];
delete this.items[this.lowestCount];
this.lowestCount++;
return result;
}
实现 peek
方法
这个方法是返回队列第一个元素,不用多说了吧,先判断为空,再利用this.lowestCount
返回第一个元素。
peek () {
if (this.isEmpty()) {
return undefiend;
}
return this.items[this.lowestCount];
}
实现 clear
方法
这个方法也很简单,令属性全部设为初始值就可以了。
clear () {
this.count = 0;
this.lowestCount = 0;
this.items = {
};
}
实现 toString
方法
这个方法主要将队列每个元素转化为字符串,每个对象都有默认的toString
方法,我们自己实现一下。实现方法其实也不是特别难,借助了递归思想。
toString() {
if (this.isEmpty()) {
return '';
}
let objString = `${
this.items[this.lowestCount]}`;
for (let i = this.lowestCount + 1; i > 0; i--) {
objString = `${
objString},${
this.items[i]}`
}