【若川视野 x 源码共读】第32期 | yocto-queue 队列 链表

464 阅读4分钟

1、yocto-queue简介

1.1 Tiny queue data structure(微型队列数据结构使用场景)

You should use this package instead of an array if you do a lot of Array#push() and Array#shift() on large arrays, since Array#shift() has linear time complexity O(n)  while Queue#dequeue() has constant time complexity O(1) . That makes a huge difference for large arrays. (如果你在大型数组上做很多事情,你应该使用这个包而不是Array#push()数组Array#shift(),因为Array#shift()它具有线性时间复杂度 O(n)Queue#dequeue()具有恒定时间复杂度 O(1) 。这对大型阵列产生了巨大的影响。)

1.2 队伍作用

队列是元素的有序列表,其中一个元素插入到队列的末尾并从队列的前面移除。队列基于先进先出 ( FIFO ) 原则工作。

1.2 队列的工作原理示意图

image.png

2、yocto的API

2.1 queue = new Queue()

该实例是一个Iterable,这意味着您可以使用“for...of”循环从前到后遍历队列,或者使用扩展将队列转换为数组。除非你真的需要,否则不要这样做,因为它很慢。

2.2 .enqueue(value),向队列中添加一个值。

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++;
	}

2.3 .dequeue(),删除队列中的下一个值。

dequeue() {
		const current = this.#head;
		// 当队列为空的时候返回
		if (!current) {
			return;
		}
		// 删除头部值,把指针指向头部后一个值
		this.#head = this.#head.next;
		// 队列长度减一
		this.#size--;
		return current.value;
	}

undefined如果队列为空,则返回删除的值。

2.4 .clear() 清空队列。

clear() {
		this.#head = undefined;
		this.#tail = undefined;
		this.#size = 0;
	}

2.5 .size(), 获取队列的大小。

// class的get,可以或者#size值,且外部无法改变(外部需要改变,需要定义一个set方法进行值的改变)
get size() {
    return this.#size;
}

2.6 * [Symbol.iterator], 为队列添加迭代器,使队列可以完成遍历操作。

具有Iterator接口的数据:数组、类数组对象、Map和Set结构(线性数据) 不具有Iterator接口的数据可以通过部署iterator转换为线性数据

* [Symbol.iterator]() {
		let current = this.#head;

		while (current) {
			yield current.value;
			current = current.next;
		}
	}

3、ava测试库

3.1 ava测试运行器简介

  • 轻量和高效
  • 简单的测试语法
  • 并发运行测试
  • 强制编写原子测试(一旦开始,就一直运行到结束,中间不会切换到另一个测试)
  • 没有隐藏的全局变量
  • 包含 TypeScript 和 Flow 的类型定义
  • Magic assert,AVA 加入了代码摘录和干净的 diff 到实际和期望的值。如果断言中的值是 object 或者 array,那么只有 diff 会显示出来,去掉了干扰让人专注问题。同时 diff 是带语法高亮的!如果你正在比较两个 string ,不管是单行还是多行的,AVA 都使用另一种 diff 显示,来高亮出新增和删除的字符。
  • 为每个测试文件隔离环境,每个测试文件都会在一个独立的 Node 进程中运行,这样让你可以在一个测试文件中改变全局状态或将其覆盖一个内置的全局状态,而不会影响其他测试文件。这样更加有效地利用现代的多核处理器,让多个测试可以并发地执行。
  • 用 ES2017 编写测试
  • 支持 Promise
  • 支持 Generator
  • 支持 Async
  • 支持 Observable ,AVA 自带对 observables 的内置支持。如果你从测试中返回一个 observable,AVA 会自动消费它使其在测试结束前完成。

你不需要使用 “callback 模式" 或者调用 t.end()

test(t => {
    t.plan(3);
    return Observable.of(1, 2, 3, 4, 5, 6)
        .filter(n => {
            // 只有奇数
            return n % 2 === 0;
        })
        .map(() => t.pass());
});
$ ava --tap | tap-nyan
  • 简明的堆栈跟踪AVA 会在堆栈跟踪信息里面自动移除不相关的行,让你更快地找到错误的原因。

3.1.1 测试语法

import test from 'ava';

test(t => {
    t.deepEqual([1, 2], [1, 2]);
});

3.2 test.js测试文件

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(), '❤️');
});

test('iterable', t => {
	const queue = new Queue();
	queue.enqueue('🦄');
	queue.enqueue('🌈');
	t.deepEqual([...queue], ['🦄', '🌈','a']); // 判断队列是否与后面的值全等
});

4、总结

1.了解队列进程,在操作大型数组时可以使用yocto-queue进行指针的偏移,降低数据时间复杂度

2.加深了迭代器知识的印象和理解

3.新了解了ava自动化测试库

4.部分配图和笔记有参考这位同学的