mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
refactor: In Graph data structures, only use 'undefined' and abandon the design where both 'null' and 'undefined' coexist.
This commit is contained in:
parent
3dc0454c24
commit
f3df66eef3
30
CHANGELOG.md
30
CHANGELOG.md
|
@ -8,38 +8,28 @@ All notable changes to this project will be documented in this file.
|
|||
- [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
|
||||
- [`auto-changelog`](https://github.com/CookPete/auto-changelog)
|
||||
|
||||
## [v1.47.6](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
|
||||
## [v1.47.7](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
|
||||
|
||||
### Changes
|
||||
|
||||
- Rbtree [`#31`](https://github.com/zrwusa/data-structure-typed/pull/31)
|
||||
- [graph test] edge cases enriched [`#30`](https://github.com/zrwusa/data-structure-typed/pull/30)
|
||||
- [graph] Modify the data structure design of the graph to change the
|
||||
g… [`#29`](https://github.com/zrwusa/data-structure-typed/pull/29)
|
||||
- [graph] Modify the data structure design of the graph to change the g… [`#29`](https://github.com/zrwusa/data-structure-typed/pull/29)
|
||||
- Optimization [`#23`](https://github.com/zrwusa/data-structure-typed/pull/23)
|
||||
- Optimization [`#20`](https://github.com/zrwusa/data-structure-typed/pull/20)
|
||||
- [binary-tree, graph] Replace all code that uses Arrays as makeshift
|
||||
Q… [`#18`](https://github.com/zrwusa/data-structure-typed/pull/18)
|
||||
-
|
||||
1. No need for dfsIterative; integrate it directly into the dfs
|
||||
metho… [`#17`](https://github.com/zrwusa/data-structure-typed/pull/17)
|
||||
- [heap] fibonacci heap implemented. [test] big O estimate. [project]
|
||||
n… [`#15`](https://github.com/zrwusa/data-structure-typed/pull/15)
|
||||
- [binary-tree, graph] Replace all code that uses Arrays as makeshift Q… [`#18`](https://github.com/zrwusa/data-structure-typed/pull/18)
|
||||
- 1. No need for dfsIterative; integrate it directly into the dfs metho… [`#17`](https://github.com/zrwusa/data-structure-typed/pull/17)
|
||||
- [heap] fibonacci heap implemented. [test] big O estimate. [project] n… [`#15`](https://github.com/zrwusa/data-structure-typed/pull/15)
|
||||
- [rbtree] implemented, but with bugs [`#13`](https://github.com/zrwusa/data-structure-typed/pull/13)
|
||||
- [trie] renamed ambiguous methods and add comments to all
|
||||
methods. [`#12`](https://github.com/zrwusa/data-structure-typed/pull/12)
|
||||
- [binarytree] modified the getDepth method to adhere to the proper
|
||||
def… [`#11`](https://github.com/zrwusa/data-structure-typed/pull/11)
|
||||
- [trie] renamed ambiguous methods and add comments to all methods. [`#12`](https://github.com/zrwusa/data-structure-typed/pull/12)
|
||||
- [binarytree] modified the getDepth method to adhere to the proper def… [`#11`](https://github.com/zrwusa/data-structure-typed/pull/11)
|
||||
- Trie [`#10`](https://github.com/zrwusa/data-structure-typed/pull/10)
|
||||
- [tree] getHeight returns faulty height bug fixed [`#9`](https://github.com/zrwusa/data-structure-typed/pull/9)
|
||||
- [trie] support casesensitivity. getWords bug fixed [`#8`](https://github.com/zrwusa/data-structure-typed/pull/8)
|
||||
- [binary-tree, graph] In order to optimize the design of Binary
|
||||
Trees,… [`#7`](https://github.com/zrwusa/data-structure-typed/pull/7)
|
||||
- [BinaryTree, Heap] In abstract classes, only retain abstract
|
||||
methods.… [`#6`](https://github.com/zrwusa/data-structure-typed/pull/6)
|
||||
- [binary-tree, graph] In order to optimize the design of Binary Trees,… [`#7`](https://github.com/zrwusa/data-structure-typed/pull/7)
|
||||
- [BinaryTree, Heap] In abstract classes, only retain abstract methods.… [`#6`](https://github.com/zrwusa/data-structure-typed/pull/6)
|
||||
- [heap] test [`#5`](https://github.com/zrwusa/data-structure-typed/pull/5)
|
||||
- [heap, priority queue] Heap improved. References #123:
|
||||
redesigned [`#4`](https://github.com/zrwusa/data-structure-typed/pull/4)
|
||||
- [heap, priority queue] Heap improved. References #123: redesigned [`#4`](https://github.com/zrwusa/data-structure-typed/pull/4)
|
||||
- test [`#3`](https://github.com/zrwusa/data-structure-typed/pull/3)
|
||||
|
||||
## [v1.35.0](https://github.com/zrwusa/data-structure-typed/compare/v1.34.1...v1.35.0) (11 October 2023)
|
||||
|
|
|
@ -89,9 +89,9 @@ export abstract class AbstractGraph<
|
|||
*/
|
||||
abstract createEdge(srcOrV1: VertexKey, destOrV2: VertexKey, weight?: number, value?: E): EO;
|
||||
|
||||
abstract deleteEdge(edge: EO): EO | null;
|
||||
abstract deleteEdge(edge: EO): EO | undefined;
|
||||
|
||||
abstract getEdge(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | null;
|
||||
abstract getEdge(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | undefined;
|
||||
|
||||
abstract degreeOf(vertexOrKey: VO | VertexKey): number;
|
||||
|
||||
|
@ -101,7 +101,7 @@ export abstract class AbstractGraph<
|
|||
|
||||
abstract getNeighbors(vertexOrKey: VO | VertexKey): VO[];
|
||||
|
||||
abstract getEndsOfEdge(edge: EO): [VO, VO] | null;
|
||||
abstract getEndsOfEdge(edge: EO): [VO, VO] | undefined;
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1) - Constant time for Map lookup.
|
||||
|
@ -112,14 +112,14 @@ export abstract class AbstractGraph<
|
|||
* Time Complexity: O(1) - Constant time for Map lookup.
|
||||
* Space Complexity: O(1) - Constant space, as it creates only a few variables.
|
||||
*
|
||||
* The function "getVertex" returns the vertex with the specified ID or null if it doesn't exist.
|
||||
* The function "getVertex" returns the vertex with the specified ID or undefined if it doesn't exist.
|
||||
* @param {VertexKey} vertexKey - The `vertexKey` parameter is the identifier of the vertex that you want to retrieve from
|
||||
* the `_vertices` map.
|
||||
* @returns The method `getVertex` returns the vertex with the specified `vertexKey` if it exists in the `_vertices`
|
||||
* map. If the vertex does not exist, it returns `null`.
|
||||
* map. If the vertex does not exist, it returns `undefined`.
|
||||
*/
|
||||
getVertex(vertexKey: VertexKey): VO | null {
|
||||
return this._vertices.get(vertexKey) || null;
|
||||
getVertex(vertexKey: VertexKey): VO | undefined {
|
||||
return this._vertices.get(vertexKey) || undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -365,7 +365,7 @@ export abstract class AbstractGraph<
|
|||
* vertices. If `isWeight` is `false` or not provided, it uses a breadth-first search (BFS) algorithm to calculate the
|
||||
* minimum number of
|
||||
*/
|
||||
getMinCostBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean): number | null {
|
||||
getMinCostBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean): number | undefined {
|
||||
if (isWeight === undefined) isWeight = false;
|
||||
|
||||
if (isWeight) {
|
||||
|
@ -380,7 +380,7 @@ export abstract class AbstractGraph<
|
|||
const vertex2 = this._getVertex(v2);
|
||||
const vertex1 = this._getVertex(v1);
|
||||
if (!(vertex1 && vertex2)) {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const visited: Map<VO, boolean> = new Map();
|
||||
|
@ -406,7 +406,7 @@ export abstract class AbstractGraph<
|
|||
}
|
||||
cost++;
|
||||
}
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -432,9 +432,9 @@ export abstract class AbstractGraph<
|
|||
* followed by iterative computation of the shortest path. This approach may result in exponential time complexity,
|
||||
* so the default method is to use the Dijkstra algorithm to obtain the shortest weighted path.
|
||||
* @returns The function `getMinPathBetween` returns an array of vertices (`VO[]`) representing the minimum path between
|
||||
* two vertices (`v1` and `v2`). If there is no path between the vertices, it returns `null`.
|
||||
* two vertices (`v1` and `v2`). If there is no path between the vertices, it returns `undefined`.
|
||||
*/
|
||||
getMinPathBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean, isDFS = false): VO[] | null {
|
||||
getMinPathBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean, isDFS = false): VO[] | undefined {
|
||||
if (isWeight === undefined) isWeight = false;
|
||||
|
||||
if (isWeight) {
|
||||
|
@ -451,7 +451,7 @@ export abstract class AbstractGraph<
|
|||
}
|
||||
index++;
|
||||
}
|
||||
return allPaths[minIndex] || null;
|
||||
return allPaths[minIndex] || undefined;
|
||||
} else {
|
||||
return this.dijkstra(v1, v2, true, true)?.minPath ?? [];
|
||||
}
|
||||
|
@ -503,9 +503,9 @@ export abstract class AbstractGraph<
|
|||
* a graph without using a heap data structure.
|
||||
* @param {VO | VertexKey} src - The source vertex from which to start the Dijkstra's algorithm. It can be either a
|
||||
* vertex object or a vertex ID.
|
||||
* @param {VO | VertexKey | null} [dest] - The `dest` parameter in the `dijkstraWithoutHeap` function is an optional
|
||||
* @param {VO | VertexKey | undefined} [dest] - The `dest` parameter in the `dijkstraWithoutHeap` function is an optional
|
||||
* parameter that specifies the destination vertex for the Dijkstra algorithm. It can be either a vertex object or its
|
||||
* identifier. If no destination is provided, the value is set to `null`.
|
||||
* identifier. If no destination is provided, the value is set to `undefined`.
|
||||
* @param {boolean} [getMinDist] - The `getMinDist` parameter is a boolean flag that determines whether the minimum
|
||||
* distance from the source vertex to the destination vertex should be calculated and returned in the result. If
|
||||
* `getMinDist` is set to `true`, the `minDist` property in the result will contain the minimum distance
|
||||
|
@ -516,29 +516,29 @@ export abstract class AbstractGraph<
|
|||
*/
|
||||
dijkstraWithoutHeap(
|
||||
src: VO | VertexKey,
|
||||
dest?: VO | VertexKey | null,
|
||||
dest?: VO | VertexKey | undefined,
|
||||
getMinDist?: boolean,
|
||||
genPaths?: boolean
|
||||
): DijkstraResult<VO> {
|
||||
if (getMinDist === undefined) getMinDist = false;
|
||||
if (genPaths === undefined) genPaths = false;
|
||||
|
||||
if (dest === undefined) dest = null;
|
||||
if (dest === undefined) dest = undefined;
|
||||
let minDist = Infinity;
|
||||
let minDest: VO | null = null;
|
||||
let minDest: VO | undefined = undefined;
|
||||
let minPath: VO[] = [];
|
||||
const paths: VO[][] = [];
|
||||
|
||||
const vertices = this._vertices;
|
||||
const distMap: Map<VO, number> = new Map();
|
||||
const seen: Set<VO> = new Set();
|
||||
const preMap: Map<VO, VO | null> = new Map(); // predecessor
|
||||
const preMap: Map<VO, VO | undefined> = new Map(); // predecessor
|
||||
const srcVertex = this._getVertex(src);
|
||||
|
||||
const destVertex = dest ? this._getVertex(dest) : null;
|
||||
const destVertex = dest ? this._getVertex(dest) : undefined;
|
||||
|
||||
if (!srcVertex) {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
for (const vertex of vertices) {
|
||||
|
@ -546,11 +546,11 @@ export abstract class AbstractGraph<
|
|||
if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Infinity);
|
||||
}
|
||||
distMap.set(srcVertex, 0);
|
||||
preMap.set(srcVertex, null);
|
||||
preMap.set(srcVertex, undefined);
|
||||
|
||||
const getMinOfNoSeen = () => {
|
||||
let min = Infinity;
|
||||
let minV: VO | null = null;
|
||||
let minV: VO | undefined = undefined;
|
||||
for (const [key, value] of distMap) {
|
||||
if (!seen.has(key)) {
|
||||
if (value < min) {
|
||||
|
@ -562,7 +562,7 @@ export abstract class AbstractGraph<
|
|||
return minV;
|
||||
};
|
||||
|
||||
const getPaths = (minV: VO | null) => {
|
||||
const getPaths = (minV: VO | undefined) => {
|
||||
for (const vertex of vertices) {
|
||||
const vertexOrKey = vertex[1];
|
||||
|
||||
|
@ -600,7 +600,7 @@ export abstract class AbstractGraph<
|
|||
if (edge) {
|
||||
const curFromMap = distMap.get(cur);
|
||||
const neighborFromMap = distMap.get(neighbor);
|
||||
// TODO after no-non-null-assertion not ensure the logic
|
||||
// TODO after no-non-undefined-assertion not ensure the logic
|
||||
if (curFromMap !== undefined && neighborFromMap !== undefined) {
|
||||
if (edge.weight + curFromMap < neighborFromMap) {
|
||||
distMap.set(neighbor, edge.weight + curFromMap);
|
||||
|
@ -651,7 +651,7 @@ export abstract class AbstractGraph<
|
|||
* optional destination vertex, and optionally returns the minimum distance, the paths, and other information.
|
||||
* @param {VO | VertexKey} src - The `src` parameter represents the source vertex from which the Dijkstra algorithm will
|
||||
* start. It can be either a vertex object or a vertex ID.
|
||||
* @param {VO | VertexKey | null} [dest] - The `dest` parameter is the destination vertex or vertex ID. It specifies the
|
||||
* @param {VO | VertexKey | undefined} [dest] - The `dest` parameter is the destination vertex or vertex ID. It specifies the
|
||||
* vertex to which the shortest path is calculated from the source vertex. If no destination is provided, the algorithm
|
||||
* will calculate the shortest paths to all other vertices from the source vertex.
|
||||
* @param {boolean} [getMinDist] - The `getMinDist` parameter is a boolean flag that determines whether the minimum
|
||||
|
@ -664,27 +664,27 @@ export abstract class AbstractGraph<
|
|||
*/
|
||||
dijkstra(
|
||||
src: VO | VertexKey,
|
||||
dest?: VO | VertexKey | null,
|
||||
dest?: VO | VertexKey | undefined,
|
||||
getMinDist?: boolean,
|
||||
genPaths?: boolean
|
||||
): DijkstraResult<VO> {
|
||||
if (getMinDist === undefined) getMinDist = false;
|
||||
if (genPaths === undefined) genPaths = false;
|
||||
|
||||
if (dest === undefined) dest = null;
|
||||
if (dest === undefined) dest = undefined;
|
||||
let minDist = Infinity;
|
||||
let minDest: VO | null = null;
|
||||
let minDest: VO | undefined = undefined;
|
||||
let minPath: VO[] = [];
|
||||
const paths: VO[][] = [];
|
||||
const vertices = this._vertices;
|
||||
const distMap: Map<VO, number> = new Map();
|
||||
const seen: Set<VO> = new Set();
|
||||
const preMap: Map<VO, VO | null> = new Map(); // predecessor
|
||||
const preMap: Map<VO, VO | undefined> = new Map(); // predecessor
|
||||
|
||||
const srcVertex = this._getVertex(src);
|
||||
const destVertex = dest ? this._getVertex(dest) : null;
|
||||
const destVertex = dest ? this._getVertex(dest) : undefined;
|
||||
|
||||
if (!srcVertex) return null;
|
||||
if (!srcVertex) return undefined;
|
||||
|
||||
for (const vertex of vertices) {
|
||||
const vertexOrKey = vertex[1];
|
||||
|
@ -695,14 +695,14 @@ export abstract class AbstractGraph<
|
|||
heap.add({ key: 0, value: srcVertex });
|
||||
|
||||
distMap.set(srcVertex, 0);
|
||||
preMap.set(srcVertex, null);
|
||||
preMap.set(srcVertex, undefined);
|
||||
|
||||
/**
|
||||
* The function `getPaths` retrieves all paths from vertices to a specified minimum vertex.
|
||||
* @param {VO | null} minV - The parameter `minV` is of type `VO | null`. It represents the minimum vertex value or
|
||||
* null.
|
||||
* @param {VO | undefined} minV - The parameter `minV` is of type `VO | undefined`. It represents the minimum vertex value or
|
||||
* undefined.
|
||||
*/
|
||||
const getPaths = (minV: VO | null) => {
|
||||
const getPaths = (minV: VO | undefined) => {
|
||||
for (const vertex of vertices) {
|
||||
const vertexOrKey = vertex[1];
|
||||
if (vertexOrKey instanceof AbstractVertex) {
|
||||
|
@ -841,7 +841,7 @@ export abstract class AbstractGraph<
|
|||
}
|
||||
}
|
||||
|
||||
let minDest: VO | null = null;
|
||||
let minDest: VO | undefined = undefined;
|
||||
if (getMin) {
|
||||
distMap.forEach((d, v) => {
|
||||
if (v !== srcVertex) {
|
||||
|
@ -920,22 +920,22 @@ export abstract class AbstractGraph<
|
|||
* graph.
|
||||
* @returns The function `floydWarshall()` returns an object with two properties: `costs` and `predecessor`. The `costs`
|
||||
* property is a 2D array of numbers representing the shortest path costs between vertices in a graph. The
|
||||
* `predecessor` property is a 2D array of vertices (or `null`) representing the predecessor vertices in the shortest
|
||||
* `predecessor` property is a 2D array of vertices (or `undefined`) representing the predecessor vertices in the shortest
|
||||
* path between vertices in the
|
||||
*/
|
||||
floydWarshall(): { costs: number[][]; predecessor: (VO | null)[][] } {
|
||||
floydWarshall(): { costs: number[][]; predecessor: (VO | undefined)[][] } {
|
||||
const idAndVertices = [...this._vertices];
|
||||
const n = idAndVertices.length;
|
||||
|
||||
const costs: number[][] = [];
|
||||
const predecessor: (VO | null)[][] = [];
|
||||
const predecessor: (VO | undefined)[][] = [];
|
||||
// successors
|
||||
|
||||
for (let i = 0; i < n; i++) {
|
||||
costs[i] = [];
|
||||
predecessor[i] = [];
|
||||
for (let j = 0; j < n; j++) {
|
||||
predecessor[i][j] = null;
|
||||
predecessor[i][j] = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1021,7 +1021,7 @@ export abstract class AbstractGraph<
|
|||
const cutVertexes: VO[] = [];
|
||||
const bridges: EO[] = [];
|
||||
let dfn = 0;
|
||||
const dfs = (cur: VO, parent: VO | null) => {
|
||||
const dfs = (cur: VO, parent: VO | undefined) => {
|
||||
dfn++;
|
||||
dfnMap.set(cur, dfn);
|
||||
lowMap.set(cur, dfn);
|
||||
|
@ -1036,7 +1036,7 @@ export abstract class AbstractGraph<
|
|||
}
|
||||
const childLow = lowMap.get(neighbor);
|
||||
const curLow = lowMap.get(cur);
|
||||
// TODO after no-non-null-assertion not ensure the logic
|
||||
// TODO after no-non-undefined-assertion not ensure the logic
|
||||
if (curLow !== undefined && childLow !== undefined) {
|
||||
lowMap.set(cur, Math.min(curLow, childLow));
|
||||
}
|
||||
|
@ -1062,7 +1062,7 @@ export abstract class AbstractGraph<
|
|||
}
|
||||
};
|
||||
|
||||
dfs(root, null);
|
||||
dfs(root, undefined);
|
||||
|
||||
let SCCs: Map<number, VO[]> = new Map();
|
||||
|
||||
|
@ -1170,9 +1170,9 @@ export abstract class AbstractGraph<
|
|||
return true;
|
||||
}
|
||||
|
||||
protected _getVertex(vertexOrKey: VertexKey | VO): VO | null {
|
||||
protected _getVertex(vertexOrKey: VertexKey | VO): VO | undefined {
|
||||
const vertexKey = this._getVertexKey(vertexOrKey);
|
||||
return this._vertices.get(vertexKey) || null;
|
||||
return this._vertices.get(vertexKey) || undefined;
|
||||
}
|
||||
|
||||
protected _getVertexKey(vertexOrKey: VO | VertexKey): VertexKey {
|
||||
|
|
|
@ -119,18 +119,18 @@ export class DirectedGraph<
|
|||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `getEdge` function retrieves an edge between two vertices based on their source and destination IDs.
|
||||
* @param {VO | VertexKey | null} srcOrKey - The source vertex or its ID. It can be either a vertex object or a vertex ID.
|
||||
* @param {VO | VertexKey | null} destOrKey - The `destOrKey` parameter in the `getEdge` function represents the
|
||||
* destination vertex of the edge. It can be either a vertex object (`VO`), a vertex ID (`VertexKey`), or `null` if the
|
||||
* @param {VO | VertexKey | undefined} srcOrKey - The source vertex or its ID. It can be either a vertex object or a vertex ID.
|
||||
* @param {VO | VertexKey | undefined} destOrKey - The `destOrKey` parameter in the `getEdge` function represents the
|
||||
* destination vertex of the edge. It can be either a vertex object (`VO`), a vertex ID (`VertexKey`), or `undefined` if the
|
||||
* destination is not specified.
|
||||
* @returns the first edge found between the source and destination vertices, or null if no such edge is found.
|
||||
* @returns the first edge found between the source and destination vertices, or undefined if no such edge is found.
|
||||
*/
|
||||
getEdge(srcOrKey: VO | VertexKey | null, destOrKey: VO | VertexKey | null): EO | null {
|
||||
getEdge(srcOrKey: VO | VertexKey | undefined, destOrKey: VO | VertexKey | undefined): EO | undefined {
|
||||
let edges: EO[] = [];
|
||||
|
||||
if (srcOrKey !== null && destOrKey !== null) {
|
||||
const src: VO | null = this._getVertex(srcOrKey);
|
||||
const dest: VO | null = this._getVertex(destOrKey);
|
||||
if (srcOrKey !== undefined && destOrKey !== undefined) {
|
||||
const src: VO | undefined = this._getVertex(srcOrKey);
|
||||
const dest: VO | undefined = this._getVertex(destOrKey);
|
||||
|
||||
if (src && dest) {
|
||||
const srcOutEdges = this._outEdgeMap.get(src);
|
||||
|
@ -140,7 +140,7 @@ export class DirectedGraph<
|
|||
}
|
||||
}
|
||||
|
||||
return edges[0] || null;
|
||||
return edges[0] || undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,14 +155,14 @@ export class DirectedGraph<
|
|||
* The function removes an edge between two vertices in a graph and returns the removed edge.
|
||||
* @param {VO | VertexKey} srcOrKey - The source vertex or its ID.
|
||||
* @param {VO | VertexKey} destOrKey - The `destOrKey` parameter represents the destination vertex or its ID.
|
||||
* @returns the removed edge (EO) if it exists, or null if either the source or destination vertex does not exist.
|
||||
* @returns the removed edge (EO) if it exists, or undefined if either the source or destination vertex does not exist.
|
||||
*/
|
||||
deleteEdgeSrcToDest(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | null {
|
||||
const src: VO | null = this._getVertex(srcOrKey);
|
||||
const dest: VO | null = this._getVertex(destOrKey);
|
||||
let removed: EO | null = null;
|
||||
deleteEdgeSrcToDest(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | undefined {
|
||||
const src: VO | undefined = this._getVertex(srcOrKey);
|
||||
const dest: VO | undefined = this._getVertex(destOrKey);
|
||||
let removed: EO | undefined = undefined;
|
||||
if (!src || !dest) {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const srcOutEdges = this._outEdgeMap.get(src);
|
||||
|
@ -172,7 +172,7 @@ export class DirectedGraph<
|
|||
|
||||
const destInEdges = this._inEdgeMap.get(dest);
|
||||
if (destInEdges) {
|
||||
removed = arrayRemove<EO>(destInEdges, (edge: EO) => edge.src === src.key)[0] || null;
|
||||
removed = arrayRemove<EO>(destInEdges, (edge: EO) => edge.src === src.key)[0] || undefined;
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
@ -186,13 +186,13 @@ export class DirectedGraph<
|
|||
* Time Complexity: O(|E|) where |E| is the number of edges
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function removes an edge from a graph and returns the removed edge, or null if the edge was not found.
|
||||
* The function removes an edge from a graph and returns the removed edge, or undefined if the edge was not found.
|
||||
* @param {EO} edge - The `edge` parameter is an object that represents an edge in a graph. It has two properties: `src`
|
||||
* and `dest`, which represent the source and destination vertices of the edge, respectively.
|
||||
* @returns The method `deleteEdge` returns the removed edge (`EO`) if it exists, or `null` if the edge does not exist.
|
||||
* @returns The method `deleteEdge` returns the removed edge (`EO`) if it exists, or `undefined` if the edge does not exist.
|
||||
*/
|
||||
deleteEdge(edge: EO): EO | null {
|
||||
let removed: EO | null = null;
|
||||
deleteEdge(edge: EO): EO | undefined {
|
||||
let removed: EO | undefined = undefined;
|
||||
const src = this._getVertex(edge.src);
|
||||
const dest = this._getVertex(edge.dest);
|
||||
if (src && dest) {
|
||||
|
@ -361,11 +361,11 @@ export class DirectedGraph<
|
|||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function "getEdgeSrc" returns the source vertex of an edge, or null if the edge does not exist.
|
||||
* The function "getEdgeSrc" returns the source vertex of an edge, or undefined if the edge does not exist.
|
||||
* @param {EO} e - The parameter "e" is of type EO, which represents an edge in a graph.
|
||||
* @returns either a vertex object (VO) or null.
|
||||
* @returns either a vertex object (VO) or undefined.
|
||||
*/
|
||||
getEdgeSrc(e: EO): VO | null {
|
||||
getEdgeSrc(e: EO): VO | undefined {
|
||||
return this._getVertex(e.src);
|
||||
}
|
||||
|
||||
|
@ -380,9 +380,9 @@ export class DirectedGraph<
|
|||
*
|
||||
* The function "getEdgeDest" returns the destination vertex of an edge.
|
||||
* @param {EO} e - The parameter "e" is of type "EO", which represents an edge in a graph.
|
||||
* @returns either a vertex object of type VO or null.
|
||||
* @returns either a vertex object of type VO or undefined.
|
||||
*/
|
||||
getEdgeDest(e: EO): VO | null {
|
||||
getEdgeDest(e: EO): VO | undefined {
|
||||
return this._getVertex(e.dest);
|
||||
}
|
||||
|
||||
|
@ -396,12 +396,12 @@ export class DirectedGraph<
|
|||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function `getDestinations` returns an array of destination vertices connected to a given vertex.
|
||||
* @param {VO | VertexKey | null} vertex - The `vertex` parameter represents the starting vertex from which we want to
|
||||
* find the destinations. It can be either a `VO` object, a `VertexKey` value, or `null`.
|
||||
* @param {VO | VertexKey | undefined} vertex - The `vertex` parameter represents the starting vertex from which we want to
|
||||
* find the destinations. It can be either a `VO` object, a `VertexKey` value, or `undefined`.
|
||||
* @returns an array of vertices (VO[]).
|
||||
*/
|
||||
getDestinations(vertex: VO | VertexKey | null): VO[] {
|
||||
if (vertex === null) {
|
||||
getDestinations(vertex: VO | VertexKey | undefined): VO[] {
|
||||
if (vertex === undefined) {
|
||||
return [];
|
||||
}
|
||||
const destinations: VO[] = [];
|
||||
|
@ -425,13 +425,13 @@ export class DirectedGraph<
|
|||
* Space Complexity: O(|V|)
|
||||
*
|
||||
* The `topologicalSort` function performs a topological sort on a graph and returns an array of vertices or vertex IDs
|
||||
* in the sorted order, or null if the graph contains a cycle.
|
||||
* in the sorted order, or undefined if the graph contains a cycle.
|
||||
* @param {'vertex' | 'key'} [propertyName] - The `propertyName` parameter is an optional parameter that specifies the
|
||||
* property to use for sorting the vertices. It can have two possible values: 'vertex' or 'key'. If 'vertex' is
|
||||
* specified, the vertices themselves will be used for sorting. If 'key' is specified, the ids of
|
||||
* @returns an array of vertices or vertex IDs in topological order. If there is a cycle in the graph, it returns null.
|
||||
* @returns an array of vertices or vertex IDs in topological order. If there is a cycle in the graph, it returns undefined.
|
||||
*/
|
||||
topologicalSort(propertyName?: 'vertex' | 'key'): Array<VO | VertexKey> | null {
|
||||
topologicalSort(propertyName?: 'vertex' | 'key'): Array<VO | VertexKey> | undefined {
|
||||
propertyName = propertyName ?? 'key';
|
||||
// When judging whether there is a cycle in the undirected graph, all nodes with degree of **<= 1** are enqueued
|
||||
// When judging whether there is a cycle in the directed graph, all nodes with **in degree = 0** are enqueued
|
||||
|
@ -463,7 +463,7 @@ export class DirectedGraph<
|
|||
}
|
||||
}
|
||||
|
||||
if (hasCycle) return null;
|
||||
if (hasCycle) return undefined;
|
||||
|
||||
if (propertyName === 'key') sorted = sorted.map(vertex => (vertex instanceof DirectedVertex ? vertex.key : vertex));
|
||||
return sorted.reverse();
|
||||
|
@ -510,7 +510,7 @@ export class DirectedGraph<
|
|||
const outEdges = this.outgoingEdgesOf(vertex);
|
||||
for (const outEdge of outEdges) {
|
||||
const neighbor = this._getVertex(outEdge.dest);
|
||||
// TODO after no-non-null-assertion not ensure the logic
|
||||
// TODO after no-non-undefined-assertion not ensure the logic
|
||||
if (neighbor) {
|
||||
neighbors.push(neighbor);
|
||||
}
|
||||
|
@ -529,21 +529,21 @@ export class DirectedGraph<
|
|||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function "getEndsOfEdge" returns the source and destination vertices of an edge if it exists in the graph,
|
||||
* otherwise it returns null.
|
||||
* otherwise it returns undefined.
|
||||
* @param {EO} edge - The parameter `edge` is of type `EO`, which represents an edge in a graph.
|
||||
* @returns The function `getEndsOfEdge` returns an array containing two vertices `[VO, VO]` if the edge exists in the
|
||||
* graph. If the edge does not exist, it returns `null`.
|
||||
* graph. If the edge does not exist, it returns `undefined`.
|
||||
*/
|
||||
getEndsOfEdge(edge: EO): [VO, VO] | null {
|
||||
getEndsOfEdge(edge: EO): [VO, VO] | undefined {
|
||||
if (!this.hasEdge(edge.src, edge.dest)) {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
const v1 = this._getVertex(edge.src);
|
||||
const v2 = this._getVertex(edge.dest);
|
||||
if (v1 && v2) {
|
||||
return [v1, v2];
|
||||
} else {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -570,7 +570,7 @@ export class DirectedGraph<
|
|||
const srcVertex = this._getVertex(edge.src);
|
||||
const destVertex = this._getVertex(edge.dest);
|
||||
|
||||
// TODO after no-non-null-assertion not ensure the logic
|
||||
// TODO after no-non-undefined-assertion not ensure the logic
|
||||
if (srcVertex && destVertex) {
|
||||
const srcOutEdges = this._outEdgeMap.get(srcVertex);
|
||||
if (srcOutEdges) {
|
||||
|
|
|
@ -100,26 +100,26 @@ export class UndirectedGraph<
|
|||
* Time Complexity: O(|E|), where |E| is the number of edges incident to the given vertex.
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function `getEdge` returns the first edge that connects two vertices, or null if no such edge exists.
|
||||
* @param {VO | VertexKey | null} v1 - The parameter `v1` represents a vertex or vertex ID. It can be of type `VO` (vertex
|
||||
* object), `null`, or `VertexKey` (a string or number representing the ID of a vertex).
|
||||
* @param {VO | VertexKey | null} v2 - The parameter `v2` represents a vertex or vertex ID. It can be of type `VO` (vertex
|
||||
* object), `null`, or `VertexKey` (vertex ID).
|
||||
* @returns an edge (EO) or null.
|
||||
* The function `getEdge` returns the first edge that connects two vertices, or undefined if no such edge exists.
|
||||
* @param {VO | VertexKey | undefined} v1 - The parameter `v1` represents a vertex or vertex ID. It can be of type `VO` (vertex
|
||||
* object), `undefined`, or `VertexKey` (a string or number representing the ID of a vertex).
|
||||
* @param {VO | VertexKey | undefined} v2 - The parameter `v2` represents a vertex or vertex ID. It can be of type `VO` (vertex
|
||||
* object), `undefined`, or `VertexKey` (vertex ID).
|
||||
* @returns an edge (EO) or undefined.
|
||||
*/
|
||||
getEdge(v1: VO | VertexKey | null, v2: VO | VertexKey | null): EO | null {
|
||||
getEdge(v1: VO | VertexKey | undefined, v2: VO | VertexKey | undefined): EO | undefined {
|
||||
let edges: EO[] | undefined = [];
|
||||
|
||||
if (v1 !== null && v2 !== null) {
|
||||
const vertex1: VO | null = this._getVertex(v1);
|
||||
const vertex2: VO | null = this._getVertex(v2);
|
||||
if (v1 !== undefined && v2 !== undefined) {
|
||||
const vertex1: VO | undefined = this._getVertex(v1);
|
||||
const vertex2: VO | undefined = this._getVertex(v2);
|
||||
|
||||
if (vertex1 && vertex2) {
|
||||
edges = this._edges.get(vertex1)?.filter(e => e.vertices.includes(vertex2.key));
|
||||
}
|
||||
}
|
||||
|
||||
return edges ? edges[0] || null : null;
|
||||
return edges ? edges[0] || undefined : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,20 +135,20 @@ export class UndirectedGraph<
|
|||
* @param {VO | VertexKey} v1 - The parameter `v1` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).
|
||||
* @param {VO | VertexKey} v2 - VO | VertexKey - This parameter can be either a vertex object (VO) or a vertex ID
|
||||
* (VertexKey). It represents the second vertex of the edge that needs to be removed.
|
||||
* @returns the removed edge (EO) if it exists, or null if either of the vertices (VO) does not exist.
|
||||
* @returns the removed edge (EO) if it exists, or undefined if either of the vertices (VO) does not exist.
|
||||
*/
|
||||
deleteEdgeBetween(v1: VO | VertexKey, v2: VO | VertexKey): EO | null {
|
||||
const vertex1: VO | null = this._getVertex(v1);
|
||||
const vertex2: VO | null = this._getVertex(v2);
|
||||
deleteEdgeBetween(v1: VO | VertexKey, v2: VO | VertexKey): EO | undefined {
|
||||
const vertex1: VO | undefined = this._getVertex(v1);
|
||||
const vertex2: VO | undefined = this._getVertex(v2);
|
||||
|
||||
if (!vertex1 || !vertex2) {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const v1Edges = this._edges.get(vertex1);
|
||||
let removed: EO | null = null;
|
||||
let removed: EO | undefined = undefined;
|
||||
if (v1Edges) {
|
||||
removed = arrayRemove<EO>(v1Edges, (e: EO) => e.vertices.includes(vertex2.key))[0] || null;
|
||||
removed = arrayRemove<EO>(v1Edges, (e: EO) => e.vertices.includes(vertex2.key))[0] || undefined;
|
||||
}
|
||||
const v2Edges = this._edges.get(vertex2);
|
||||
if (v2Edges) {
|
||||
|
@ -168,9 +168,9 @@ export class UndirectedGraph<
|
|||
*
|
||||
* The deleteEdge function removes an edge between two vertices in a graph.
|
||||
* @param {EO} edge - The parameter "edge" is of type EO, which represents an edge in a graph.
|
||||
* @returns The method is returning either the removed edge (of type EO) or null if the edge was not found.
|
||||
* @returns The method is returning either the removed edge (of type EO) or undefined if the edge was not found.
|
||||
*/
|
||||
deleteEdge(edge: EO): EO | null {
|
||||
deleteEdge(edge: EO): EO | undefined {
|
||||
return this.deleteEdgeBetween(edge.vertices[0], edge.vertices[1]);
|
||||
}
|
||||
|
||||
|
@ -282,21 +282,21 @@ export class UndirectedGraph<
|
|||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function "getEndsOfEdge" returns the vertices at the ends of an edge if the edge exists in the graph, otherwise
|
||||
* it returns null.
|
||||
* it returns undefined.
|
||||
* @param {EO} edge - The parameter "edge" is of type EO, which represents an edge in a graph.
|
||||
* @returns The function `getEndsOfEdge` returns an array containing two vertices `[VO, VO]` if the edge exists in the
|
||||
* graph. If the edge does not exist, it returns `null`.
|
||||
* graph. If the edge does not exist, it returns `undefined`.
|
||||
*/
|
||||
getEndsOfEdge(edge: EO): [VO, VO] | null {
|
||||
getEndsOfEdge(edge: EO): [VO, VO] | undefined {
|
||||
if (!this.hasEdge(edge.vertices[0], edge.vertices[1])) {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
const v1 = this._getVertex(edge.vertices[0]);
|
||||
const v2 = this._getVertex(edge.vertices[1]);
|
||||
if (v1 && v2) {
|
||||
return [v1, v2];
|
||||
} else {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,7 +316,7 @@ export class UndirectedGraph<
|
|||
protected _addEdgeOnly(edge: EO): boolean {
|
||||
for (const end of edge.vertices) {
|
||||
const endVertex = this._getVertex(end);
|
||||
if (endVertex === null) return false;
|
||||
if (endVertex === undefined) return false;
|
||||
if (endVertex) {
|
||||
const edges = this._edges.get(endVertex);
|
||||
if (edges) {
|
||||
|
|
|
@ -3,9 +3,9 @@ export type VertexKey = string | number;
|
|||
export type DijkstraResult<V> = {
|
||||
distMap: Map<V, number>;
|
||||
distPaths?: Map<V, V[]>;
|
||||
preMap: Map<V, V | null>;
|
||||
preMap: Map<V, V | undefined>;
|
||||
seen: Set<V>;
|
||||
paths: V[][];
|
||||
minDist: number;
|
||||
minPath: V[];
|
||||
} | null;
|
||||
} | undefined;
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
<meta charset='UTF-8'>
|
||||
<title>CDN Test</title>
|
||||
<!-- <script src="../../dist/umd/data-structure-typed.min.js"></script>-->
|
||||
<script src="../../dist/umd/data-structure-typed.js"></script>
|
||||
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed/dist/umd/data-structure-typed.min.js'></script>-->
|
||||
<!-- <script src="../../dist/umd/data-structure-typed.js"></script>-->
|
||||
<script src='https://cdn.jsdelivr.net/npm/data-structure-typed/dist/umd/data-structure-typed.min.js'></script>
|
||||
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed@1.42.2/dist/umd/data-structure-typed.min.js'></script>-->
|
||||
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed@1.43.3/dist/umd/data-structure-typed.min.js'></script>-->
|
||||
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed@1.44.0/dist/umd/data-structure-typed.min.js'></script>-->
|
||||
|
@ -215,25 +215,25 @@
|
|||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const {
|
||||
const {
|
||||
AVLTree,
|
||||
BinaryTree,
|
||||
BST,
|
||||
Deque,
|
||||
DoublyLinkedList,
|
||||
HashMap,
|
||||
Heap,
|
||||
MaxPriorityQueue,
|
||||
MinHeap,
|
||||
MinPriorityQueue,
|
||||
Queue,
|
||||
RedBlackTree,
|
||||
SinglyLinkedList,
|
||||
Stack,
|
||||
TreeMultimap,
|
||||
Trie
|
||||
BinaryTree,
|
||||
BST,
|
||||
Deque,
|
||||
DoublyLinkedList,
|
||||
HashMap,
|
||||
Heap,
|
||||
MaxPriorityQueue,
|
||||
MinHeap,
|
||||
MinPriorityQueue,
|
||||
Queue,
|
||||
RedBlackTree,
|
||||
SinglyLinkedList,
|
||||
Stack,
|
||||
TreeMultimap,
|
||||
Trie
|
||||
} = dataStructureTyped;
|
||||
const orgArr = [6, 1, 2, 7, 5, 3, 4, 9, 8];
|
||||
const orgStrArr = ["trie", "trial", "trick", "trip", "tree", "trend", "triangle", "track", "trace", "transmit"];
|
||||
|
@ -299,7 +299,7 @@
|
|||
const entries2 = dq2.map((el, i) => [i, el]);
|
||||
const avl2 = new AVLTree(entries2);
|
||||
avl2.print();
|
||||
} catch (e) {
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -196,7 +196,7 @@ describe('Inherit from DirectedGraph and perform operations', () => {
|
|||
expect(edge1).toBeInstanceOf(MyEdge);
|
||||
expect(edge1.src).toBe(1);
|
||||
expect(edge1).toEqual(edge2);
|
||||
expect(edge3).toBeNull();
|
||||
expect(edge3).toBe(undefined);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -217,7 +217,7 @@ describe('Inherit from DirectedGraph and perform operations', () => {
|
|||
removedEdge && expect(removedEdge.value).toBe('edge-data1-2');
|
||||
removedEdge && expect(removedEdge.src).toBe(1);
|
||||
}
|
||||
expect(edgeAfterRemoval).toBeNull();
|
||||
expect(edgeAfterRemoval).toBe(undefined);
|
||||
});
|
||||
|
||||
it('Topological sort', () => {
|
||||
|
@ -303,7 +303,7 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|||
|
||||
myGraph.addEdge(new MyEdge(7, 3, 73, 'edge-data7-3'));
|
||||
const topologicalSorted = myGraph.topologicalSort();
|
||||
expect(topologicalSorted).toBeNull();
|
||||
expect(topologicalSorted).toBe(undefined);
|
||||
|
||||
const minPath1to7 = myGraph.getMinPathBetween(1, 7);
|
||||
|
||||
|
@ -378,11 +378,11 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|||
|
||||
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]);
|
||||
expect(predecessor[0]).toEqual([vertex2, undefined, vertex2, undefined, vertex3, undefined, vertex4, undefined, undefined]);
|
||||
expect(predecessor[1]).toEqual([undefined, vertex1, undefined, vertex1, vertex3, undefined, vertex4, undefined, vertex1]);
|
||||
expect(predecessor[5]).toEqual([undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]);
|
||||
expect(predecessor[7]).toEqual([undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]);
|
||||
expect(predecessor[8]).toEqual([vertex7, vertex7, vertex7, vertex7, vertex7, undefined, undefined, undefined, vertex7]);
|
||||
}
|
||||
|
||||
const dijkstraRes12tt = myGraph.dijkstra(1, 2, true, true);
|
||||
|
@ -436,7 +436,7 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|||
expect(paths[8][1]).toBe(vertex9);
|
||||
}
|
||||
|
||||
const dijkstraRes1ntt = myGraph.dijkstra(1, null, true, true);
|
||||
const dijkstraRes1ntt = myGraph.dijkstra(1, undefined, true, true);
|
||||
|
||||
expect(dijkstraRes1ntt).toBeTruthy();
|
||||
if (dijkstraRes1ntt) {
|
||||
|
@ -499,7 +499,7 @@ describe('Inherit from DirectedGraph and perform operations test2.', () => {
|
|||
expect(paths[8][1]).toBe(vertex9);
|
||||
}
|
||||
|
||||
const dijkstraWithoutHeapRes1ntt = myGraph.dijkstraWithoutHeap(1, null, true, true);
|
||||
const dijkstraWithoutHeapRes1ntt = myGraph.dijkstraWithoutHeap(1, undefined, true, true);
|
||||
expect(dijkstraWithoutHeapRes1ntt).toBeTruthy();
|
||||
if (dijkstraWithoutHeapRes1ntt) {
|
||||
const { distMap, minDist, minPath, paths } = dijkstraWithoutHeapRes1ntt;
|
||||
|
|
|
@ -10,11 +10,11 @@ describe('UndirectedGraph Operation Test', () => {
|
|||
});
|
||||
|
||||
it('should edge cases', () => {
|
||||
expect(graph.deleteEdge(new UndirectedEdge('c', 'd'))).toBe(null);
|
||||
expect(graph.deleteEdgeBetween('c', 'd')).toBe(null);
|
||||
expect(graph.deleteEdge(new UndirectedEdge('c', 'd'))).toBe(undefined);
|
||||
expect(graph.deleteEdgeBetween('c', 'd')).toBe(undefined);
|
||||
expect(graph.degreeOf('c')).toBe(0);
|
||||
expect(graph.edgesOf('c').length).toBe(0);
|
||||
expect(graph.getEndsOfEdge(new UndirectedEdge('c', 'd'))).toBe(null);
|
||||
expect(graph.getEndsOfEdge(new UndirectedEdge('c', 'd'))).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should add vertices', () => {
|
||||
|
|
Loading…
Reference in a new issue