「我正在参与掘金会员专属活动-源码共读第一期,点击参与」
本篇文章介绍的是
yocto-queue
,一个微型队列的数据结构。
数组在做向前插入unshift
删除shift
时间复杂度为O(n)
,而队列仅仅是O(1)
。如果需要频繁进行操作的话,推荐队列作为数据存储的首选。
安装
$ npm install yocto-queue
使用
import Queue from 'yocto-queue';
const queue = new Queue();
queue.enqueue('🦄');
queue.enqueue('🌈');
console.log(queue.size);
//=> 2
console.log(...queue);
//=> '🦄 🌈'
console.log(queue.dequeue());
//=> '🦄'
console.log(queue.dequeue());
//=> '🌈'
API
queue = new Queue()
实例是一个可迭代对象,这就是说你可以使用for..of
循环迭代它,或者可以使用展开符将它转换成数组,不要这么做,因为这样很慢。
.enqueue(value)
向队列中添加元素
.dequeue()
移除队列中的元素,并返回该值,如果队列为空,返回undefined
.clear()
清空队列
.size
返回队列大小
源码
class Node {
value;
next;
constructor(value) {
this.value = value;
}
}
这个是队列中元素的数据结构
export default class Queue {
#head;
#tail;
#size;
constructor() {
this.clear();
}
enqueue(value) {
const node = new Node(value);
if (this.#head) {
this.#tail.next = node;
this.#tail = node;
} else {
this.#head = node;
this.#tail = node;
}
this.#size++;
}
dequeue() {
const current = this.#head;
if (!current) {
return;
}
this.#head = this.#head.next;
this.#size--;
return current.value;
}
clear() {
this.#head = undefined;
this.#tail = undefined;
this.#size = 0;
}
get size() {
return this.#size;
}
* [Symbol.iterator]() {
let current = this.#head;
while (current) {
yield current.value;
current = current.next;
}
}
}
这个是队列的数据结构。
- #head:队列的头部 #tail:队列的尾部 #size 队列的长度
- enqueue: 入队操作(向队列添加元素)。首先会根据传入的
value
构造出node
,如果头部存在,就向#tail
本身和它的next
属性赋值为node
,如果不存在#head
,头部和尾部都赋值为node
-
dequeue:如果存在
#head
,将#head
next属性赋值为#head
,返回原来头部的值。否则返回undefined
-
clear: 将
#head
#tail
置空,#size设置为0 -
自定义一个迭代器:
* [Symbol.iterator]()
测试用例
测试用例使用的是ava
这个包,它默认导出test
方法,可以传入测试自定义名字,和一个回调函数,回调函数接收到一个参数为t
来校验测试结果
test('.enqueue()', t => {
const queue = new Queue();
queue.enqueue('🦄');
t.is(queue.dequeue(), '🦄');
queue.enqueue('🌈');
queue.enqueue('❤️');
t.is(queue.dequeue(), '🌈');
t.is(queue.dequeue(), '❤️');
});
通常我们在开发某个功能的时候可以先把所有的测试用例写出来,然后运行测试,等到所有的测试用例都跑通了,我们的功能也就开发完了。
结束语
这篇文章介绍的队列在插入和删除方面优势确实是比数组的性能高,但是在取值方面是不如数组的,数组在取值O(1)
的复杂度。所以我们在平时选择数据结构还得看实际是怎么应用的。