update Typescript version to 4.9.5, DirectedGraph tests completed, Remedial measures have been taken in TypeScript versions 5.0 and above to enforce consistent access modifiers for getters and setters., annotation content has been enriched.

This commit is contained in:
Revone 2023-08-16 22:44:38 +08:00
parent 9fac28cf35
commit 2d07c5e5af
18 changed files with 3111 additions and 1156 deletions

457
README.md
View file

@ -15,15 +15,28 @@ yarn add data-structure-typed
```bash
npm install data-structure-typed
```
## Online examples
[Online Examples](https://data-structure-typed-examples.vercel.app)
## Live Examples
[Live Examples](https://data-structure-typed-examples.vercel.app)
<a href="https://data-structure-typed-examples.vercel.app" target="_blank">Live Examples</a>
## Examples Repository
[Example Repository](https://github.com/zrwusa/data-structure-typed-examples)
[Examples Repository](https://github.com/zrwusa/data-structure-typed-examples)
## api docs
<a href="https://github.com/zrwusa/data-structure-typed-examples" target="_blank">Examples Repository</a>
## Data Structures
Meticulously crafted to empower developers with a versatile set of essential data structures. Our library includes a
wide range of data structures:
Binary Tree, Binary Search Tree (BST), AVL Tree, Tree Multiset, Segment Tree, Binary Indexed Tree, Graph, Directed
Graph, Undirected Graph, Linked List, Singly Linked List, Doubly Linked List, Queue, Object Deque, Array Deque, Stack,
Hash, Coordinate Set, Coordinate Map, Heap, Priority Queue, Max Priority Queue, Min Priority Queue, Trie
## API docs
[//]: # ([api docs]&#40;https://data-structure-typed-docs.vercel.app/&#41;)
@ -37,14 +50,16 @@ npm install data-structure-typed
[//]: # (<li><a href="https://data-structure-typed-docs.vercel.app/enums/LoopType.html"><span>Loop<wbr/>Type</span></a></li>)
<li><a href="https://data-structure-typed-docs.vercel.app/classes/AVLTree.html"><span>AVLTree</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/AVLTreeNode.html"><span>AVLTree<wbr/>Node</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/AaTree.html"><span>Aa<wbr/>Tree</span></a></li>
[//]: # (<li><a href="https://data-structure-typed-docs.vercel.app/classes/AaTree.html"><span>Aa<wbr/>Tree</span></a></li>)
<li><a href="https://data-structure-typed-docs.vercel.app/classes/AbstractEdge.html"><span>Abstract<wbr/>Edge</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/AbstractGraph.html"><span>Abstract<wbr/>Graph</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/AbstractVertex.html"><span>Abstract<wbr/>Vertex</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/ArrayDeque.html"><span>Array<wbr/>Deque</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/BST.html"><span>BST</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/BSTNode.html"><span>BSTNode</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/BTree.html"><span>BTree</span></a></li>
[//]: # (<li><a href="https://data-structure-typed-docs.vercel.app/classes/BTree.html"><span>BTree</span></a></li>)
<li><a href="https://data-structure-typed-docs.vercel.app/classes/BinaryIndexedTree.html"><span>Binary<wbr/>Indexed<wbr/>Tree</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/BinaryTree.html"><span>Binary<wbr/>Tree</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/BinaryTreeNode.html"><span>Binary<wbr/>Tree<wbr/>Node</span></a></li>
@ -68,200 +83,287 @@ npm install data-structure-typed
<li><a href="https://data-structure-typed-docs.vercel.app/classes/ObjectDeque.html"><span>Object<wbr/>Deque</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/PriorityQueue.html"><span>Priority<wbr/>Queue</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/Queue.html"><span>Queue</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/RBTree.html"><span>RBTree</span></a></li>
[//]: # (<li><a href="https://data-structure-typed-docs.vercel.app/classes/RBTree.html"><span>RBTree</span></a></li>)
<li><a href="https://data-structure-typed-docs.vercel.app/classes/SegmentTree.html"><span>Segment<wbr/>Tree</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/SegmentTreeNode.html"><span>Segment<wbr/>Tree<wbr/>Node</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/SinglyLinkedList.html"><span>Singly<wbr/>Linked<wbr/>List</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/SinglyLinkedListNode.html"><span>Singly<wbr/>Linked<wbr/>List<wbr/>Node</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/SplayTree.html"><span>Splay<wbr/>Tree</span></a></li>
[//]: # (<li><a href="https://data-structure-typed-docs.vercel.app/classes/SplayTree.html"><span>Splay<wbr/>Tree</span></a></li>)
<li><a href="https://data-structure-typed-docs.vercel.app/classes/Stack.html"><span>Stack</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/TreeMultiSet.html"><span>Tree<wbr/>Multi<wbr/>Set</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/Trie.html"><span>Trie</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/TrieNode.html"><span>Trie<wbr/>Node</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/TwoThreeTree.html"><span>Two<wbr/>Three<wbr/>Tree</span></a></li>
[//]: # (<li><a href="https://data-structure-typed-docs.vercel.app/classes/TwoThreeTree.html"><span>Two<wbr/>Three<wbr/>Tree</span></a></li>)
<li><a href="https://data-structure-typed-docs.vercel.app/classes/UndirectedEdge.html"><span>Undirected<wbr/>Edge</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/UndirectedGraph.html"><span>Undirected<wbr/>Graph</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/UndirectedVertex.html"><span>Undirected<wbr/>Vertex</span></a></li>
<li><a href="https://data-structure-typed-docs.vercel.app/classes/Vector2D.html"><span>Vector2D</span></a></li></ul></nav>
## data structures
## Complexities
### performance of Big O
Meticulously crafted to empower developers with a versatile set of essential data structures. Our library includes a wide range of data structures:
Binary Tree, Binary Search Tree (BST), AVL Tree, Tree Multiset, Segment Tree, Binary Indexed Tree, Graph, Directed Graph, Undirected Graph, Linked List, Singly Linked List, Doubly Linked List, Queue, Object Deque, Array Deque, Stack, Hash, Coordinate Set, Coordinate Map, Heap, Priority Queue, Max Priority Queue, Min Priority Queue, Trie
<table>
<thead>
<tr>
<th>Data Structure</th>
<th>Derived</th>
<th>Basic Features</th>
<th>Additional Features</th>
</tr>
<tr>
<th>Big O Notation</th>
<th>Type</th>
<th>Computations for 10 elements</th>
<th>Computations for 100 elements</th>
<th>Computations for 1000 elements</th>
</tr>
</thead>
<tbody>
<tr>
<td>Binary Tree</td>
<td>AVL Tree, Binary Search Tree, Tree Multiset</td>
<td>put, has, get, remove, size, insertTo, insertMany, fill, getDepth, getHeight, getMinHeight, getPathToRoot, isBalanced </td>
<td>getLeftMost, isBST, getSubTreeSizeAndCount, subTreeSum, subTreeAdd, BFS, DFS, DFSIterative, levelIterative, listLevels, getPredecessor, morris, </td>
</tr>
<tr>
<td>AVL Tree</td>
<td></td>
<td>All the features inherited from Binary Tree, balanceFactor, updateHeight, balancePath, balanceLL, balanceLR, balanceRR, balanceRL</td>
<td></td>
</tr>
<tr>
<td>Binary Search Tree (BST)</td>
<td></td>
<td>All the features inherited from Binary Tree, lastKey</td>
<td>All the features inherited from Binary Tree, lesserSum, allGreaterNodesAdd, balance, isAVLBalanced</td>
</tr>
<tr>
<td>Tree Multiset</td>
<td></td>
<td>All the features inherited from Binary Tree</td>
<td>All the features inherited from Binary Tree</td>
</tr>
<tr>
<td>Segment Tree</td>
<td></td>
<td>build, updateNode, querySumByRange</td>
<td></td>
</tr>
<tr>
<td>Binary Indexed Tree</td>
<td></td>
<td>update, getPrefixSum, getRangeSum, BinaryIndexedTree.lowBit</td>
<td></td>
</tr>
<tr>
<td>Graph</td>
<td>Directed Graph, Undirected Graph</td>
<td>getVertex, getVertexId, containsVertex, vertexSet, addVertex, removeVertex, removeAllVertices, containsEdge, setEdgeWeight, getAllPathsBetween, getPathSumWeight, getMinCostBetween, getMinPathBetween, </td>
<td>dijkstra, dijkstraWithoutHeap, bellmanFord, floyd, tarjan</td>
</tr>
<tr>
<td>Directed Graph</td>
<td></td>
<td>All the features inherited from Graph, getEdge, addEdge, removeEdgeBetween, removeEdge, removeAllEdges, incomingEdgesOf, outgoingEdgesOf, degreeOf, inDegreeOf, outDegreeOf, edgesOf, getEdgeSrc, getEdgeDest, getDestinations, edgeSet, getNeighbors, getEndsOfEdge</td>
<td>All the features inherited from Graph, topologicalSort</td>
</tr>
<tr>
<td>Undirected Graph</td>
<td></td>
<td>All the features inherited from Graph, getEdge, addEdge, removeEdgeBetween, removeEdge, degreeOf, edgesOf, edgeSet, getEdgesOf, getNeighbors, getEndsOfEdge</td>
<td>All the features inherited from Graph</td>
</tr>
<tr>
<td>Singly Linked List</td>
<td></td>
<td>length, head, tail, size, get, getNode, findNodeIndex, findNode, find, findIndex, append, push, prepend, insertAt, removeNode, removeAt, insertBefore, sort, insertAfter, shift, pop, merge, clear, slice, reverse, forEach, map, filter, reduce, toArray, toString</td>
<td></td>
</tr>
<tr>
<td>Hash</td>
<td>CoordinateSet, CoordinateMap</td>
<td></td>
<td></td>
</tr>
<tr>
<td>CoordinateSet</td>
<td></td>
<td>has, set, get, delete</td>
<td></td>
</tr>
<tr>
<td>CoordinateMap</td>
<td></td>
<td>has, add, delete</td>
<td></td>
</tr>
<tr>
<td>Heap</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Doubly Linked List</td>
<td></td>
<td>size, offerFirst, offerLast, peekFirst, peekLast, pollFirst, pollLast, get, isEmpty, insert, remove, </td>
<td></td>
</tr>
[//]: # ( <tr>)
[//]: # ( <td>Matrix</td>)
[//]: # ( <td></td>)
[//]: # ( <td></td>)
[//]: # ( <td></td>)
[//]: # ( </tr>)
<tr>
<td>Priority Queue</td>
<td>Max Priority Queue, Min Priority Queue</td>
<td>offer, peek, poll, leaf, isEmpty, clear, toArray, clone</td>
<td>isValid, sort, DFS</td>
</tr>
<tr>
<td>Max Priority Queue</td>
<td></td>
<td>All the features inherited from Priority Queue</td>
<td>All the features inherited from Priority Queue</td>
</tr>
<tr>
<td>Min Priority Queue</td>
<td></td>
<td>All the features inherited from Priority Queue</td>
<td>All the features inherited from Priority Queue</td>
</tr>
<tr>
<td>Queue</td>
<td>Queue, Dequeue</td>
<td>offer, poll, peek, peekLast, size, isEmpty, toArray, clear, clone, Queue.fromArray</td>
<td></td>
</tr>
<tr>
<td>ObjectDeque</td>
<td></td>
<td>size, offerFirst, offerLast, pollFirst, peekFirst, pollLast, peekLast, get, isEmpty</td>
<td></td>
</tr>
<tr>
<td>ArrayDeque</td>
<td></td>
<td>offerLast, pollLast, pollFirst, offerFirst, peekFirst, peekLast, get, set, insert, remove, isEmpty</td>
<td></td>
</tr>
<tr>
<td>Stack</td>
<td></td>
<td>isEmpty, size, peek, push, pop, toArray, clear, clone, Stack.fromArray</td>
<td></td>
</tr>
<tr>
<td>Trie</td>
<td></td>
<td>put, has, remove, isAbsPrefix, isPrefix, getAll</td>
<td></td>
</tr>
<td><strong>O(1)</strong></td>
<td>Constant</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td><strong>O(log N)</strong></td>
<td>Logarithmic</td>
<td>3</td>
<td>6</td>
<td>9</td>
</tr>
<tr>
<td><strong>O(N)</strong></td>
<td>Linear</td>
<td>10</td>
<td>100</td>
<td>1000</td>
</tr>
<tr>
<td><strong>O(N log N)</strong></td>
<td>n log(n)</td>
<td>30</td>
<td>600</td>
<td>9000</td>
</tr>
<tr>
<td><strong>O(N^2)</strong></td>
<td>Quadratic</td>
<td>100</td>
<td>10000</td>
<td>1000000</td>
</tr>
<tr>
<td><strong>O(2^N)</strong></td>
<td>Exponential</td>
<td>1024</td>
<td>1.26e+29</td>
<td>1.07e+301</td>
</tr>
<tr>
<td><strong>O(N!)</strong></td>
<td>Factorial</td>
<td>3628800</td>
<td>9.3e+157</td>
<td>4.02e+2567</td>
</tr>
</tbody>
</table>
### Data Structure Complexity
<table>
<thead>
<tr>
<th>Data Structure</th>
<th>Access</th>
<th>Search</th>
<th>Insertion</th>
<th>Deletion</th>
<th>Comments</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Array</strong></td>
<td>1</td>
<td>n</td>
<td>n</td>
<td>n</td>
<td></td>
</tr>
<tr>
<td><strong>Stack</strong></td>
<td>n</td>
<td>n</td>
<td>1</td>
<td>1</td>
<td></td>
</tr>
<tr>
<td><strong>Queue</strong></td>
<td>n</td>
<td>n</td>
<td>1</td>
<td>1</td>
<td></td>
</tr>
<tr>
<td><strong>Linked List</strong></td>
<td>n</td>
<td>n</td>
<td>1</td>
<td>n</td>
<td></td>
</tr>
<tr>
<td><strong>Hash Table</strong></td>
<td>-</td>
<td>n</td>
<td>n</td>
<td>n</td>
<td>In case of perfect hash function costs would be O(1)</td>
</tr>
<tr>
<td><strong>Binary Search Tree</strong></td>
<td>n</td>
<td>n</td>
<td>n</td>
<td>n</td>
<td>In case of balanced tree costs would be O(log(n))</td>
</tr>
<tr>
<td><strong>B-Tree</strong></td>
<td>log(n)</td>
<td>log(n)</td>
<td>log(n)</td>
<td>log(n)</td>
<td></td>
</tr>
<tr>
<td><strong>Red-Black Tree</strong></td>
<td>log(n)</td>
<td>log(n)</td>
<td>log(n)</td>
<td>log(n)</td>
<td></td>
</tr>
<tr>
<td><strong>AVL Tree</strong></td>
<td>log(n)</td>
<td>log(n)</td>
<td>log(n)</td>
<td>log(n)</td>
<td></td>
</tr>
<tr>
<td><strong>Bloom Filter</strong></td>
<td>-</td>
<td>1</td>
<td>1</td>
<td>-</td>
<td>False positives are possible while searching</td>
</tr>
</tbody>
</table>
### Sorting Complexity
<table>
<thead>
<tr>
<th>Name</th>
<th>Best</th>
<th>Average</th>
<th>Worst</th>
<th>Memory</th>
<th>Stable</th>
<th>Comments</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Bubble sort</strong></td>
<td>n</td>
<td>n<sup>2</sup></td>
<td>n<sup>2</sup></td>
<td>1</td>
<td>Yes</td>
<td></td>
</tr>
<tr>
<td><strong>Insertion sort</strong></td>
<td>n</td>
<td>n<sup>2</sup></td>
<td>n<sup>2</sup></td>
<td>1</td>
<td>Yes</td>
<td></td>
</tr>
<tr>
<td><strong>Selection sort</strong></td>
<td>n<sup>2</sup></td>
<td>n<sup>2</sup></td>
<td>n<sup>2</sup></td>
<td>1</td>
<td>No</td>
<td></td>
</tr>
<tr>
<td><strong>Heap sort</strong></td>
<td>n&nbsp;log(n)</td>
<td>n&nbsp;log(n)</td>
<td>n&nbsp;log(n)</td>
<td>1</td>
<td>No</td>
<td></td>
</tr>
<tr>
<td><strong>Merge sort</strong></td>
<td>n&nbsp;log(n)</td>
<td>n&nbsp;log(n)</td>
<td>n&nbsp;log(n)</td>
<td>n</td>
<td>Yes</td>
<td></td>
</tr>
<tr>
<td><strong>Quick sort</strong></td>
<td>n&nbsp;log(n)</td>
<td>n&nbsp;log(n)</td>
<td>n<sup>2</sup></td>
<td>log(n)</td>
<td>No</td>
<td>Quicksort is usually done in-place with O(log(n)) stack space</td>
</tr>
<tr>
<td><strong>Shell sort</strong></td>
<td>n&nbsp;log(n)</td>
<td>depends on gap sequence</td>
<td>n&nbsp;(log(n))<sup>2</sup></td>
<td>1</td>
<td>No</td>
<td></td>
</tr>
<tr>
<td><strong>Counting sort</strong></td>
<td>n + r</td>
<td>n + r</td>
<td>n + r</td>
<td>n + r</td>
<td>Yes</td>
<td>r - biggest number in array</td>
</tr>
<tr>
<td><strong>Radix sort</strong></td>
<td>n * k</td>
<td>n * k</td>
<td>n * k</td>
<td>n + k</td>
<td>Yes</td>
<td>k - length of longest key</td>
</tr>
</tbody>
</table>
![complexities](src/assets/complexities-diff.jpg)
@ -272,7 +374,6 @@ Binary Tree, Binary Search Tree (BST), AVL Tree, Tree Multiset, Segment Tree, Bi
![](src/data-structures/binary-tree/diagrams/avl-tree-inserting.gif)
![](src/data-structures/graph/diagrams/tarjan.webp)
![](src/data-structures/graph/diagrams/adjacency-list.jpg)

2229
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "data-structure-typed",
"version": "1.12.11",
"version": "1.12.21",
"description": "Explore our comprehensive Javascript Data Structure / TypeScript Data Structure Library, meticulously crafted to empower developers with a versatile set of essential data structures. Our library includes a wide range of data structures, such as Binary Tree, AVL Tree, Binary Search Tree (BST), Tree Multiset, Segment Tree, Binary Indexed Tree, Graph, Directed Graph, Undirected Graph, Singly Linked List, Hash, CoordinateSet, CoordinateMap, Heap, Doubly Linked List, Priority Queue, Max Priority Queue, Min Priority Queue, Queue, ObjectDeque, ArrayDeque, Stack, and Trie. Each data structure is thoughtfully designed and implemented using TypeScript to provide efficient, reliable, and easy-to-use solutions for your programming needs. Whether you're optimizing algorithms, managing data, or enhancing performance, our TypeScript Data Structure Library is your go-to resource. Elevate your coding experience with these fundamental building blocks for software development.",
"main": "dist/index.js",
"scripts": {
@ -54,7 +54,7 @@
"jest": "^29.6.2",
"ts-jest": "^29.1.1",
"typedoc": "^0.24.8",
"typescript": "^4.6.2"
"typescript": "^4.9.5"
},
"dependencies": {
"lodash": "^4.17.21"

View file

@ -1,3 +1,3 @@
export class AaTree {
}
}

View file

@ -30,15 +30,15 @@ export enum LoopType { iterative = 1, recursive = 2}
export class BinaryTreeNode<T> {
constructor(id: BinaryTreeNodeId, val: T, count?: number) {
this._id = id;
this._val = val;
this._count = count ?? 1;
protected _id: BinaryTreeNodeId;
get id(): BinaryTreeNodeId {
return this._id;
}
protected _id: BinaryTreeNodeId;
get id(): BinaryTreeNodeId {
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getId(): BinaryTreeNodeId {
return this._id;
}
@ -47,21 +47,33 @@ export class BinaryTreeNode<T> {
}
protected _val: T;
get val(): T {
return this._val;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getVal(): T {
return this._val;
}
set val(v: T) {
this._val = v;
}
protected _left?: BinaryTreeNode<T> | null;
get left(): BinaryTreeNode<T> | null | undefined {
return this._left;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getLeft(): BinaryTreeNode<T> | null | undefined {
return this._left;
}
set left(v: BinaryTreeNode<T> | null | undefined) {
if (v) {
v.parent = this;
@ -71,11 +83,17 @@ export class BinaryTreeNode<T> {
}
protected _right?: BinaryTreeNode<T> | null;
get right(): BinaryTreeNode<T> | null | undefined {
return this._right;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getRight(): BinaryTreeNode<T> | null | undefined {
return this._right;
}
set right(v: BinaryTreeNode<T> | null | undefined) {
if (v) {
v.parent = this;
@ -85,45 +103,75 @@ export class BinaryTreeNode<T> {
}
protected _parent: BinaryTreeNode<T> | null | undefined;
get parent(): BinaryTreeNode<T> | null | undefined {
return this._parent;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getParent(): BinaryTreeNode<T> | null | undefined {
return this._parent;
}
set parent(v: BinaryTreeNode<T> | null | undefined) {
this._parent = v;
}
protected _familyPosition: FamilyPosition = FamilyPosition.root;
get familyPosition(): FamilyPosition {
return this._familyPosition;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getFamilyPosition(): FamilyPosition {
return this._familyPosition;
}
set familyPosition(v: FamilyPosition) {
this._familyPosition = v;
}
protected _count = 1;
get count(): number {
return this._count;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getCount(): number {
return this._count;
}
set count(v: number) {
this._count = v;
}
protected _height = 0;
get height(): number {
return this._height;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getHeight(): number {
return this._height;
}
set height(v: number) {
this._height = v;
}
constructor(id: BinaryTreeNodeId, val: T, count?: number) {
this._id = id;
this._val = val;
this._count = count ?? 1;
}
swapLocation(swapNode: BinaryTreeNode<T>): BinaryTreeNode<T> {
const {val, count, height} = swapNode;
const tempNode = new BinaryTreeNode<T>(swapNode.id, val);
@ -187,6 +235,14 @@ export class BinaryTree<T> {
return this._root;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Getters (using the same name as the property) while utilizing separate method names for Setters.
* @returns The method is returning either a BinaryTreeNode object of type T or null.
*/
getRoot(): BinaryTreeNode<T> | null {
return this._root;
}
protected set root(v: BinaryTreeNode<T> | null) {
if (v) {
v.parent = null;
@ -201,6 +257,13 @@ export class BinaryTree<T> {
return this._size;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getSize(): number {
return this._size;
}
protected set size(v: number) {
this._size = v;
}
@ -211,6 +274,13 @@ export class BinaryTree<T> {
return this._count;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getCount(): number {
return this._count;
}
protected set count(v: number) {
this._count = v;
}

View file

@ -17,61 +17,85 @@ export class SegmentTreeNode {
}
protected _start = 0;
get start(): number {
return this._start;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getStart(): number {
return this._start;
}
set start(v: number) {
this._start = v;
}
protected _end = 0;
get end(): number {
return this._end;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getEnd(): number {
return this._end;
}
set end(v: number) {
this._end = v;
}
protected _val: SegmentTreeNodeVal | null = null;
get val(): SegmentTreeNodeVal | null {
return this._val;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getVal(): SegmentTreeNodeVal | null {
return this._val;
}
set val(v: SegmentTreeNodeVal | null) {
this._val = v;
}
protected _sum = 0;
get sum(): number {
return this._sum;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getSum(): number {
return this._sum;
}
set sum(v: number) {
this._sum = v;
}
protected _left: SegmentTreeNode | null = null;
get left(): SegmentTreeNode | null {
return this._left;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getLeft(): SegmentTreeNode | null {
return this._left;
}
set left(v: SegmentTreeNode | null) {
this._left = v;
}
protected _right: SegmentTreeNode | null = null;
get right(): SegmentTreeNode | null {
return this._right;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getRight(): SegmentTreeNode | null {
return this._right;
}
set right(v: SegmentTreeNode | null) {
this._right = v;
}
@ -101,10 +125,18 @@ export class SegmentTree {
}
protected _root: SegmentTreeNode | null;
get root(): SegmentTreeNode | null {
return this._root;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getRoot(): SegmentTreeNode | null {
return this._root;
}
set root(v: SegmentTreeNode | null) {
this._root = v;
}
/**
* The function builds a segment tree by recursively dividing the given range into smaller segments and creating nodes

View file

@ -10,19 +10,25 @@ import {PriorityQueue} from '../priority-queue';
import type {DijkstraResult, IGraph, VertexId} from '../types';
export class AbstractVertex {
constructor(id: VertexId) {
this._id = id;
}
protected _id: VertexId;
public get id(): VertexId {
get id(): VertexId {
return this._id;
}
public set id(v: VertexId) {
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getId(): VertexId {
return this._id;
}
set id(v: VertexId) {
this._id = v;
}
constructor(id: VertexId) {
this._id = id;
}
}
export abstract class AbstractEdge {
@ -41,21 +47,33 @@ export abstract class AbstractEdge {
}
private _weight: number;
get weight(): number {
return this._weight;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getWeight(): number {
return this._weight;
}
set weight(v: number) {
this._weight = v;
}
private _hashCode: string;
get hashCode(): string {
return this._hashCode;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getHashCode(): string {
return this._hashCode;
}
set hashCode(v: string) {
this._hashCode = v;
}
@ -97,9 +115,9 @@ export abstract class AbstractGraph<V extends AbstractVertex, E extends Abstract
* The function checks if a vertex exists in a graph.
* @param {V | VertexId} vertexOrId - The parameter `vertexOrId` can accept either a vertex object (`V`) or a vertex ID
* (`VertexId`).
* @returns The method `containsVertex` returns a boolean value.
* @returns The method `hasVertex` returns a boolean value.
*/
containsVertex(vertexOrId: V | VertexId): boolean {
hasVertex(vertexOrId: V | VertexId): boolean {
return this._vertices.has(this.getVertexId(vertexOrId));
}
@ -120,7 +138,7 @@ export abstract class AbstractGraph<V extends AbstractVertex, E extends Abstract
* false. Otherwise, it will add the newVertex to the graph and return true.
*/
addVertex(newVertex: V): boolean {
if (this.containsVertex(newVertex)) {
if (this.hasVertex(newVertex)) {
return false;
}
this._vertices.set(newVertex.id, newVertex);
@ -165,10 +183,10 @@ export abstract class AbstractGraph<V extends AbstractVertex, E extends Abstract
* a vertex in a graph, while V represents the type of the vertex itself.
* @param {VertexId | V} v2 - The parameter `v2` represents the second vertex in an edge. It can be either a `VertexId`
* or a `V` type.
* @returns The function `containsEdge` returns a boolean value. It returns `true` if there is an edge between the
* @returns The function `hasEdge` returns a boolean value. It returns `true` if there is an edge between the
* vertices `v1` and `v2`, and `false` otherwise.
*/
containsEdge(v1: VertexId | V, v2: VertexId | V): boolean {
hasEdge(v1: VertexId | V, v2: VertexId | V): boolean {
const edge = this.getEdge(v1, v2);
return !!edge;
}
@ -499,8 +517,20 @@ export abstract class AbstractGraph<V extends AbstractVertex, E extends Abstract
return {distMap, preMap, seen, paths, minDist, minPath};
}
/**
* Dijkstra's algorithm only solves the single-source shortest path problem, while the Bellman-Ford algorithm and Floyd-Warshall algorithm can address shortest paths between all pairs of nodes.
* Dijkstra's algorithm is suitable for graphs with non-negative edge weights, whereas the Bellman-Ford algorithm and Floyd-Warshall algorithm can handle negative-weight edges.
* The time complexity of Dijkstra's algorithm and the Bellman-Ford algorithm depends on the size of the graph, while the time complexity of the Floyd-Warshall algorithm is O(V^3), where V is the number of nodes. For dense graphs, Floyd-Warshall might become slower.
*/
/**
* Dijkstra algorithm time: O(logVE) space: O(V + E)
* Dijkstra's algorithm is used to find the shortest paths from a source node to all other nodes in a graph. Its basic idea is to repeatedly choose the node closest to the source node and update the distances of other nodes using this node as an intermediary. Dijkstra's algorithm requires that the edge weights in the graph are non-negative.
*/
/**
* Dijkstra algorithm time: O(logVE) space: O(V + E)
* Dijkstra's algorithm is used to find the shortest paths from a source node to all other nodes in a graph. Its basic idea is to repeatedly choose the node closest to the source node and update the distances of other nodes using this node as an intermediary. Dijkstra's algorithm requires that the edge weights in the graph are non-negative.
* The `dijkstra` function implements Dijkstra's algorithm to find the shortest path between a source vertex and an
* optional destination vertex, and optionally returns the minimum distance, the paths, and other information.
* @param {V | VertexId} src - The `src` parameter represents the source vertex from which the Dijkstra algorithm will
@ -625,10 +655,17 @@ export abstract class AbstractGraph<V extends AbstractVertex, E extends Abstract
abstract getEndsOfEdge(edge: E): [V, V] | null;
/**
* BellmanFord time:O(VE) space:O(V)
* one to rest pairs
* The Bellman-Ford algorithm is also used to find the shortest paths from a source node to all other nodes in a graph. Unlike Dijkstra's algorithm, it can handle edge weights that are negative. Its basic idea involves iterative relaxation of all edges for several rounds to gradually approximate the shortest paths. Due to its ability to handle negative-weight edges, the Bellman-Ford algorithm is more flexible in some scenarios.
* The `bellmanFord` function implements the Bellman-Ford algorithm to find the shortest path from a source vertex to
*/
/**
* BellmanFord time:O(VE) space:O(V)
* one to rest pairs
* The Bellman-Ford algorithm is also used to find the shortest paths from a source node to all other nodes in a graph. Unlike Dijkstra's algorithm, it can handle edge weights that are negative. Its basic idea involves iterative relaxation of all edges for several rounds to gradually approximate the shortest paths. Due to its ability to handle negative-weight edges, the Bellman-Ford algorithm is more flexible in some scenarios.
* The `bellmanFord` function implements the Bellman-Ford algorithm to find the shortest path from a source vertex to
* all other vertices in a graph, and optionally detects negative cycles and generates the minimum path.
* @param {V | VertexId} src - The `src` parameter is the source vertex from which the Bellman-Ford algorithm will
@ -732,6 +769,13 @@ export abstract class AbstractGraph<V extends AbstractVertex, E extends Abstract
/**
* Floyd algorithm time: O(V^3) space: O(V^2), not support graph with negative weight cycle
* all pairs
* The Floyd-Warshall algorithm is used to find the shortest paths between all pairs of nodes in a graph. It employs dynamic programming to compute the shortest paths from any node to any other node. The Floyd-Warshall algorithm's advantage lies in its ability to handle graphs with negative-weight edges, and it can simultaneously compute shortest paths between any two nodes.
*/
/**
* Floyd algorithm time: O(V^3) space: O(V^2), not support graph with negative weight cycle
* all pairs
* The Floyd-Warshall algorithm is used to find the shortest paths between all pairs of nodes in a graph. It employs dynamic programming to compute the shortest paths from any node to any other node. The Floyd-Warshall algorithm's advantage lies in its ability to handle graphs with negative-weight edges, and it can simultaneously compute shortest paths between any two nodes.
* The function implements the Floyd-Warshall algorithm to find the shortest path between all pairs of vertices in a
* graph.
* @returns The function `floyd()` returns an object with two properties: `costs` and `predecessor`. The `costs`
@ -903,8 +947,7 @@ export abstract class AbstractGraph<V extends AbstractVertex, E extends Abstract
}
// unionFind() {
// }
// unionFind() {}
/**--- end find cycles --- */

View file

@ -40,17 +40,26 @@ export class DirectedEdge extends AbstractEdge {
get src(): VertexId {
return this._src;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getSrc(): VertexId {
return this._src;
}
set src(v: VertexId) {
this._src = v;
}
private _dest: VertexId;
get dest(): VertexId {
return this._dest;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getDest(): VertexId {
return this._dest;
}
set dest(v: VertexId) {
this._dest = v;
}
@ -101,7 +110,7 @@ export class DirectedGraph<V extends DirectedVertex, E extends DirectedEdge> ext
* graph, and `false` if either the source or destination vertices of the edge are not present in the graph.
*/
addEdge(edge: E): boolean {
if (!(this.containsVertex(edge.src) && this.containsVertex(edge.dest))) {
if (!(this.hasVertex(edge.src) && this.hasVertex(edge.dest))) {
return false;
}
@ -401,7 +410,7 @@ export class DirectedGraph<V extends DirectedVertex, E extends DirectedEdge> ext
* returns null.
*/
getEndsOfEdge(edge: E): [V, V] | null {
if (!this.containsEdge(edge.src, edge.dest)) {
if (!this.hasEdge(edge.src, edge.dest)) {
return null;
}
const v1 = this.getVertex(edge.src);

View file

@ -35,21 +35,38 @@ export class UndirectedEdge extends AbstractEdge {
}
private _vertices: [VertexId, VertexId];
public get vertices() {
get vertices() {
return this._vertices;
}
public set vertices(v: [VertexId, VertexId]) {
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getVertices() {
return this._vertices;
}
set vertices(v: [VertexId, VertexId]) {
this._vertices = v;
}
}
export class UndirectedGraph<V extends UndirectedVertex, E extends UndirectedEdge> extends AbstractGraph<V, E> {
protected _edges: Map<V, E[]> = new Map();
protected _edges: Map<V, E[]>;
get edges(): Map<V, E[]> {
return this._edges;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getEdges(): Map<V, E[]> {
return this._edges;
}
protected set edges(v: Map<V, E[]>) {
this._edges = v;
}
constructor() {
super();
this._edges = new Map<V, E[]>();
}
/**
@ -223,7 +240,7 @@ export class UndirectedGraph<V extends UndirectedVertex, E extends UndirectedEdg
* `null`.
*/
getEndsOfEdge(edge: E): [V, V] | null {
if (!this.containsEdge(edge.vertices[0], edge.vertices[1])) {
if (!this.hasEdge(edge.vertices[0], edge.vertices[1])) {
return null;
}
const v1 = this.getVertex(edge.vertices[0]);

View file

@ -6,7 +6,19 @@
* @license MIT License
*/
export class CoordinateMap<V> extends Map<any, V> {
private readonly _joint: string = '_';
protected _joint: string = '_';
get joint(): string {
return this._joint;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getJoint(): string {
return this._joint;
}
protected set joint(v: string) {
this._joint = v;
}
constructor(joint?: string) {
super();

View file

@ -6,7 +6,19 @@
* @license MIT License
*/
export class CoordinateSet extends Set {
private readonly _joint: string = '_';
protected _joint: string = '_';
get joint(): string {
return this._joint;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getJoint(): string {
return this._joint;
}
protected set joint(v: string) {
this._joint = v;
}
constructor(joint?: string) {
super();

View file

@ -10,7 +10,32 @@ import type {HeapItem, HeapOptions} from '../types';
export abstract class Heap<T> {
protected abstract _pq: PriorityQueue<HeapItem<T>>;
get pq() {
return this._pq;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getPq() {
return this._pq;
}
protected set pq(v: PriorityQueue<HeapItem<T>>) {
this._pq = v;
}
protected _priorityCb: (element: T) => number;
get priorityCb() {
return this._priorityCb;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getPriorityCb() {
return this._priorityCb;
}
protected set priorityCb(v: (element: T) => number) {
this._priorityCb = v;
}
/**
* The function is a constructor for a class that initializes a priority callback function based on the
@ -36,6 +61,12 @@ export abstract class Heap<T> {
get size(): number {
return this._pq.size;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getSize(): number {
return this._pq.size;
}
/**
* The function checks if a priority queue is empty.

View file

@ -8,29 +8,86 @@
import type {DoublyLinkedListGetBy} from '../types';
export class DoublyLinkedListNode<T> {
val: T;
next: DoublyLinkedListNode<T> | null;
prev: DoublyLinkedListNode<T> | null;
protected _val: T;
get val(): T {
return this._val;
}
set val(v: T) {
this._val = v;
}
protected _next: DoublyLinkedListNode<T> | null;
get next(): DoublyLinkedListNode<T> | null {
return this._next;
}
set next(v: DoublyLinkedListNode<T> | null) {
this._next = v;
}
protected _prev: DoublyLinkedListNode<T> | null;
get prev(): DoublyLinkedListNode<T> | null {
return this._prev;
}
set prev(v: DoublyLinkedListNode<T> | null) {
this._prev = v;
}
constructor(nodeValue: T) {
this.val = nodeValue;
this.next = null;
this.prev = null;
this._val = nodeValue;
this._next = null;
this._prev = null;
}
}
export class DoublyLinkedList<T> {
private _first: DoublyLinkedListNode<T> | null = null;
private _last: DoublyLinkedListNode<T> | null = null;
private _size = 0;
protected _first: DoublyLinkedListNode<T> | null;
get first(): DoublyLinkedListNode<T> | null {
return this._first;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getFirst(): DoublyLinkedListNode<T> | null {
return this._first;
}
protected set first(v: DoublyLinkedListNode<T> | null) {
this._first = v;
}
protected _last: DoublyLinkedListNode<T> | null;
get last(): DoublyLinkedListNode<T> | null {
return this._last;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getLast(): DoublyLinkedListNode<T> | null {
return this._last;
}
protected set last(v: DoublyLinkedListNode<T> | null) {
this._last = v;
}
protected _size: number;
get size(): number {
return this._size;
}
set size(v: number) {
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getSize(): number {
return this._size;
}
protected set size(v: number) {
this._size = v;
}
constructor() {
this._first = null;
this._last = null;
this._size = 0;
}
/**
* The function adds a new node with a given value to the beginning of a doubly linked list.
* @param {T} val - The `val` parameter represents the value of the element that you want to add to the beginning of

View file

@ -6,81 +6,88 @@
* @license MIT License
*/
/**
* The class which represents one link or node in a linked list
* ```ts
* const node = new SinglyLinkedListNode(1, null, null, null);
* ```
*/
export class SinglyLinkedListNode<NodeData = any> {
constructor(
/** Data stored on the node */
public val: NodeData,
/** The previous node in the list */
public prev: SinglyLinkedListNode<NodeData> | null,
/** The next link in the list */
public next: SinglyLinkedListNode<NodeData> | null,
/** The list this node belongs to */
public list: SinglyLinkedList<NodeData> | null,
) {
/* The SinglyLinkedListNode class represents a node in a singly linked list and provides methods for inserting, removing,
and accessing nodes. */
export class SinglyLinkedListNode<NodeVal = any> {
protected _val: NodeVal;
get val(): NodeVal {
return this._val;
}
/**
* Alias to .val
* ```ts
* new LinkedList(1, 2, 3).head.value; // 1
* ```
*/
public get value() {
return this.val;
set val(value: NodeVal) {
this._val = value;
}
/**
* Get the index of this node
* ```ts
* new LinkedList(1, 2, 3).head.index; // 0
* ```
*/
public get index() {
protected _prev: SinglyLinkedListNode<NodeVal> | null;
get prev(): SinglyLinkedListNode<NodeVal> | null {
return this._prev;
}
set prev(value: SinglyLinkedListNode<NodeVal> | null) {
this._prev = value;
}
protected _next: SinglyLinkedListNode<NodeVal> | null
get next(): SinglyLinkedListNode<NodeVal> | null {
return this._next;
}
set next(value: SinglyLinkedListNode<NodeVal> | null) {
this._next = value;
}
protected _list: SinglyLinkedList<NodeVal> | null
get list(): SinglyLinkedList<NodeVal> | null {
return this._list;
}
set list(value: SinglyLinkedList<NodeVal> | null) {
this._list = value;
}
constructor(val: NodeVal, prev?: SinglyLinkedListNode<NodeVal> | null, next?: SinglyLinkedListNode<NodeVal> | null, list?: SinglyLinkedList<NodeVal> | null) {
this._val = val;
this._prev = prev || null;
this._next = next || null;
this._list = list || null;
}
get index() {
if (!this.list) {
return undefined;
}
return this.list.findIndex((value) => value === this.value);
return this.list.findIndex((value) => value === this.val);
}
/**
* Insert a new node before this one
* ```ts
* new LinkedList(2, 3).head.insertBefore(1); // 1 <=> 2 <=> 3
* ```
* @param val Data to save in the node
* The `insertBefore` function inserts a new node with the given value before the current node in a singly linked list.
* @param {NodeVal} val - The parameter "val" is of type "NodeVal". It represents the value of the node that you want
* to insert before the current node.
* @returns The method is returning a SinglyLinkedList<NodeVal>.
*/
public insertBefore(val: NodeData): SinglyLinkedList<NodeData> {
insertBefore(val: NodeVal): SinglyLinkedList<NodeVal> {
return this.list !== null
? this.list.insertBefore(this, val)
: new SinglyLinkedList(val, this.val);
}
/**
* Insert new val after this node
* ```ts
* new LinkedList(1, 2).tail.insertAfter(3); // 1 <=> 2 <=> 3
* ```
* @param val Data to be saved in the node
* The function inserts a new node with the given value after the current node in a singly linked list.
* @param {NodeVal} val - The parameter `val` is the value of the node that you want to insert after the current node.
* @returns The method is returning a SinglyLinkedList<NodeVal>.
*/
public insertAfter(val: NodeData): SinglyLinkedList<NodeData> {
insertAfter(val: NodeVal): SinglyLinkedList<NodeVal> {
return this.list !== null
? this.list.insertAfter(this, val)
: new SinglyLinkedList(this.val, val);
}
/**
* Remove this node
* ```ts
* new LinkedList(1, 2, 3, 4).tail.remove(); // 1 <=> 2 <=> 3
* ```
* The `remove()` function removes a node from a singly linked list.
* @returns The remove() method is returning a SinglyLinkedListNode<NodeVal> object.
*/
public remove(): SinglyLinkedListNode<NodeData> {
remove(): SinglyLinkedListNode<NodeVal> {
if (this.list === null) {
throw new ReferenceError('Node does not belong to any list');
}
@ -88,27 +95,42 @@ export class SinglyLinkedListNode<NodeData = any> {
}
}
export class SinglyLinkedList<NodeVal = any> {
/**
* A doubly linked list
* ```ts
* const list = new LinkedList(1, 2, 3);
* const listFromArray = LinkedList.from([1, 2, 3]);
* ```
*/
export class SinglyLinkedList<NodeData = any> {
protected _head: SinglyLinkedListNode<NodeVal> | null;
get head(): SinglyLinkedListNode<NodeVal> | null {
return this._head;
}
set head(value: SinglyLinkedListNode<NodeVal> | null) {
this._head = value;
}
/** The head of the list, the first node */
public head: SinglyLinkedListNode<NodeData> | null;
/** The tail of the list, the last node */
public tail: SinglyLinkedListNode<NodeData> | null;
/** Internal size reference */
private size: number;
constructor(...args: NodeData[]) {
this.head = null;
this.tail = null;
this.size = 0;
protected _tail: SinglyLinkedListNode<NodeVal> | null;
get tail(): SinglyLinkedListNode<NodeVal> | null {
return this._tail;
}
set tail(value: SinglyLinkedListNode<NodeVal> | null) {
this._tail = value;
}
protected _size: number;
get size(): number {
return this._size;
}
set size(value: number) {
this._size = value;
}
/**
* The constructor initializes a linked list with the given arguments as nodes.
* @param {NodeVal[]} args - args is a rest parameter that allows the constructor to accept an arbitrary number of
* arguments of type NodeVal.
*/
constructor(...args: NodeVal[]) {
this._head = null;
this._tail = null;
this._size = 0;
for (let i = 0; i < arguments.length; i++) {
this.append(args[i]);
@ -116,49 +138,39 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* The length of the list
* The `from` function in TypeScript creates a new SinglyLinkedList instance from an iterable object.
* @param iterable - The `iterable` parameter is an object that can be iterated over, such as an array or a string. It
* contains a collection of elements of type `T`.
* @returns The method is returning a new instance of the SinglyLinkedList class.
*/
public get length(): number {
return this.size;
}
/**
* Convert any iterable to a new linked list
* ```javascript
* const array = [1, 2, 3];
* const list = LinkedList.from(array);
* ```
* @param iterable Any iterable datatype like Array or Map
*/
public static from<T>(iterable: Iterable<T>): SinglyLinkedList<T> {
static from<T>(iterable: Iterable<T>): SinglyLinkedList<T> {
return new SinglyLinkedList(...iterable);
}
/**
* Get the node val at a specified index, zero based
* ```ts
* new LinkedList(1, 2, 3).get(0); // 1
* ```
* @param index to retrieve val at
* The `get` function returns the value of a node at a given index in a data structure.
* @param {number} index - The index parameter is a number that represents the position of the node in the data
* structure.
* @returns The method is returning the value of the node at the specified index if the node exists, otherwise it
* returns undefined.
*/
public get(index: number): NodeData | undefined {
get(index: number): NodeVal | undefined {
const node = this.getNode(index);
return node !== undefined ? node.val : undefined;
}
/**
* Get the node at index, zero based
* ```ts
* new LinkedList(1, 2, 3).getNode(0);
* // { prev: null, val: 1, next: SinglyLinkedListNode }
* ```
* The function `getNode` returns the node at a given index in a singly linked list.
* @param {number} index - The `index` parameter is a number that represents the position of the node we want to
* retrieve from the linked list.
* @returns a SinglyLinkedListNode<NodeVal> object or undefined.
*/
public getNode(index: number): SinglyLinkedListNode<NodeData> | undefined {
if (this.head === null || index < 0 || index >= this.length) {
getNode(index: number): SinglyLinkedListNode<NodeVal> | undefined {
if (this.head === null || index < 0 || index >= this.size) {
return undefined;
}
const asc = index < this.length / 2;
const stopAt = asc ? index : this.length - index - 1;
const asc = index < this.size / 2;
const stopAt = asc ? index : this.size - index - 1;
const nextNode = asc ? 'next' : 'prev';
let currentNode = asc ? this.head : this.tail;
// TODO after no-non-null-assertion not ensure the logic
@ -171,26 +183,28 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* Return the first node and its index in the list that
* satisfies the testing function
* ```ts
* new LinkedList(1, 2, 3).findNodeIndex(val => val === 1);
* // { node: SinglyLinkedListNode, index: 0 }
* ```
* @param f A function to be applied to the val of each node
* The function `findNodeIndex` searches for a node in a singly linked list that satisfies a given condition and
* returns its index and the node itself.
* @param callbackFn - The callbackFn parameter is a function that takes three arguments: data, index, and list. It is
* used to determine whether a node in the singly linked list matches a certain condition. The function should return a
* boolean value indicating whether the condition is met for the given node.
* @returns The function `findNodeIndex` returns an object with two properties: `node` and `index`. The `node` property
* contains the node that matches the condition specified in the `callbackFn` function, and the `index` property
* contains the index of that node in the linked list. If no node matches the condition, the function returns
* `undefined`.
*/
public findNodeIndex(f: (
data: NodeData,
findNodeIndex(callbackFn: (
data: NodeVal,
index: number,
list: SinglyLinkedList<NodeData>,
list: SinglyLinkedList<NodeVal>,
) => boolean): ({
node: SinglyLinkedListNode<NodeData>,
node: SinglyLinkedListNode<NodeVal>,
index: number,
}) | undefined {
let currentIndex = 0;
let currentNode = this.head;
while (currentNode) {
if (f(currentNode.val, currentIndex, this)) {
if (callbackFn(currentNode.val, currentIndex, this)) {
return {
index: currentIndex,
node: currentNode,
@ -203,67 +217,56 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* Returns the first node in the list that
* satisfies the provided testing function. Otherwise undefined is returned.
* ```ts
* new LinkedList(1, 2, 3).findNode(val => val === 1);
* // { prev: null, val: 1, next: SinglyLinkedListNode }
* ```
* @param f Function to test val against
* The findNode function searches for a node in a singly linked list based on a given callback function.
* @param callbackFn - A callback function that takes three parameters: data, index, and list. It returns a boolean
* value indicating whether the current node matches the desired criteria.
* @returns The function `findNode` returns a `SinglyLinkedListNode<NodeVal>` if a node satisfying the condition
* specified by the `callbackFn` is found in the linked list. If no such node is found, it returns `undefined`.
*/
public findNode(f: (
data: NodeData,
findNode(callbackFn: (
data: NodeVal,
index: number,
list: SinglyLinkedList<NodeData>,
) => boolean): SinglyLinkedListNode<NodeData> | undefined {
const nodeIndex = this.findNodeIndex(f);
list: SinglyLinkedList<NodeVal>,
) => boolean): SinglyLinkedListNode<NodeVal> | undefined {
const nodeIndex = this.findNodeIndex(callbackFn);
return nodeIndex !== undefined ? nodeIndex.node : undefined;
}
/**
* Returns the value of the first element in the list that
* satisfies the provided testing function. Otherwise undefined is returned.
* ```ts
* new LinkedList(1, 2, 3).find(val => val === 1); // 1
* ```
* @param f Function to test val against
* The `find` function in TypeScript searches for a node in a singly linked list based on a given callback function and
* returns the value of the found node.
* @param callbackFn - A callback function that takes three parameters: data, index, and list. It returns a boolean
* value indicating whether the condition is met for a particular node in the linked list.
* @returns The method `find` returns the `NodeVal` value of the first node in the linked list that satisfies the
* condition specified by the `callbackFn` function. If no node satisfies the condition, it returns `undefined`.
*/
public find(f: (
data: NodeData,
find(callbackFn: (
data: NodeVal,
index: number,
list: SinglyLinkedList<NodeData>,
) => boolean): NodeData | undefined {
const nodeIndex = this.findNodeIndex(f);
list: SinglyLinkedList<NodeVal>,
) => boolean): NodeVal | undefined {
const nodeIndex = this.findNodeIndex(callbackFn);
return nodeIndex !== undefined ? nodeIndex.node.val : undefined;
}
/**
* Returns the index of the first node in the list that
* satisfies the provided testing function. Ohterwise -1 is returned.
* ```ts
* new LinkedList(1, 2, 3).findIndex(val => val === 3); // 2
* ```
* @param f Function to test val against
* The findIndex function returns the index of the first node in a singly linked list that satisfies a given condition,
* or -1 if no such node is found.
* @param callbackFn - A callback function that takes three parameters: data, index, and list. It returns a boolean
* value indicating whether the condition is met for a particular node in the singly linked list.
* @returns The method `findIndex` returns a number.
*/
public findIndex(f: (
data: NodeData,
findIndex(callbackFn: (
data: NodeVal,
index: number,
list: SinglyLinkedList<NodeData>,
list: SinglyLinkedList<NodeVal>,
) => boolean): number {
const nodeIndex = this.findNodeIndex(f);
const nodeIndex = this.findNodeIndex(callbackFn);
return nodeIndex !== undefined ? nodeIndex.index : -1;
}
/**
* Append one or any number of nodes to the end of the list.
* This modifies the list in place and returns the list itself
* to make this method chainable.
* ```ts
* new LinkedList(1).append(2).append(3, 4); // 1 <=> 2 <=> 3 <=> 4
* ```
* @param args Data to be stored in the node, takes any number of arguments
*/
public append(...args: NodeData[]): SinglyLinkedList<NodeData> {
/* The above code is a comment in TypeScript. It is using the triple hash symbol ( */
append(...args: NodeVal[]): SinglyLinkedList<NodeVal> {
for (const val of args) {
const node = new SinglyLinkedListNode(val, this.tail, null, this);
if (this.head === null) {
@ -279,26 +282,23 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* Synonym for append
* ```ts
* new LinkedList(1).push(2).push(3, 4); // 1 <=> 2 <=> 3 <=> 4
* ```
* @param args Data to be stored, takes any number of arguments
* The push function appends multiple NodeVal objects to a data structure and returns the new size of the data
* structure.
* @param {NodeVal[]} args - args is a rest parameter of type NodeVal[]. It allows the function to accept any number
* of arguments of type NodeVal.
* @returns The size of the data structure after the nodes are appended.
*/
public push(...args: NodeData[]): number {
push(...args: NodeVal[]): number {
this.append(...args);
return this.length;
return this.size;
}
/**
* Prepend any number of val arguments to the list. The
* argument list is prepended as a block to reduce confusion:
* ```javascript
* new LinkedList(3, 4).prepend(0, 1, 2); // [0, 1, 2, 3, 4]
* ```
* @param args Data to be stored in the node, accepts any number of arguments
* The `prepend` function adds new nodes to the beginning of a singly linked list.
* @param {NodeVal[]} args - An array of NodeVal objects.
* @returns The `prepend` method is returning the updated `SinglyLinkedList` object.
*/
public prepend(...args: NodeData[]): SinglyLinkedList<NodeData> {
prepend(...args: NodeVal[]): SinglyLinkedList<NodeVal> {
const reverseArgs = Array.from(args).reverse();
for (const val of reverseArgs) {
const node = new SinglyLinkedListNode(val, null, this.head, this);
@ -315,16 +315,14 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* Insert a new node at a given index position. If index is
* out of bounds, the node is appended, if index is negative
* or 0, it will be prepended.
* ```ts
* new LinkedList(1, 3).insertAt(1, 2); // 1 <=> 2 <=> 3
* ```
* @param index The index to insert the new node at
* @param val Data to be stored on the new node
* The `insertAt` function inserts a value at a specified index in a singly linked list.
* @param {number} index - The index parameter is a number that represents the position at which the new node should be
* inserted in the linked list.
* @param {NodeVal} val - The `val` parameter represents the value of the node that you want to insert into the linked
* list.
* @returns The method `insertAt` returns the updated `SinglyLinkedList` object.
*/
public insertAt(index: number, val: NodeData): SinglyLinkedList<NodeData> {
insertAt(index: number, val: NodeVal): SinglyLinkedList<NodeVal> {
if (this.head === null) {
return this.append(val);
}
@ -343,15 +341,13 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* Remove the specified node from the list and return the removed
* node afterwards.
* ```ts
* const list = new LinkedList(1, 2, 3);
* list.removeNode(list.tail); // { prev: null, val: 3, next: null, list: null }
* ```
* @param node The node to be removed
* The removeNode function removes a node from a singly linked list and updates the head, tail, and size properties
* accordingly.
* @param node - The `node` parameter is of type `SinglyLinkedListNode<NodeVal>`, which represents a node in a singly
* linked list.
* @returns the removed node.
*/
public removeNode(node: SinglyLinkedListNode<NodeData>): SinglyLinkedListNode<NodeData> {
removeNode(node: SinglyLinkedListNode<NodeVal>): SinglyLinkedListNode<NodeVal> {
if (node.list !== this) {
throw new ReferenceError('Node does not belong to this list');
}
@ -380,30 +376,29 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* Remove the node at the specified index
* ```ts
* new LinkedList(1, 2, 3).removeAt(2); // { prev: null, val: 3, next: null, list: null }
* ```
* @param index Index at which to remove
* The `removeAt` function removes a node at a specified index from a singly linked list.
* @param {number} index - The index parameter is a number that represents the position of the node to be removed in
* the singly linked list.
* @returns The method `removeAt` returns a `SinglyLinkedListNode<NodeVal>` if the node at the specified index is
* found and removed successfully. If the node is not found, it returns `undefined`.
*/
public removeAt(index: number): SinglyLinkedListNode<NodeData> | undefined {
removeAt(index: number): SinglyLinkedListNode<NodeVal> | undefined {
const node = this.getNode(index);
return node !== undefined ? this.removeNode(node) : undefined;
}
/**
* Insert a new node before the reference node
* ```ts
* const list = new LinkedList(1, 3);
* list.insertBefore(list.tail, 2); // 1 <=> 2 <=> 3
* ```
* @param referenceNode The node reference
* @param val Data to save in the node
* The `insertBefore` function inserts a new node with a given value before a specified reference node in a singly
* linked list.
* @param referenceNode - The referenceNode parameter is the node in the linked list before which the new node will be
* inserted.
* @param {NodeVal} val - The value of the new node that will be inserted before the reference node.
* @returns The method is returning the updated SinglyLinkedList object.
*/
public insertBefore(
referenceNode: SinglyLinkedListNode<NodeData>,
val: NodeData,
): SinglyLinkedList<NodeData> {
insertBefore(
referenceNode: SinglyLinkedListNode<NodeVal>,
val: NodeVal,
): SinglyLinkedList<NodeVal> {
const node = new SinglyLinkedListNode(val, referenceNode.prev, referenceNode, this);
if (referenceNode.prev === null) {
this.head = node;
@ -417,23 +412,24 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* Sorts the linked list using the provided compare function
* @param compare A function used to compare the val of two nodes. It should return
* a boolean. True will insert a before b, false will insert b before a.
* (a, b) => a < b or (1, 2) => 1 < 2 === true, 2 will be inserted after 1,
* the sort order will be ascending.
* The `sort` function uses the quicksort algorithm to sort the elements of a singly linked list based on a provided
* comparison function.
* @param start - The `start` parameter is the starting node of the sublist that needs to be sorted.
* @param end - The `end` parameter is a reference to the last node in the linked list. It is used as the pivot element
* for the quicksort algorithm.
* @returns The `sort` method is returning the sorted `SinglyLinkedList` object.
*/
public sort(compare: (a: NodeData, b: NodeData) => boolean): SinglyLinkedList<NodeData> {
sort(compare: (a: NodeVal, b: NodeVal) => boolean): SinglyLinkedList<NodeVal> {
if (this.head === null || this.tail === null) {
return this;
}
if (this.length < 2) {
if (this.size < 2) {
return this;
}
const quicksort = (
start: SinglyLinkedListNode<NodeData>,
end: SinglyLinkedListNode<NodeData>,
start: SinglyLinkedListNode<NodeVal>,
end: SinglyLinkedListNode<NodeVal>,
) => {
if (start === end) {
return;
@ -476,18 +472,16 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* Insert a new node after this one
* ```ts
* const list = new LinkedList(2, 3);
* list.insertAfter(list.head, 1); // 1 <=> 2 <=> 3
* ```
* @param referenceNode The reference node
* @param val Data to be saved in the node
* The `insertAfter` function inserts a new node with a given value after a specified reference node in a singly linked
* list.
* @param referenceNode - The referenceNode parameter is the node after which the new node will be inserted.
* @param {NodeVal} val - The value of the new node that will be inserted after the reference node.
* @returns The `insertAfter` method is returning the updated `SinglyLinkedList` object.
*/
public insertAfter(
referenceNode: SinglyLinkedListNode<NodeData>,
val: NodeData,
): SinglyLinkedList<NodeData> {
insertAfter(
referenceNode: SinglyLinkedListNode<NodeVal>,
val: NodeVal,
): SinglyLinkedList<NodeVal> {
const node = new SinglyLinkedListNode(val, referenceNode, referenceNode.next, this);
if (referenceNode.next === null) {
this.tail = node;
@ -501,39 +495,27 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* Remove the first node from the list and return the val of the removed node
* or undefined
* ```ts
* new LinkedList(1, 2, 3).shift(); // 1
* ```
* The `shift()` function removes and returns the first element from a linked list.
* @returns The `shift()` method is returning a value of type `NodeVal` or `undefined`.
*/
public shift(): NodeData | undefined {
shift(): NodeVal | undefined {
return this.removeFromAnyEnd(this.head);
}
/**
* Remove the last node from the list and return the val of the removed node
* or undefined if the list was empty
* ```ts
* new LinkedList(1, 2, 3).pop(); // 3
* ```
* The `pop()` function removes and returns the last element from a linked list.
* @returns The `pop()` method is returning a value of type `NodeVal` or `undefined`.
*/
public pop(): NodeData | undefined {
pop(): NodeVal | undefined {
return this.removeFromAnyEnd(this.tail);
}
/**
* Merge the current list with another. Both lists will be
* equal after merging.
* ```ts
* const list = new LinkedList(1, 2);
* const otherList = new LinkedList(3);
* list.merge(otherList);
* (list === otherList); // true
* ```
* @param list The list to be merged
* The merge function merges two singly linked lists by updating the next and prev pointers, as well as the head, tail,
* and size properties.
* @param list - The parameter "list" is a SinglyLinkedList object that contains nodes with data of type NodeVal.
*/
public merge(list: SinglyLinkedList<NodeData>): void {
merge(list: SinglyLinkedList<NodeVal>): void {
if (this.tail !== null) {
this.tail.next = list.head;
}
@ -549,13 +531,10 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* Removes all nodes from a list
*
* ```ts
* list.clear();
* ```
* The clear() function resets the linked list by setting the head and tail to null and the size to 0.
* @returns The "this" object is being returned.
*/
public clear() {
clear() {
this.head = null;
this.tail = null;
this.size = 0;
@ -563,19 +542,16 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* The slice() method returns a shallow copy of a
* portion of a list into a new list object selected
* from start to end (end not included).
* The original list will not be modified.
* ```ts
* const list = new LinkedList(1, 2, 3, 4, 5);
* const newList = list.slice(0, 3); // 1 <=> 2 <=> 3
* ```
* @param start Start index
* @param end End index, optional
* The `slice` function returns a new SinglyLinkedList containing a portion of the original list, starting from the
* specified index and ending at the optional end index.
* @param {number} start - The `start` parameter is a number that represents the index at which to start slicing the
* linked list.
* @param {number} [end] - The `end` parameter is an optional number that specifies the index at which to end the
* slicing. If no value is provided for `end`, or if the provided value is less than the `start` index, the slicing
* will continue until the end of the list.
* @returns a new SinglyLinkedList containing the sliced elements from the original list.
*/
// eslint-disable-next-line @typescript-eslint/ban-types
public slice(start: number, end?: number): SinglyLinkedList<NodeData | {}> {
slice(start: number, end?: number): SinglyLinkedList<NodeVal | {}> {
const list = new SinglyLinkedList();
let finish = end;
@ -583,10 +559,10 @@ export class SinglyLinkedList<NodeData = any> {
return list;
}
if (finish === undefined || finish < start) {
finish = this.length;
finish = this.size;
}
let head: SinglyLinkedListNode<NodeData> | null | undefined = this.getNode(start);
let head: SinglyLinkedListNode<NodeVal> | null | undefined = this.getNode(start);
for (let i = 0; i < finish - start && head !== null && head !== undefined; i++) {
list.append(head.val);
head = head.next;
@ -595,13 +571,10 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* The reverse() function reverses the list in place and returns the list
* itself.
* ```ts
* new LinkedList(1, 2, 3).reverse(); // 3 <=> 2 <=> 1
* ```
* The reverse() function reverses the order of nodes in a singly linked list.
* @returns The reverse() method is returning the reversed SinglyLinkedList.
*/
public reverse(): SinglyLinkedList<NodeData> {
reverse(): SinglyLinkedList<NodeVal> {
let currentNode = this.head;
while (currentNode) {
const next = currentNode.next;
@ -616,67 +589,67 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* The forEach() method executes a provided function once for each list node.
* ```ts
* new LinkedList(1, 2, 3).forEach(val => log(val)); // 1 2 3
* ```
* @param f Function to execute for each element, taking up to three arguments.
* @param reverse Indicates if the list should be walked in reverse order, default is false
* The `forEach` function iterates over a singly linked list and applies a callback function to each node, either in
* forward or reverse order.
* @param callbackFn - A callback function that will be called for each element in the linked list. It takes three
* parameters:
* @param [reverse=false] - A boolean value indicating whether to iterate over the linked list in reverse order. If set
* to true, the iteration will start from the tail of the linked list and move towards the head. If set to false
* (default), the iteration will start from the head and move towards the tail.
*/
public forEach(f: (
forEach(callbackFn: (
data: any,
index: number,
list: SinglyLinkedList<NodeData>,
list: SinglyLinkedList<NodeVal>,
) => any, reverse = false): void {
let currentIndex = reverse ? this.length - 1 : 0;
let currentIndex = reverse ? this.size - 1 : 0;
let currentNode = reverse ? this.tail : this.head;
const modifier = reverse ? -1 : 1;
const nextNode = reverse ? 'prev' : 'next';
while (currentNode) {
f(currentNode.val, currentIndex, this);
callbackFn(currentNode.val, currentIndex, this);
currentNode = currentNode[nextNode];
currentIndex += modifier;
}
}
/**
* The map() method creates a new list with the results of
* calling a provided function on every node in the calling list.
* ```ts
* new LinkedList(1, 2, 3).map(val => val + 10); // 11 <=> 12 <=> 13
* ```
* @param f Function that produces an node of the new list, taking up to three arguments
* @param reverse Indicates if the list should be mapped in reverse order, default is false
* The map function takes a callback function and applies it to each element in the linked list, returning a new linked
* list with the results.
* @param callbackFn - A callback function that will be applied to each element in the linked list. It takes three
* parameters:
* @param [reverse=false] - The `reverse` parameter is a boolean value that determines whether the mapping should be
* done in reverse order or not. If `reverse` is set to `true`, the mapping will be done in reverse order. If `reverse`
* is set to `false` or not provided, the mapping will be
* @returns The `map` function is returning a new `SinglyLinkedList` object.
*/
// eslint-disable-next-line @typescript-eslint/ban-types
public map(f: (
map(callbackFn: (
data: any,
index: number,
list: SinglyLinkedList<NodeData>,
) => any, reverse = false): SinglyLinkedList<NodeData | {}> {
list: SinglyLinkedList<NodeVal>,
) => any, reverse = false): SinglyLinkedList<NodeVal | {}> {
const list = new SinglyLinkedList();
this.forEach((val, index) => list.append(f(val, index, this)), reverse);
this.forEach((val, index) => list.append(callbackFn(val, index, this)), reverse);
return list;
}
/**
* The filter() method creates a new list with all nodes
* that pass the test implemented by the provided function.
* ```ts
* new LinkedList(1, 2, 3, 4, 5).filter(val => val < 4); // 1 <=> 2 <=> 3
* ```
* @param f Function to test each node val in the list. Return true to keep the node
* @param reverse Indicates if the list should be filtered in reverse order, default is false
* The `filter` function filters the elements of a singly linked list based on a given callback function.
* @param callbackFn - A callback function that takes three parameters: data, index, and list. It should return a
* boolean value indicating whether the current element should be included in the filtered list or not.
* @param [reverse=false] - The `reverse` parameter is a boolean value that determines whether the filtered list should
* be reversed or not. If `reverse` is set to `true`, the filtered list will be in reverse order. If `reverse` is set
* to `false` or not provided, the filtered list will be in
* @returns The `filter` method is returning a new `SinglyLinkedList` object.
*/
// eslint-disable-next-line @typescript-eslint/ban-types
public filter(f: (
data: NodeData,
filter(callbackFn: (
data: NodeVal,
index: number,
list: SinglyLinkedList<NodeData>,
) => boolean, reverse = false): SinglyLinkedList<NodeData | {}> {
list: SinglyLinkedList<NodeVal>,
) => boolean, reverse = false): SinglyLinkedList<NodeVal | {}> {
const list = new SinglyLinkedList();
this.forEach((val, index) => {
if (f(val, index, this)) {
if (callbackFn(val, index, this)) {
list.append(val);
}
}, reverse);
@ -684,25 +657,30 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* Reduce over each node in the list
* ```ts
* new LinkedList(1, 2, 3).reduce(n => n += 1, 0); // 3
* ```
* @param f A reducer function
* @param start An initial value
* @returns The final state of the accumulator
* The `reduce` function iterates over a singly linked list and applies a callback function to each element,
* accumulating a single value.
* @param callbackFn - A callback function that will be called for each element in the linked list. It takes four
* parameters:
* @param {any} [start] - The `start` parameter is an optional initial value for the accumulator. If provided, the
* `reduce` function will start accumulating from this value. If not provided, the `reduce` function will use the value
* of the first element in the linked list as the initial value.
* @param [reverse=false] - A boolean value indicating whether to iterate over the linked list in reverse order. If set
* to true, the iteration will start from the tail of the linked list and move towards the head. If set to false
* (default), the iteration will start from the head and move towards the tail.
* @returns The `reduce` method returns the accumulated value after applying the callback function to each element in
* the linked list.
*/
public reduce(
f: (
reduce(
callbackFn: (
accumulator: any,
currentNode: NodeData,
currentNode: NodeVal,
index: number,
list: SinglyLinkedList<NodeData>,
list: SinglyLinkedList<NodeVal>,
) => any,
start?: any,
reverse = false,
): any {
let currentIndex = reverse ? this.length - 1 : 0;
let currentIndex = reverse ? this.size - 1 : 0;
const modifier = reverse ? -1 : 1;
const nextNode = reverse ? 'prev' : 'next';
let currentElement = reverse ? this.tail : this.head;
@ -718,7 +696,7 @@ export class SinglyLinkedList<NodeData = any> {
}
while (currentElement) {
result = f(result, currentElement.val, currentIndex, this);
result = callbackFn(result, currentElement.val, currentIndex, this);
currentIndex += modifier;
currentElement = currentElement[nextNode];
}
@ -727,34 +705,29 @@ export class SinglyLinkedList<NodeData = any> {
}
/**
* Convert the linked list to an array
* ```ts
* new LinkedList(1, 2, 3).toArray(); // [1, 2, 3]
* ```
* The toArray() function converts a NodeVal object into an array of NodeVal objects.
* @returns An array of NodeVal objects.
*/
public toArray(): NodeData[] {
toArray(): NodeVal[] {
return [...this];
}
/**
* Convert a linked list to string
* ```ts
* new LinkedList('one', 'two', 'three').toString(' <=> ') === 'one <=> two <=> three';
* ```
* @param separator Optional string to be placed in between val nodes, default is one space
* The `toString` function takes an optional separator and returns a string representation of an array, with each
* element separated by the specified separator.
* @param [separator= ] - The separator parameter is a string that specifies the character(s) to be used as a separator
* between each element in the array when converting it to a string. By default, the separator is set to a space
* character (' ').
* @returns The toString method is being returned as a string.
*/
public toString(separator = ' '): string {
toString(separator = ' '): string {
return this.reduce((s, val) => `${s}${separator}${val}`);
}
/**
* The iterator implementation
* ```ts
* const list = new LinkedList(1, 2, 3);
* for (const val of list) { log(val); } // 1 2 3
* ```
* The function is an iterator that returns the values of each node in a linked list.
*/
public* [Symbol.iterator](): IterableIterator<NodeData> {
public* [Symbol.iterator](): IterableIterator<NodeVal> {
let element = this.head;
while (element !== null) {
@ -763,8 +736,13 @@ export class SinglyLinkedList<NodeData = any> {
}
}
/** Private helper function to reduce duplication of pop() and shift() methods */
private removeFromAnyEnd(node: SinglyLinkedListNode<NodeData> | null) {
/**
* The function removes a node from either end of a singly linked list and returns its value.
* @param {SinglyLinkedListNode<NodeVal> | null} node - The `node` parameter is a reference to a node in a singly
* linked list. It can be either a `SinglyLinkedListNode` object or `null`.
* @returns The value of the removed node if the node is not null, otherwise undefined.
*/
protected removeFromAnyEnd(node: SinglyLinkedListNode<NodeVal> | null) {
return node !== null ? this.removeNode(node).val : undefined;
}
}

View file

@ -8,8 +8,21 @@
import type {PriorityQueueComparator, PriorityQueueDFSOrderPattern, PriorityQueueOptions} from '../types';
export class PriorityQueue<T = number> {
protected nodes: T[] = [];
protected _nodes: T[] = [];
get nodes(): T[] {
return this._nodes;
}
/**
* Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters.
*/
getNodes(): T[] {
return this._nodes;
}
protected set nodes(value: T[]) {
this._nodes = value;
}
/**
* The constructor initializes a priority queue with the given options, including an array of nodes and a comparator
* function.
@ -21,7 +34,7 @@ export class PriorityQueue<T = number> {
if (nodes && nodes instanceof Array && nodes.length > 0) {
// TODO support distinct
this.nodes = Array.isArray(nodes) ? [...nodes] : [];
this._nodes = Array.isArray(nodes) ? [...nodes] : [];
isFix && this._fix();
}
}

View file

@ -17,20 +17,50 @@ export class Deque<T> extends DoublyLinkedList<T> {
// O(n) time complexity of adding at the beginning and the end
// todo tested slowest one
export class ObjectDeque<T> {
protected _nodes: { [key: number]: T } = {};
protected _capacity = Number.MAX_SAFE_INTEGER;
protected _first: number = -1;
protected _last: number = -1;
protected _size: number = 0;
private _nodes: { [key: number]: T } = {};
get nodes(): { [p: number]: T } {
return this._nodes;
}
protected set nodes(value: { [p: number]: T }) {
this._nodes = value;
}
private _capacity = Number.MAX_SAFE_INTEGER;
get capacity(): number {
return this._capacity;
}
set capacity(value: number) {
this._capacity = value;
}
private _first: number = -1;
get first(): number {
return this._first;
}
set first(value: number) {
this._first = value;
}
private _last: number = -1;
get last(): number {
return this._last;
}
set last(value: number) {
this._last = value;
}
private _size: number = 0;
get size(): number {
return this._size;
}
protected set size(value: number) {
this._size = value;
}
constructor(capacity?: number) {
if (capacity !== undefined) this._capacity = capacity;
}
size() {
return this._size;
}
addFirst(value: T) {
if (this._size === 0) {
const mid = Math.floor(this._capacity / 2);

View file

@ -5,7 +5,7 @@ export type DijkstraResult<V> =
export interface IGraph<V, E> {
containsVertex(vertexOrId: V | VertexId): boolean;
hasVertex(vertexOrId: V | VertexId): boolean;
getVertex(vertexOrId: VertexId | V): V | null;
@ -23,9 +23,9 @@ export interface IGraph<V, E> {
edgesOf(vertexOrId: V | VertexId): E[];
containsEdge(src: V | VertexId, dest: V | VertexId): boolean;
hasEdge(src: V | VertexId, dest: V | VertexId): boolean;
// containsEdge(e: E): boolean;
// hasEdge(e: E): boolean;
getEdge(srcOrId: V | VertexId, destOrId: V | VertexId): E | null;

View file

@ -1,13 +1,37 @@
import { DirectedGraph, DirectedVertex, DirectedEdge } from '../../../../src';
import {DirectedEdge, DirectedGraph, DirectedVertex, VertexId} from '../../../../src';
// TODO too few unit tests
describe('DirectedGraph', () => {
class MyVertex extends DirectedVertex {
data: string;
constructor(id: VertexId, data: string) {
super(id);
this.data = data;
}
}
class MyEdge extends DirectedEdge {
data: string;
constructor(v1: VertexId, v2: VertexId, weight: number, data: string) {
super(v1, v2, weight);
this.data = data;
}
}
class MyGraph<V extends MyVertex, E extends MyEdge> extends DirectedGraph<V, E> {
constructor() {
super();
}
}
describe('DirectedGraph Test1', () => {
let graph: DirectedGraph<DirectedVertex, DirectedEdge>;
beforeEach(() => {
graph = new DirectedGraph();
});
it('should add vertices', () => {
const vertex1 = new DirectedVertex('A');
const vertex2 = new DirectedVertex('B');
@ -15,8 +39,8 @@ describe('DirectedGraph', () => {
graph.addVertex(vertex1);
graph.addVertex(vertex2);
expect(graph.containsVertex(vertex1)).toBe(true);
expect(graph.containsVertex(vertex2)).toBe(true);
expect(graph.hasVertex(vertex1)).toBe(true);
expect(graph.hasVertex(vertex2)).toBe(true);
});
it('should add edges', () => {
@ -28,8 +52,8 @@ describe('DirectedGraph', () => {
graph.addVertex(vertex2);
graph.addEdge(edge);
expect(graph.containsEdge('A', 'B')).toBe(true);
expect(graph.containsEdge('B', 'A')).toBe(false);
expect(graph.hasEdge('A', 'B')).toBe(true);
expect(graph.hasEdge('B', 'A')).toBe(false);
});
it('should remove edges', () => {
@ -42,7 +66,7 @@ describe('DirectedGraph', () => {
graph.addEdge(edge);
expect(graph.removeEdge(edge)).toBe(edge);
expect(graph.containsEdge('A', 'B')).toBe(false);
expect(graph.hasEdge('A', 'B')).toBe(false);
});
// Add more test cases for other methods...
@ -70,3 +94,402 @@ describe('DirectedGraph', () => {
// Add more test cases for other methods...
});
describe('DirectedGraph Test2 operations', () => {
const myGraph = new DirectedGraph<MyVertex, MyEdge>();
test('Add vertices', () => {
myGraph.addVertex(new MyVertex(1, 'data1'));
myGraph.addVertex(new MyVertex(2, 'data2'));
myGraph.addVertex(new MyVertex(3, 'data3'));
myGraph.addVertex(new MyVertex(4, 'data4'));
myGraph.addVertex(new MyVertex(5, 'data5'));
myGraph.addVertex(new MyVertex(6, 'data6'));
myGraph.addVertex(new MyVertex(7, 'data7'));
myGraph.addVertex(new MyVertex(8, 'data8'));
myGraph.addVertex(new MyVertex(9, 'data9'));
});
test('Add edges', () => {
myGraph.addVertex(new MyVertex(1, 'data1'));
myGraph.addVertex(new MyVertex(2, 'data2'));
myGraph.addEdge(new MyEdge(1, 2, 10, 'edge-data1-2'));
myGraph.addEdge(new MyEdge(2, 1, 20, 'edge-data2-1'));
expect(myGraph.edgeSet().length).toBe(2);
// TODO
expect(myGraph.getEdge(1, 2)).toBeInstanceOf(MyEdge);
expect(myGraph.getEdge(2, 1)).toBeInstanceOf(MyEdge);
});
test('Get edge', () => {
const edge1 = myGraph.getEdge(1, 2);
const edge2 = myGraph.getEdge(myGraph.getVertex(1), myGraph.getVertex(2));
const edge3 = myGraph.getEdge(1, '100');
expect(edge1).toBeInstanceOf(MyEdge);
edge1 && expect(edge1.src).toBe(1);
expect(edge1).toEqual(edge2);
expect(edge3).toBeNull();
});
test('Edge set and vertex set', () => {
const edges = myGraph.edgeSet();
const vertices = myGraph.vertexSet();
});
test('Remove edge between vertices', () => {
myGraph.addVertex(new MyVertex(1, 'data1'));
myGraph.addVertex(new MyVertex(2, 'data2'));
myGraph.addEdge(new MyEdge(1, 2, 10, 'edge-data1-2'));
const removedEdge = myGraph.removeEdgeBetween(1, 2);
const edgeAfterRemoval = myGraph.getEdge(1, 2);
expect(removedEdge).toBeInstanceOf(MyEdge);
if (removedEdge) {
removedEdge && expect(removedEdge.data).toBe('edge-data1-2');
removedEdge && expect(removedEdge.src).toBe(1)
}
expect(edgeAfterRemoval).toBeNull();
});
test('Topological sort', () => {
const sorted = myGraph.topologicalSort();
expect(sorted).toBeInstanceOf(Array);
if (sorted && sorted.length > 0) {
expect(sorted.length).toBe(9);
expect(sorted[0].data).toBe('data9');
expect(sorted[3].data).toBe('data6');
expect(sorted[8].id).toBe(1);
}
});
test('Minimum path between vertices', () => {
myGraph.addVertex(new MyVertex(1, 'data1'));
myGraph.addVertex(new MyVertex(2, 'data2'));
myGraph.addEdge(new MyEdge(1, 2, 10, 'edge-data1-2'));
const minPath = myGraph.getMinPathBetween(1, 2);
});
test('All paths between vertices', () => {
// Add vertices and edges as needed for this test
myGraph.addVertex(new MyVertex(1, 'data1'));
myGraph.addVertex(new MyVertex(2, 'data2'));
myGraph.addEdge(new MyEdge(1, 2, 10, 'edge-data1-2'));
const allPaths = myGraph.getAllPathsBetween(1, 2);
// Add expect statements here to verify the allPaths
});
});
describe('DirectedGraph Test3', () => {
const myGraph = new DirectedGraph<MyVertex, MyEdge>();
it('should test graph operations', () => {
const vertex1 = new MyVertex(1, 'data1');
const vertex2 = new MyVertex(2, 'data2');
const vertex3 = new MyVertex(3, 'data3');
const vertex4 = new MyVertex(4, 'data4');
const vertex5 = new MyVertex(5, 'data5');
const vertex6 = new MyVertex(6, 'data6');
const vertex7 = new MyVertex(7, 'data7');
const vertex8 = new MyVertex(8, 'data8');
const vertex9 = new MyVertex(9, 'data9');
myGraph.addVertex(vertex1);
myGraph.addVertex(vertex2);
myGraph.addVertex(vertex3);
myGraph.addVertex(vertex4);
myGraph.addVertex(vertex5);
myGraph.addVertex(vertex6);
myGraph.addVertex(vertex7);
myGraph.addVertex(vertex8);
myGraph.addVertex(vertex9);
myGraph.addEdge(new MyEdge(1, 2, 10, 'edge-data1-2'));
myGraph.addEdge(new MyEdge(2, 1, 20, 'edge-data2-1'));
expect(myGraph.getEdge(1, 2)).toBeTruthy();
expect(myGraph.getEdge(2, 1)).toBeTruthy();
expect(myGraph.getEdge(1, '100')).toBeFalsy();
// Add the rest of your assertions here...
myGraph.removeEdgeBetween(1, 2);
expect(myGraph.getEdge(1, 2)).toBeFalsy();
myGraph.addEdge(new MyEdge(3, 1, 3, 'edge-data-3-1'));
myGraph.addEdge(new MyEdge(1, 9, 19, 'edge-data1-9'));
myGraph.addEdge(new MyEdge(9, 7, 97, 'edge-data9-7'));
myGraph.addEdge(new MyEdge(7, 9, 79, 'edge-data7-9'));
myGraph.addEdge(new MyEdge(1, 4, 14, 'edge-data1-4'));
myGraph.addEdge(new MyEdge(4, 7, 47, 'edge-data4-7'));
myGraph.addEdge(new MyEdge(1, 2, 12, 'edge-data1-2'));
myGraph.addEdge(new MyEdge(2, 3, 23, 'edge-data2-3'));
myGraph.addEdge(new MyEdge(3, 5, 35, 'edge-data3-5'));
myGraph.addEdge(new MyEdge(5, 7, 57, 'edge-data5-7'));
myGraph.addEdge(new MyEdge(7, 3, 73, 'edge-data7-3'));
const topologicalSorted = myGraph.topologicalSort();
expect(topologicalSorted).toBeNull();
const minPath1to7 = myGraph.getMinPathBetween(1, 7);
expect(minPath1to7).toBeInstanceOf(Array);
if (minPath1to7 && minPath1to7.length > 0) {
expect(minPath1to7).toHaveLength(3);
expect(minPath1to7[0]).toBeInstanceOf(MyVertex);
expect(minPath1to7[0].id).toBe(1);
expect(minPath1to7[1].id).toBe(9);
expect(minPath1to7[2].id).toBe(7);
}
const fordResult1 = myGraph.bellmanFord(1);
expect(fordResult1).toBeTruthy();
expect(fordResult1.hasNegativeCycle).toBeUndefined();
const {distMap, preMap, paths, min, minPath} = fordResult1;
expect(distMap).toBeInstanceOf(Map);
expect(distMap.size).toBe(9);
expect(distMap.get(vertex1)).toBe(0);
expect(distMap.get(vertex2)).toBe(12);
expect(distMap.get(vertex3)).toBe(35);
expect(distMap.get(vertex4)).toBe(14);
expect(distMap.get(vertex5)).toBe(70);
expect(distMap.get(vertex6)).toBe(Infinity);
expect(distMap.get(vertex7)).toBe(61);
expect(distMap.get(vertex8)).toBe(Infinity);
expect(distMap.get(vertex9)).toBe(19);
expect(preMap).toBeInstanceOf(Map);
expect(preMap.size).toBe(0);
expect(paths).toBeInstanceOf(Array);
expect(paths.length).toBe(0);
expect(min).toBe(Infinity);
expect(minPath).toBeInstanceOf(Array);
const floydResult = myGraph.floyd();
expect(floydResult).toBeTruthy();
if (floydResult) {
const {costs, predecessor} = floydResult;
expect(costs).toBeInstanceOf(Array);
expect(costs.length).toBe(9);
expect(costs[0]).toEqual([32, 12, 35, 14, 70, Infinity, 61, Infinity, 19]);
expect(costs[1]).toEqual([20, 32, 23, 34, 58, Infinity, 81, Infinity, 39]);
expect(costs[2]).toEqual([3, 15, 38, 17, 35, Infinity, 64, Infinity, 22]);
expect(costs[3]).toEqual([123, 135, 120, 137, 155, Infinity, 47, Infinity, 126]);
expect(costs[4]).toEqual([133, 145, 130, 147, 165, Infinity, 57, Infinity, 136]);
expect(costs[5]).toEqual([Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity]);
expect(costs[6]).toEqual([76, 88, 73, 90, 108, Infinity, 137, Infinity, 79]);
expect(costs[7]).toEqual([Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity]);
expect(costs[8]).toEqual([173, 185, 170, 187, 205, Infinity, 97, Infinity, 176]);
expect(predecessor).toBeInstanceOf(Array);
expect(predecessor.length).toBe(9);
expect(predecessor[0]).toEqual([vertex2, null, vertex2, null, vertex3, null, vertex4, null, null]);
expect(predecessor[1]).toEqual([null, vertex1, null, vertex1, vertex3, null, vertex4, null, vertex1]);
expect(predecessor[5]).toEqual([null, null, null, null, null, null, null, null, null]);
expect(predecessor[7]).toEqual([null, null, null, null, null, null, null, null, null]);
expect(predecessor[8]).toEqual([vertex7, vertex7, vertex7, vertex7, vertex7, null, null, null, vertex7]);
}
const dijkstraRes12tt = myGraph.dijkstra(1, 2, true, true);
expect(dijkstraRes12tt).toBeTruthy();
if (dijkstraRes12tt) {
const {distMap, minDist, minPath, paths, preMap, seen} = dijkstraRes12tt;
expect(distMap).toBeInstanceOf(Map);
expect(distMap.size).toBe(9);
expect(distMap.get(vertex1)).toBe(0);
expect(distMap.get(vertex2)).toBe(12);
expect(distMap.get(vertex3)).toBe(Infinity);
expect(distMap.get(vertex4)).toBe(14);
expect(distMap.get(vertex5)).toBe(Infinity);
expect(distMap.get(vertex6)).toBe(Infinity);
expect(distMap.get(vertex7)).toBe(Infinity);
expect(distMap.get(vertex8)).toBe(Infinity);
expect(distMap.get(vertex9)).toBe(19);
expect(minDist).toBe(12);
expect(minPath).toBeInstanceOf(Array);
expect(minPath.length).toBe(2);
expect(minPath[0]).toBe(vertex1);
expect(minPath[1]).toBe(vertex2);
expect(paths).toBeInstanceOf(Array);
expect(paths.length).toBe(9);
expect(paths[0]).toBeInstanceOf(Array);
expect(paths[0][0]).toBe(vertex1);
expect(paths[1]).toBeInstanceOf(Array);
expect(paths[1][0]).toBe(vertex1);
expect(paths[1][1]).toBe(vertex2);
expect(paths[2]).toBeInstanceOf(Array);
expect(paths[2][0]).toBe(vertex3);
expect(paths[3]).toBeInstanceOf(Array);
expect(paths[3][0]).toBe(vertex1);
expect(paths[3][1]).toBe(vertex4);
expect(paths[4]).toBeInstanceOf(Array);
expect(paths[4][0]).toBe(vertex5);
expect(paths[5]).toBeInstanceOf(Array);
expect(paths[5][0]).toBe(vertex6);
expect(paths[6]).toBeInstanceOf(Array);
expect(paths[6][0]).toBe(vertex7);
expect(paths[7]).toBeInstanceOf(Array);
expect(paths[7][0]).toBe(vertex8);
expect(paths[8]).toBeInstanceOf(Array);
expect(paths[8][0]).toBe(vertex1);
expect(paths[8][1]).toBe(vertex9);
}
const dijkstraRes1ntt = myGraph.dijkstra(1, null, true, true);
expect(dijkstraRes1ntt).toBeTruthy();
if (dijkstraRes1ntt) {
const {distMap, minDist, minPath, paths, preMap, seen} = dijkstraRes1ntt;
expect(distMap).toBeInstanceOf(Map);
expect(distMap.size).toBe(9);
expect(distMap.get(vertex1)).toBe(0);
expect(distMap.get(vertex2)).toBe(12);
expect(distMap.get(vertex3)).toBe(35);
expect(distMap.get(vertex4)).toBe(14);
expect(distMap.get(vertex5)).toBe(70);
expect(distMap.get(vertex6)).toBe(Infinity);
expect(distMap.get(vertex7)).toBe(61);
expect(distMap.get(vertex8)).toBe(Infinity);
expect(distMap.get(vertex9)).toBe(19);
expect(minDist).toBe(12);
expect(minPath).toBeInstanceOf(Array);
expect(minPath.length).toBe(2);
expect(minPath[0]).toBe(vertex1);
expect(minPath[1]).toBe(vertex2);
expect(paths).toBeInstanceOf(Array);
expect(paths.length).toBe(9);
expect(paths[0]).toBeInstanceOf(Array);
expect(paths[0][0]).toBe(vertex1);
expect(paths[1]).toBeInstanceOf(Array);
expect(paths[1][0]).toBe(vertex1);
expect(paths[1][1]).toBe(vertex2);
expect(paths[2]).toBeInstanceOf(Array);
expect(paths[2][0]).toBe(vertex1);
expect(paths[2][1]).toBe(vertex2);
expect(paths[2][2]).toBe(vertex3);
expect(paths[3]).toBeInstanceOf(Array);
expect(paths[3][0]).toBe(vertex1);
expect(paths[3][1]).toBe(vertex4);
expect(paths[4]).toBeInstanceOf(Array);
expect(paths[4][0]).toBe(vertex1);
expect(paths[4][1]).toBe(vertex2);
expect(paths[4][2]).toBe(vertex3);
expect(paths[4][3]).toBe(vertex5);
expect(paths[5]).toBeInstanceOf(Array);
expect(paths[5][0]).toBe(vertex6);
expect(paths[6]).toBeInstanceOf(Array);
expect(paths[6][0]).toBe(vertex1);
expect(paths[6][1]).toBe(vertex4);
expect(paths[6][2]).toBe(vertex7);
expect(paths[7]).toBeInstanceOf(Array);
expect(paths[7][0]).toBe(vertex8);
expect(paths[8]).toBeInstanceOf(Array);
expect(paths[8][0]).toBe(vertex1);
expect(paths[8][1]).toBe(vertex9);
}
const dijkstraWithoutHeapRes1ntt = myGraph.dijkstraWithoutHeap(1, null, true, true);
expect(dijkstraWithoutHeapRes1ntt).toBeTruthy();
if (dijkstraWithoutHeapRes1ntt) {
const {distMap, minDist, minPath, paths, preMap, seen} = dijkstraWithoutHeapRes1ntt;
expect(distMap).toBeInstanceOf(Map);
expect(distMap.size).toBe(9);
expect(distMap.get(vertex1)).toBe(0);
expect(distMap.get(vertex2)).toBe(12);
expect(distMap.get(vertex3)).toBe(35);
expect(distMap.get(vertex4)).toBe(14);
expect(distMap.get(vertex5)).toBe(70);
expect(distMap.get(vertex6)).toBe(Infinity);
expect(distMap.get(vertex7)).toBe(61);
expect(distMap.get(vertex8)).toBe(Infinity);
expect(distMap.get(vertex9)).toBe(19);
expect(minDist).toBe(12);
expect(minPath).toBeInstanceOf(Array);
expect(minPath.length).toBe(2);
expect(minPath[0]).toBe(vertex1);
expect(minPath[1]).toBe(vertex2);
expect(paths).toBeInstanceOf(Array);
expect(paths.length).toBe(9);
expect(paths[0]).toBeInstanceOf(Array);
expect(paths[0][0]).toBe(vertex1);
expect(paths[1]).toBeInstanceOf(Array);
expect(paths[1][0]).toBe(vertex1);
expect(paths[1][1]).toBe(vertex2);
expect(paths[2]).toBeInstanceOf(Array);
expect(paths[2][0]).toBe(vertex1);
expect(paths[2][1]).toBe(vertex2);
expect(paths[2][2]).toBe(vertex3);
expect(paths[3]).toBeInstanceOf(Array);
expect(paths[3][0]).toBe(vertex1);
expect(paths[3][1]).toBe(vertex4);
expect(paths[4]).toBeInstanceOf(Array);
expect(paths[4][0]).toBe(vertex1);
expect(paths[4][1]).toBe(vertex2);
expect(paths[4][2]).toBe(vertex3);
expect(paths[4][3]).toBe(vertex5);
expect(paths[5]).toBeInstanceOf(Array);
expect(paths[5][0]).toBe(vertex6);
expect(paths[6]).toBeInstanceOf(Array);
expect(paths[6][0]).toBe(vertex1);
expect(paths[6][1]).toBe(vertex4);
expect(paths[6][2]).toBe(vertex7);
expect(paths[7]).toBeInstanceOf(Array);
expect(paths[7][0]).toBe(vertex8);
expect(paths[8]).toBeInstanceOf(Array);
expect(paths[8][0]).toBe(vertex1);
expect(paths[8][1]).toBe(vertex9);
}
});
});