[test] test coverage enriched to 90.37%

This commit is contained in:
Revone 2023-10-29 21:52:27 +08:00
parent c492af0461
commit f87e682f26
47 changed files with 343 additions and 153 deletions

View file

@ -273,11 +273,6 @@ module.exports = {
your webpack config is a function and takes them (see webpack documentation
for details)
*/
// webpackConfig: {
// fileName: './webpack.config.js',
// env: {},
// arguments: {},
// },
/* Babel config ('.babelrc', '.babelrc.json', '.babelrc.json5', ...) to use
for compilation (and whatever other naughty things babel plugins do to

1
.gitignore vendored
View file

@ -8,6 +8,7 @@ npm-debug.*
*.orig.*
.DS_Store
.idea
.vscode
/notes
/backup

View file

@ -1,4 +1,5 @@
.idea
.vscode
.auto-changelog
.auto-changelog-template.hbs
.dependency-cruiser.js
@ -9,7 +10,6 @@
/notes
/backup
/webpack.config.js
/scripts
/tsconfig.prod.json

62
package-lock.json generated
View file

@ -1045,9 +1045,9 @@
}
},
"node_modules/@eslint-community/regexpp": {
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz",
"integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==",
"version": "4.10.0",
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
"integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
"dev": true,
"engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
@ -2021,12 +2021,12 @@
"dev": true
},
"node_modules/@types/node": {
"version": "20.8.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.8.tgz",
"integrity": "sha512-YRsdVxq6OaLfmR9Hy816IMp33xOBjfyOgUd77ehqg96CFywxAPbDbXvAsuN2KVg2HOT8Eh6uAfU+l4WffwPVrQ==",
"version": "20.8.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz",
"integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==",
"dev": true,
"dependencies": {
"undici-types": "~5.25.1"
"undici-types": "~5.26.4"
}
},
"node_modules/@types/semver": {
@ -2728,9 +2728,9 @@
}
},
"node_modules/avl-tree-typed": {
"version": "1.39.0",
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.39.0.tgz",
"integrity": "sha512-YpYfpO0slt8R5lcy4wrz7inKFAG1NKUZk2FnJ2FEYIdBJaBIUvW0cflx6Cuuy1iRiXbazpTqGQgKC0nERWUiow==",
"version": "1.39.1",
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.39.1.tgz",
"integrity": "sha512-V4H5cBue8qzsUYzDIngPR6FJELuuMtwYSk34BdpgwPHpo79ZL0LqJmEiIY9FCmkoYPQFvZAz/Z7+RH9MJXgZPA==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.39.0"
@ -2927,9 +2927,9 @@
}
},
"node_modules/binary-tree-typed": {
"version": "1.39.0",
"resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.39.0.tgz",
"integrity": "sha512-oJzCbrs+l4qacscxFvVB/ielr22KiO8z/bWSx/tJmafpinWmkAuQIBRGqo+frfFi8MKstNerHPEF+4yT8AakUA==",
"version": "1.39.1",
"resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.39.1.tgz",
"integrity": "sha512-fbPwGQXmy9GKw/23yRm9c+9wDNgXbhvGUP6za0NQuo3kvJ522SAEzvgwPXEqO92RIKT/OpP0+aO5dpTJaOiodQ==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.39.0"
@ -3011,9 +3011,9 @@
}
},
"node_modules/bst-typed": {
"version": "1.39.0",
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.39.0.tgz",
"integrity": "sha512-AvitIe0j8jPrXyZkQI5zhTYIc4eS5rxvW59/0YHymg54BeMs+zm1WzouPhsh7qp9D+IcTpQmqDY0kjc07Tic3w==",
"version": "1.39.1",
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.39.1.tgz",
"integrity": "sha512-Oo86lN3GJIODrGHZSpNJZ7X1N1adgEpY8kd7jOvZd+zF2BHEJVpW8uTk3PtSgbCLGnEkSzE2lXWaaOZh5F9x1A==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.39.0"
@ -3082,9 +3082,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001554",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001554.tgz",
"integrity": "sha512-A2E3U//MBwbJVzebddm1YfNp7Nud5Ip+IPn4BozBmn4KqVX7AvluoIDFWjsv5OkGnKUXQVmMSoMKLa3ScCblcQ==",
"version": "1.0.30001557",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001557.tgz",
"integrity": "sha512-91oR7hLNUP3gG6MLU+n96em322a8Xzes8wWdBKhLgUoiJsAF5irZnxSUCbc+qUZXNnPCfUwLOi9ZCZpkvjQajw==",
"dev": true,
"funding": [
{
@ -3413,9 +3413,9 @@
}
},
"node_modules/data-structure-typed": {
"version": "1.39.0",
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.39.0.tgz",
"integrity": "sha512-HESmI/a+uE3ELRDVKIBSmfgSMep4ETJco8jeZD2By5lNhMW9HDZE+SGNqlSeBJd3PdJyact9dWlXWwg7S3+ztQ==",
"version": "1.39.1",
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.39.1.tgz",
"integrity": "sha512-zAotqpGJoWKG12b4pybA05oih3RAy50RlD++ye8M58AjcM5Aw8lZjWlsNmi+ICiAdq8P0xdJM6Z7/etysctJZg==",
"dev": true
},
"node_modules/debug": {
@ -3598,9 +3598,9 @@
"dev": true
},
"node_modules/electron-to-chromium": {
"version": "1.4.566",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.566.tgz",
"integrity": "sha512-mv+fAy27uOmTVlUULy15U3DVJ+jg+8iyKH1bpwboCRhtDC69GKf1PPTZvEIhCyDr81RFqfxZJYrbgp933a1vtg==",
"version": "1.4.569",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.569.tgz",
"integrity": "sha512-LsrJjZ0IbVy12ApW3gpYpcmHS3iRxH4bkKOW98y1/D+3cvDUWGcbzbsFinfUS8knpcZk/PG/2p/RnkMCYN7PVg==",
"dev": true
},
"node_modules/emittery": {
@ -4771,9 +4771,9 @@
}
},
"node_modules/heap-typed": {
"version": "1.39.0",
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.39.0.tgz",
"integrity": "sha512-n9Qa+Ph6nnqRN6lz52R62CHrpgWixU/39P22WT9Epf+4dj+pDYPKEGekCCidjjxQXgoR56d6XjnZWFgiQYYN4Q==",
"version": "1.39.1",
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.39.1.tgz",
"integrity": "sha512-+fKr3EKYNGLK9ZVLeZZFP58eKvGv/zWGYbBOZYIXkQZeBXtdL0b4rHL0LsoIpuyPMbhXDFNOhaasG4D1NbCu2Q==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.39.0"
@ -8915,9 +8915,9 @@
}
},
"node_modules/undici-types": {
"version": "5.25.3",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz",
"integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==",
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"dev": true
},
"node_modules/update-browserslist-db": {

View file

@ -1,6 +1,6 @@
{
"name": "data-structure-typed",
"version": "1.39.1",
"version": "1.39.2",
"description": "Data Structures of Javascript & TypeScript. Binary Tree, BST, Graph, Heap, Priority Queue, Linked List, Queue, Deque, Stack, AVL Tree, Tree Multiset, Trie, Directed Graph, Undirected Graph, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue.",
"main": "dist/cjs/index.js",
"module": "dist/mjs/index.js",

View file

@ -21,8 +21,7 @@ export class AVLTreeNode<V = any, N extends AVLTreeNode<V, N> = AVLTreeNodeNeste
export class AVLTree<V = any, N extends AVLTreeNode<V, N> = AVLTreeNode<V, AVLTreeNodeNested<V>>>
extends BST<V, N>
implements IBinaryTree<V, N>
{
implements IBinaryTree<V, N> {
/**
* This is a constructor function for an AVL tree data structure in TypeScript.
* @param {AVLTreeOptions} [options] - The `options` parameter is an optional object that can be passed to the
@ -161,7 +160,7 @@ export class AVLTree<V = any, N extends AVLTreeNode<V, N> = AVLTreeNode<V, AVLTr
// Balance Restoration: If a balance issue is discovered after inserting a node, it requires balance restoration operations. Balance restoration includes four basic cases where rotation operations need to be performed to fix the balance:
switch (
this._balanceFactor(A) // second O(1)
) {
) {
case -2:
if (A && A.left) {
if (this._balanceFactor(A.left) <= 0) {

View file

@ -17,7 +17,7 @@ export class BinaryIndexedTree {
* @param - - `frequency`: The default frequency value. It is optional and has a default
* value of 0.
*/
constructor({frequency = 0, max}: {frequency?: number; max: number}) {
constructor({frequency = 0, max}: { frequency?: number; max: number }) {
this._freq = frequency;
this._max = max;
this._freqMap = {0: 0};

View file

@ -6,7 +6,7 @@
* @license MIT License
*/
import type {OneParamCallback, BinaryTreeNodeKey, BinaryTreeNodeNested, BinaryTreeOptions} from '../../types';
import type {BinaryTreeNodeKey, BinaryTreeNodeNested, BinaryTreeOptions, OneParamCallback} from '../../types';
import {BinaryTreeDeletedResult, DFSOrderPattern, FamilyPosition, IterationType} from '../../types';
import {IBinaryTree} from '../../interfaces';
import {trampoline} from '../../utils';
@ -108,8 +108,7 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
* @template N - The type of the binary tree's nodes.
*/
export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>>
implements IBinaryTree<V, N>
{
implements IBinaryTree<V, N> {
/**
* Creates a new instance of BinaryTree.
* @param {BinaryTreeOptions} [options] - The options for the binary tree.
@ -395,7 +394,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
return -1;
}
const stack: {node: N; depth: number}[] = [{node: beginRoot, depth: 0}];
const stack: { node: N; depth: number }[] = [{node: beginRoot, depth: 0}];
let maxHeight = 0;
while (stack.length > 0) {
@ -832,7 +831,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
_traverse(beginRoot);
} else {
// 0: visit, 1: print
const stack: {opt: 0 | 1; node: N | null | undefined}[] = [{opt: 0, node: beginRoot}];
const stack: { opt: 0 | 1; node: N | null | undefined }[] = [{opt: 0, node: beginRoot}];
while (stack.length > 0) {
const cur = stack.pop();
@ -1093,6 +1092,49 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
return ans;
}
/**
* The above function is an iterator for a binary tree that can be used to traverse the tree in
* either an iterative or recursive manner.
* @param node - The `node` parameter represents the current node in the binary tree from which the
* iteration starts. It is an optional parameter with a default value of `this.root`, which means
* that if no node is provided, the iteration will start from the root of the binary tree.
* @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the
* binary tree nodes in a specific order.
*/
* [Symbol.iterator](node = this.root): Generator<BinaryTreeNodeKey, void, undefined> {
if (!node) {
return;
}
if (this.iterationType === IterationType.ITERATIVE) {
const stack: (N | null | undefined)[] = [];
let current: N | null | undefined = node;
while (current || stack.length > 0) {
while (current) {
stack.push(current);
current = current.left;
}
current = stack.pop();
if (current) yield current.key;
if (current) current = current.right;
}
} else {
if (node.left) {
yield* this[Symbol.iterator](node.left);
}
yield node.key;
if (node.right) {
yield* this[Symbol.iterator](node.right);
}
}
}
/**
* Swap the data of two nodes in the binary tree.
* @param {N} srcNode - The source node to swap.

View file

@ -19,8 +19,7 @@ export class BSTNode<V = any, N extends BSTNode<V, N> = BSTNodeNested<V>> extend
export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>>
extends BinaryTree<V, N>
implements IBinaryTree<V, N>
{
implements IBinaryTree<V, N> {
/**
* The constructor function initializes a binary search tree object with an optional comparator
* function.

View file

@ -21,8 +21,7 @@ export class RBTreeNode<V = any, N extends RBTreeNode<V, N> = RBTreeNodeNested<V
export class RBTree<V, N extends RBTreeNode<V, N> = RBTreeNode<V, RBTreeNodeNested<V>>>
extends BST<V, N>
implements IBinaryTree<V, N>
{
implements IBinaryTree<V, N> {
constructor(options?: RBTreeOptions) {
super(options);
}

View file

@ -37,8 +37,7 @@ export class TreeMultisetNode<
*/
export class TreeMultiset<V = any, N extends TreeMultisetNode<V, N> = TreeMultisetNode<V, TreeMultisetNodeNested<V>>>
extends AVLTree<V, N>
implements IBinaryTree<V, N>
{
implements IBinaryTree<V, N> {
/**
* The constructor function for a TreeMultiset class in TypeScript, which extends another class and sets an option to
* merge duplicated values.

View file

@ -105,8 +105,7 @@ export abstract class AbstractEdge<V = any> {
export abstract class AbstractGraph<
V extends AbstractVertex<any> = AbstractVertex<any>,
E extends AbstractEdge<any> = AbstractEdge<any>
> implements IGraph<V, E>
{
> implements IGraph<V, E> {
private _vertices: Map<VertexKey, V> = new Map<VertexKey, V>();
get vertices(): Map<VertexKey, V> {
@ -554,14 +553,14 @@ export abstract class AbstractGraph<
}
getMinDist &&
distMap.forEach((d, v) => {
if (v !== srcVertex) {
if (d < minDist) {
minDist = d;
if (genPaths) minDest = v;
}
distMap.forEach((d, v) => {
if (v !== srcVertex) {
if (d < minDist) {
minDist = d;
if (genPaths) minDest = v;
}
});
}
});
genPaths && getPaths(minDest);
@ -623,7 +622,7 @@ export abstract class AbstractGraph<
if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Infinity);
}
const heap = new PriorityQueue<{key: number; val: V}>({comparator: (a, b) => a.key - b.key});
const heap = new PriorityQueue<{ key: number; val: V }>({comparator: (a, b) => a.key - b.key});
heap.add({key: 0, val: srcVertex});
distMap.set(srcVertex, 0);
@ -852,7 +851,7 @@ export abstract class AbstractGraph<
* `predecessor` property is a 2D array of vertices (or `null`) representing the predecessor vertices in the shortest
* path between vertices in the
*/
floyd(): {costs: number[][]; predecessor: (V | null)[][]} {
floyd(): { costs: number[][]; predecessor: (V | null)[][] } {
const idAndVertices = [...this._vertices];
const n = idAndVertices.length;

View file

@ -64,8 +64,7 @@ export class DirectedEdge<V = any> extends AbstractEdge<V> {
export class DirectedGraph<V extends DirectedVertex<any> = DirectedVertex, E extends DirectedEdge<any> = DirectedEdge>
extends AbstractGraph<V, E>
implements IGraph<V, E>
{
implements IGraph<V, E> {
/**
* The constructor function initializes an instance of a class.
*/

View file

@ -51,12 +51,11 @@ export class UndirectedEdge<V = number> extends AbstractEdge<V> {
}
export class UndirectedGraph<
V extends UndirectedVertex<any> = UndirectedVertex,
E extends UndirectedEdge<any> = UndirectedEdge
>
V extends UndirectedVertex<any> = UndirectedVertex,
E extends UndirectedEdge<any> = UndirectedEdge
>
extends AbstractGraph<V, E>
implements IGraph<V, E>
{
implements IGraph<V, E> {
/**
* The constructor initializes a new Map object to store edges.
*/

View file

@ -157,7 +157,7 @@ export class HashMap<K, V> {
}
}
*entries(): IterableIterator<[K, V]> {
* entries(): IterableIterator<[K, V]> {
for (const bucket of this.table) {
if (bucket) {
for (const [key, value] of bucket) {

View file

@ -1 +1,2 @@
export class TreeMap {}
export class TreeMap {
}

View file

@ -1 +1,2 @@
export class TreeSet {}
export class TreeSet {
}

View file

@ -11,7 +11,7 @@ export class Heap<E = any> {
protected nodes: E[] = [];
protected readonly comparator: Comparator<E>;
constructor(options: {comparator: Comparator<E>; nodes?: E[]}) {
constructor(options: { comparator: Comparator<E>; nodes?: E[] }) {
this.comparator = options.comparator;
if (options.nodes && options.nodes.length > 0) {
this.nodes = options.nodes;
@ -39,7 +39,7 @@ export class Heap<E = any> {
* @returns A new Heap instance.
* @param options
*/
static heapify<E>(options: {nodes: E[]; comparator: Comparator<E>}): Heap<E> {
static heapify<E>(options: { nodes: E[]; comparator: Comparator<E> }): Heap<E> {
return new Heap<E>(options);
}

View file

@ -11,7 +11,7 @@ import type {Comparator} from '../../types';
export class MaxHeap<E = any> extends Heap<E> {
constructor(
options: {comparator: Comparator<E>; nodes?: E[]} = {
options: { comparator: Comparator<E>; nodes?: E[] } = {
comparator: (a: E, b: E) => {
if (!(typeof a === 'number' && typeof b === 'number')) {
throw new Error('The a, b params of compare function must be number');

View file

@ -11,7 +11,7 @@ import type {Comparator} from '../../types';
export class MinHeap<E = any> extends Heap<E> {
constructor(
options: {comparator: Comparator<E>; nodes?: E[]} = {
options: { comparator: Comparator<E>; nodes?: E[] } = {
comparator: (a: E, b: E) => {
if (!(typeof a === 'number' && typeof b === 'number')) {
throw new Error('The a, b params of compare function must be number');

View file

@ -625,6 +625,9 @@ export class DoublyLinkedList<E = any> {
return false;
}
/**
* The function returns an iterator that iterates over the values of a linked list.
*/
* [Symbol.iterator]() {
let current = this.head;

View file

@ -587,6 +587,9 @@ export class SinglyLinkedList<E = any> {
return accumulator;
}
/**
* The function returns an iterator that iterates over the values of a linked list.
*/
* [Symbol.iterator]() {
let current = this.head;

View file

@ -14,7 +14,7 @@ export class MatrixNTI2D<V = any> {
* given initial value or 0 if not provided.
* @param options - An object containing the following properties:
*/
constructor(options: {row: number; col: number; initialVal?: V}) {
constructor(options: { row: number; col: number; initialVal?: V }) {
const {row, col, initialVal} = options;
this._matrix = new Array(row).fill(undefined).map(() => new Array(col).fill(initialVal || 0));
}

View file

@ -10,7 +10,8 @@ export class Vector2D {
public x: number = 0,
public y: number = 0,
public w: number = 1 // needed for matrix multiplication
) {}
) {
}
/**
* The function checks if the x and y values of a point are both zero.

View file

@ -10,7 +10,7 @@ import type {Comparator} from '../../types';
export class MaxPriorityQueue<E = any> extends PriorityQueue<E> {
constructor(
options: {comparator: Comparator<E>; nodes?: E[]} = {
options: { comparator: Comparator<E>; nodes?: E[] } = {
comparator: (a: E, b: E) => {
if (!(typeof a === 'number' && typeof b === 'number')) {
throw new Error('The a, b params of compare function must be number');

View file

@ -10,7 +10,7 @@ import type {Comparator} from '../../types';
export class MinPriorityQueue<E = any> extends PriorityQueue<E> {
constructor(
options: {comparator: Comparator<E>; nodes?: E[]} = {
options: { comparator: Comparator<E>; nodes?: E[] } = {
comparator: (a: E, b: E) => {
if (!(typeof a === 'number' && typeof b === 'number')) {
throw new Error('The a, b params of compare function must be number');

View file

@ -10,7 +10,7 @@ import {Heap} from '../heap';
import {Comparator} from '../../types';
export class PriorityQueue<E = any> extends Heap<E> {
constructor(options: {comparator: Comparator<E>; nodes?: E[]}) {
constructor(options: { comparator: Comparator<E>; nodes?: E[] }) {
super(options);
}
}

View file

@ -9,7 +9,8 @@ import {DoublyLinkedList} from '../linked-list';
// O(n) time complexity of obtaining the value
// O(1) time complexity of adding at the beginning and the end
export class Deque<E = any> extends DoublyLinkedList<E> {}
export class Deque<E = any> extends DoublyLinkedList<E> {
}
// O(1) time complexity of obtaining the value
// O(n) time complexity of adding at the beginning and the end
@ -19,9 +20,9 @@ export class ObjectDeque<E = number> {
if (capacity !== undefined) this._capacity = capacity;
}
private _nodes: {[key: number]: E} = {};
private _nodes: { [key: number]: E } = {};
get nodes(): {[p: number]: E} {
get nodes(): { [p: number]: E } {
return this._nodes;
}
@ -156,7 +157,7 @@ export class ObjectDeque<E = number> {
return this._size <= 0;
}
protected _seNodes(value: {[p: number]: E}) {
protected _seNodes(value: { [p: number]: E }) {
this._nodes = value;
}

View file

@ -183,7 +183,7 @@ export class Queue<E = any> {
return new Queue(this.nodes.slice(this.offset));
}
*[Symbol.iterator]() {
* [Symbol.iterator]() {
for (const item of this.nodes) {
yield item;
}

View file

@ -1,6 +1,6 @@
export type Direction = 'up' | 'right' | 'down' | 'left';
export type Turning = {[key in Direction]: Direction};
export type Turning = { [key in Direction]: Direction };
export type NavigatorParams<T = any> = {
matrix: T[][];

View file

@ -1,5 +1,5 @@
export type ToThunkFn = () => ReturnType<TrlFn>;
export type Thunk = () => ReturnType<ToThunkFn> & {__THUNK__: symbol};
export type Thunk = () => ReturnType<ToThunkFn> & { __THUNK__: symbol };
export type TrlFn = (...args: any[]) => any;
export type TrlAsyncFn = (...args: any[]) => any;

View file

@ -1,6 +1,6 @@
export type KeyValueObject = {[key: string]: any};
export type KeyValueObject = { [key: string]: any };
export type KeyValueObjectWithKey = {[key: string]: any; key: string | number | symbol};
export type KeyValueObjectWithKey = { [key: string]: any; key: string | number | symbol };
export type NonNumberNonObjectButDefined = string | boolean | symbol | null;

View file

@ -183,7 +183,7 @@ describe('Individual package BST operations test', () => {
});
it('should perform various operations on a Binary Search Tree with object values', () => {
const objBST = new BST<{key: number; keyA: number}>();
const objBST = new BST<{ key: number; keyA: number }>();
expect(objBST).toBeInstanceOf(BST);
objBST.add(11, {key: 11, keyA: 11});
objBST.add(3, {key: 3, keyA: 3});

View file

@ -219,7 +219,7 @@ describe('AVL Tree Test recursively', () => {
});
describe('AVLTree APIs test', () => {
const avl = new AVLTree<{id: number; text: string}>();
const avl = new AVLTree<{ id: number; text: string }>();
beforeEach(() => {
avl.clear();
});

View file

@ -125,11 +125,19 @@ describe('BinaryTree', () => {
});
it('should traverse in-order', () => {
tree.add(null);
tree.delete(1);
expect(tree.getHeight()).toBe(-1);
tree.add(4);
tree.add(2);
expect(tree.getHeight()).toBe(1);
tree.iterationType = IterationType.RECURSIVE;
expect(tree.getHeight()).toBe(1);
tree.iterationType = IterationType.ITERATIVE;
tree.add(6);
tree.add(1);
tree.add(3);
tree.add(new BinaryTreeNode(3));
tree.add(5);
tree.add(7);
@ -160,6 +168,7 @@ describe('BinaryTree', () => {
]);
expect(tree.isSubtreeBST(tree.get(4), IterationType.RECURSIVE)).toBe(true);
expect(tree.isSubtreeBST(tree.get(4), IterationType.ITERATIVE)).toBe(true);
});
it('should subTreeTraverse', () => {
@ -197,6 +206,7 @@ describe('BinaryTree Morris Traversal', () => {
expect(result).toEqual(expected);
expect(tree.dfs(node => node.key, 'in')).toEqual(expected);
expect(tree.dfs(node => node.key, 'in', tree.root, IterationType.RECURSIVE)).toEqual(expected);
});
it('should perform pre-order Morris traversal correctly as dfs traversal', () => {
@ -231,7 +241,7 @@ describe('BinaryTree Morris Traversal', () => {
});
describe('BinaryTree APIs test', () => {
const avl = new AVLTree<{id: number; text: string}>();
const avl = new AVLTree<{ id: number; text: string }>();
beforeEach(() => {
avl.clear();
});
@ -255,8 +265,10 @@ describe('BinaryTree traversals', () => {
const arr = [35, 20, 40, 15, 29, null, 50, null, 16, 28, 30, 45, 55];
tree.refill(arr);
expect(tree.dfs(node => node.key, 'pre')).toEqual([35, 20, 15, 16, 29, 28, 30, 40, 50, 45, 55]);
expect(tree.dfs(node => node.key, 'pre', tree.root, IterationType.RECURSIVE)).toEqual([35, 20, 15, 16, 29, 28, 30, 40, 50, 45, 55]);
expect(tree.dfs(node => node.key, 'in')).toEqual([15, 16, 20, 28, 29, 30, 35, 40, 45, 50, 55]);
expect(tree.dfs(node => node.key, 'post')).toEqual([16, 15, 28, 30, 29, 20, 45, 55, 50, 40, 35]);
expect(tree.dfs(node => node.key, 'post', tree.root, IterationType.RECURSIVE)).toEqual([16, 15, 28, 30, 29, 20, 45, 55, 50, 40, 35]);
expect(tree.bfs(node => node.key, tree.root, IterationType.RECURSIVE)).toEqual([
35, 20, 40, 15, 29, 50, 16, 28, 30, 45, 55
]);
@ -281,7 +293,7 @@ describe('BinaryTree', () => {
let tree: BinaryTree<string>;
beforeEach(() => {
tree = new BinaryTree<string>();
tree = new BinaryTree<string>({iterationType: IterationType.RECURSIVE});
});
afterEach(() => {
@ -441,6 +453,14 @@ describe('BinaryTree', () => {
tree.add(3, 'B');
tree.add(7, 'C');
tree.iterationType = IterationType.ITERATIVE;
// @ts-ignore
expect([...tree]).toEqual([3, 5, 7]);
tree.iterationType = IterationType.RECURSIVE;
// @ts-ignore
expect([...tree]).toEqual([3, 5, 7]);
tree.iterationType = IterationType.ITERATIVE;
const result = tree.morris();
expect(result).toEqual([3, 5, 7]);
// Add assertions for the result of Morris traversal

View file

@ -189,7 +189,7 @@ describe('BST operations test', () => {
});
it('should perform various operations on a Binary Search Tree with object values', () => {
const objBST = new BST<{key: number; keyA: number}>();
const objBST = new BST<{ key: number; keyA: number }>();
expect(objBST).toBeInstanceOf(BST);
objBST.add(11, {key: 11, keyA: 11});
objBST.add(3, {key: 3, keyA: 3});
@ -260,7 +260,7 @@ describe('BST operations test', () => {
objBST.perfectlyBalance();
expect(objBST.isPerfectlyBalanced()).toBe(true);
const bfsNodesAfterBalanced: BSTNode<{key: number; keyA: number}>[] = [];
const bfsNodesAfterBalanced: BSTNode<{ key: number; keyA: number }>[] = [];
objBST.bfs(node => bfsNodesAfterBalanced.push(node));
expect(bfsNodesAfterBalanced[0].key).toBe(8);
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
@ -385,7 +385,7 @@ describe('BST operations test', () => {
expect(bfsIDs[1]).toBe(12);
expect(bfsIDs[2]).toBe(16);
const bfsNodes: BSTNode<{key: number; keyA: number}>[] = [];
const bfsNodes: BSTNode<{ key: number; keyA: number }>[] = [];
objBST.bfs(node => bfsNodes.push(node));
expect(bfsNodes[0].key).toBe(2);
expect(bfsNodes[1].key).toBe(12);
@ -579,7 +579,7 @@ describe('BST operations test recursively', () => {
});
it('should perform various operations on a Binary Search Tree with object values', () => {
const objBST = new BST<{key: number; keyA: number}>();
const objBST = new BST<{ key: number; keyA: number }>();
expect(objBST).toBeInstanceOf(BST);
objBST.add(11, {key: 11, keyA: 11});
objBST.add(3, {key: 3, keyA: 3});
@ -650,7 +650,7 @@ describe('BST operations test recursively', () => {
objBST.perfectlyBalance();
expect(objBST.isPerfectlyBalanced()).toBe(true);
const bfsNodesAfterBalanced: BSTNode<{key: number; keyA: number}>[] = [];
const bfsNodesAfterBalanced: BSTNode<{ key: number; keyA: number }>[] = [];
objBST.bfs(node => bfsNodesAfterBalanced.push(node));
expect(bfsNodesAfterBalanced[0].key).toBe(8);
expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].key).toBe(16);
@ -775,7 +775,7 @@ describe('BST operations test recursively', () => {
expect(bfsIDs[1]).toBe(12);
expect(bfsIDs[2]).toBe(16);
const bfsNodes: BSTNode<{key: number; keyA: number}>[] = [];
const bfsNodes: BSTNode<{ key: number; keyA: number }>[] = [];
objBST.bfs(node => bfsNodes.push(node));
expect(bfsNodes[0].key).toBe(2);
expect(bfsNodes[1].key).toBe(12);

View file

@ -29,7 +29,7 @@ describe('Overall BinaryTree Test', () => {
bfsIDs[0] === 11; // true
expect(bfsIDs[0]).toBe(11);
const objBST = new BST<{key: number; keyA: number}>();
const objBST = new BST<{ key: number; keyA: number }>();
objBST.add(11, {key: 11, keyA: 11});
objBST.add(3, {key: 3, keyA: 3});

View file

@ -207,7 +207,7 @@ describe('TreeMultiset operations test', () => {
});
it('should perform various operations on a Binary Search Tree with object values', () => {
const objTreeMultiset = new TreeMultiset<{key: number; keyA: number}>();
const objTreeMultiset = new TreeMultiset<{ key: number; keyA: number }>();
expect(objTreeMultiset).toBeInstanceOf(TreeMultiset);
objTreeMultiset.add(11, {key: 11, keyA: 11});
objTreeMultiset.add(3, {key: 3, keyA: 3});
@ -447,7 +447,7 @@ describe('TreeMultiset operations test recursively', () => {
});
it('should perform various operations on a Binary Search Tree with object values', () => {
const objTreeMultiset = new TreeMultiset<{key: number; keyA: number}>();
const objTreeMultiset = new TreeMultiset<{ key: number; keyA: number }>();
expect(objTreeMultiset).toBeInstanceOf(TreeMultiset);
objTreeMultiset.add(11, {key: 11, keyA: 11});
objTreeMultiset.add(3, {key: 3, keyA: 3});

View file

@ -52,3 +52,23 @@ describe('CoordinateMap', () => {
expect(retrievedValue).toBe(value);
});
});
describe('CoordinateMap', () => {
class MyCoordinateMap<V = any> extends CoordinateMap<V> {
constructor(joint?: string) {
super(joint);
this._setJoint(joint += '-')
}
}
const cMap = new MyCoordinateMap<number>('*');
beforeEach(() => {
cMap.set([0, 0], 0);
cMap.set([0, 1], 1);
cMap.set([1, 1], 11);
})
it('should joint to be *-', () => {
expect(cMap.joint).toBe('*-');
});
});

View file

@ -39,3 +39,28 @@ describe('CoordinateSet', () => {
expect(hasValue).toBe(true);
});
});
describe('MyCoordinateSet', () => {
class MyCoordinateSet extends CoordinateSet {
constructor(joint?: string) {
super(joint);
this._setJoint(joint += '-')
}
}
const mySet = new MyCoordinateSet('*');
beforeEach(() => {
mySet.add([0, 0]);
mySet.add([0, 1]);
mySet.add([1, 1]);
})
it('should joint to be *-', () => {
expect(mySet.joint).toBe('*-');
});
it('should has, delete', () => {
mySet.delete([0, 1]);
expect(mySet.has([0, 1])).toBe(false);
});
});

View file

@ -15,7 +15,9 @@ describe('HashNode', () => {
describe('HashTable', () => {
it('should initialize with default capacity', () => {
const hashTable = new HashTable<string, string>();
hashTable.capacity = hashTable.capacity;
hashTable.buckets = hashTable.buckets;
hashTable.hashFn = hashTable.hashFn;
expect(hashTable.capacity).toBe(16);
expect(hashTable.size).toBe(0);
expect(hashTable.buckets.length).toBe(16);

View file

@ -22,7 +22,7 @@ describe('Heap Operation Test', () => {
});
it('should object heap work well', function () {
const minHeap = new MinHeap<{a: string; key: number}>({comparator: (a, b) => a.key - b.key});
const minHeap = new MinHeap<{ a: string; key: number }>({comparator: (a, b) => a.key - b.key});
minHeap.add({key: 1, a: 'a1'});
minHeap.add({key: 6, a: 'a6'});
minHeap.add({key: 2, a: 'a2'});
@ -37,7 +37,7 @@ describe('Heap Operation Test', () => {
i++;
}
const maxHeap = new MaxHeap<{key: number; a: string}>({comparator: (a, b) => b.key - a.key});
const maxHeap = new MaxHeap<{ key: number; a: string }>({comparator: (a, b) => b.key - a.key});
maxHeap.add({key: 1, a: 'a1'});
maxHeap.add({key: 6, a: 'a6'});
maxHeap.add({key: 5, a: 'a5'});

View file

@ -1,9 +1,72 @@
import {DoublyLinkedList} from '../../../../src';
import {DoublyLinkedList, DoublyLinkedListNode} from '../../../../src';
import {bigO, magnitude} from '../../../utils';
describe('DoublyLinkedListNode', () => {
it('should DoublyLinkedListNode', () => {
const node1 = new DoublyLinkedListNode<number>(2);
expect(node1.val).toBe(2);
node1.val = 1;
expect(node1.val).toBe(1);
})
});
describe('DoublyLinkedList Operation Test', () => {
let list: DoublyLinkedList<number>;
let objectList: DoublyLinkedList<{keyA: number}>;
beforeEach(() => {
list = DoublyLinkedList.fromArray([1, 2, 3, 4, 5]);
});
it('should out of bound index', () => {
expect(list.getNodeAt(-1)).toBe(null);
expect(list.getNodeAt(5)).toBe(null);
expect(list.insertAt(5, 6)).toBe(true);
});
it('should insertBefore', () => {
expect(list.insertBefore(1, 0)).toBe(true);
});
it('should deleteAt', () => {
expect(list.deleteAt(1)).toBeTruthy();
});
it('should delete tail', () => {
expect(list.delete(list.tail)).toBe(true);
expect(list.tail?.val).toBe(4);
expect(list.delete(6)).toBe(false);
expect(list.tail?.val).toBe(4);
});
it('should find null', () => {
expect(list.find(val => val === 6)).toBe(null);
});
it('should indexOf -1', () => {
expect(list.indexOf(6)).toBe(-1);
});
it('should findBackward null', () => {
expect(list.findBackward(val => val === 0)).toBe(null);
});
it('should insertAfter tail', () => {
expect(list.insertAfter(list.tail!, 6)).toBe(true);
});
it('should insertAfter tail', () => {
// @ts-ignore
expect([...list]).toEqual([1, 2, 3, 4, 5]);
});
});
describe('DoublyLinkedList Operation Test', () => {
let list: DoublyLinkedList<number>;
let objectList: DoublyLinkedList<{ keyA: number }>;
beforeEach(() => {
list = new DoublyLinkedList();

View file

@ -1,12 +1,21 @@
import {SinglyLinkedList} from '../../../../src';
import {SinglyLinkedList, SinglyLinkedListNode} from '../../../../src';
import {bigO, magnitude} from '../../../utils';
describe('SinglyLinkedListNode', () => {
it('should SinglyLinkedList', () => {
const node1 = new SinglyLinkedListNode<number>(2);
expect(node1.val).toBe(2);
node1.val = 1;
expect(node1.val).toBe(1);
})
});
describe('SinglyLinkedList Operation Test', () => {
let list: SinglyLinkedList<number>;
let objectList: SinglyLinkedList<{keyA: number}>;
let objectList: SinglyLinkedList<{ keyA: number }>;
beforeEach(() => {
list = new SinglyLinkedList<number>();
objectList = new SinglyLinkedList<{keyA: number}>();
objectList = new SinglyLinkedList<{ keyA: number }>();
});
describe('push', () => {
@ -21,8 +30,10 @@ describe('SinglyLinkedList Operation Test', () => {
it('should delete and return the last element of the list', () => {
list.push(1);
list.push(2);
list.push(3);
const popped = list.pop();
expect(popped).toBe(2);
expect(popped).toBe(3);
expect(list.popLast()).toBe(2);
expect(list.toArray()).toEqual([1]);
});
@ -36,9 +47,11 @@ describe('SinglyLinkedList Operation Test', () => {
it('should delete and return the first element of the list', () => {
list.push(1);
list.push(2);
list.push(3);
const shifted = list.shift();
expect(shifted).toBe(1);
expect(list.toArray()).toEqual([2]);
expect(list.popFirst()).toBe(2);
expect(list.toArray()).toEqual([3]);
});
it('should return undefined if the list is empty', () => {
@ -50,7 +63,7 @@ describe('SinglyLinkedList Operation Test', () => {
describe('unshift', () => {
it('should add elements to the beginning of the list', () => {
list.unshift(1);
list.unshift(2);
list.addFirst(2);
expect(list.toArray()).toEqual([2, 1]);
});
});
@ -62,6 +75,7 @@ describe('SinglyLinkedList Operation Test', () => {
list.push(3);
const element = list.getAt(1);
expect(element).toBe(2);
expect(list.getNodeAt(2)?.val).toBe(3);
});
it('should return undefined for an out-of-bounds index', () => {
@ -113,9 +127,14 @@ describe('SinglyLinkedList Operation Test', () => {
list.push(1);
list.push(2);
list.push(3);
const removed = list.delete(2);
expect(removed).toBe(true);
expect(list.toArray()).toEqual([1, 3]);
list.push(4);
list.push(5);
expect(list.delete(2)).toBe(true);
expect(list.toArray()).toEqual([1, 3, 4, 5]);
expect(list.delete(1)).toBe(true);
expect(list.toArray()).toEqual([3, 4, 5]);
expect(list.delete(5)).toBe(true);
expect(list.toArray()).toEqual([3, 4]);
});
it('should return false if the value is not found', () => {
@ -427,7 +446,6 @@ describe('SinglyLinkedList', () => {
expect(list.length).toBe(1);
});
// Add more test cases for other methods like shift, unshift, getAt, deleteAt, and more.
it('should reverse the list', () => {
list.push(1);
@ -439,7 +457,6 @@ describe('SinglyLinkedList', () => {
// Add more assertions for reversed order.
});
// Add more test cases for other methods like find, indexOf, and more.
it('should convert the list to an array', () => {
list.push(1);
@ -447,5 +464,35 @@ describe('SinglyLinkedList', () => {
list.push(3);
const array = list.toArray();
expect(array).toEqual([1, 2, 3]);
// @ts-ignore
expect([...list]).toEqual([1, 2, 3]);
});
it('should filter the list', () => {
list.push(1);
list.push(2);
list.push(3);
expect(list.filter(val => val !== 2).toArray()).toEqual([1, 3]);
});
it('should forEach the list', () => {
list.push(1);
list.push(2);
list.push(3);
list.forEach(val => val++);
expect(list.toArray()).toEqual([1, 2, 3])
});
it('should map the list', () => {
list.addLast(1);
list.push(2);
list.push(3);
expect(list.map(val => val * 2).toArray()).toEqual([2, 4, 6]);
});
it('should reduce the list', () => {
const list1 = SinglyLinkedList.fromArray([1, 2, 3]);
expect(list1.reduce((acc, val) => acc + val, 0)).toEqual(6);
});
});

View file

@ -17,7 +17,7 @@ describe('MaxPriorityQueue Operation Test', () => {
});
it('should add elements and maintain heap property in a object MaxPriorityQueue', () => {
const priorityQueue = new MaxPriorityQueue<{keyA: number}>({comparator: (a, b) => b.keyA - a.keyA});
const priorityQueue = new MaxPriorityQueue<{ keyA: number }>({comparator: (a, b) => b.keyA - a.keyA});
priorityQueue.refill([{keyA: 5}, {keyA: 3}, {keyA: 1}]);
priorityQueue.add({keyA: 7});
@ -64,7 +64,7 @@ describe('MaxPriorityQueue Operation Test', () => {
it('should correctly heapify an object array', () => {
const nodes = [{keyA: 5}, {keyA: 3}, {keyA: 7}, {keyA: 1}];
const maxPQ = MaxPriorityQueue.heapify<{keyA: number}>({nodes: nodes, comparator: (a, b) => b.keyA - a.keyA});
const maxPQ = MaxPriorityQueue.heapify<{ keyA: number }>({nodes: nodes, comparator: (a, b) => b.keyA - a.keyA});
expect(maxPQ.poll()?.keyA).toBe(7);
expect(maxPQ.poll()?.keyA).toBe(5);

View file

@ -26,7 +26,7 @@ export const bigO = {
function findPotentialN(input: any): number {
let longestArray: any[] = [];
let mostProperties: {[key: string]: any} = {};
let mostProperties: { [key: string]: any } = {};
function recurse(obj: any) {
if (Array.isArray(obj)) {

View file

@ -1,28 +0,0 @@
const path = require('path');
module.exports = [
{
mode:'production',
entry: './src/index.ts',
target: 'web',
output: {
filename: 'bundle.min.js',
path: path.resolve(__dirname, 'umd'),
library: 'dataStructureTyped',
libraryTarget: 'umd',
},
resolve: {
extensions: ['.ts', '.js'],
},
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/,
}
],
},
devtool: 'source-map',
},
];