tree-multimap-typed
Version:
341 lines (340 loc) • 14.5 kB
TypeScript
/**
* data-structure-typed
*
* @author Pablo Zeng
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
* @license MIT License
*/
import type { DijkstraResult, EntryCallback, GraphOptions, VertexKey } from '../../types';
import { IterableEntryBase } from '../base';
import { IGraph } from '../../interfaces';
export declare abstract class AbstractVertex<V = any> {
key: VertexKey;
value: V | undefined;
protected constructor(key: VertexKey, value?: V);
}
export declare abstract class AbstractEdge<E = any> {
value: E | undefined;
weight: number;
protected constructor(weight?: number, value?: E);
protected _hashCode: string;
get hashCode(): string;
}
/**
* Abstract graph over vertices and edges.
* @template V - Vertex value type.
* @template E - Edge value type.
* @template VO - Concrete vertex subclass (extends AbstractVertex<V>).
* @template EO - Concrete edge subclass (extends AbstractEdge<E>).
* @remarks Time O(1), Space O(1)
* @example examples will be generated by unit test
*/
export declare abstract class AbstractGraph<V = any, E = any, VO extends AbstractVertex<V> = AbstractVertex<V>, EO extends AbstractEdge<E> = AbstractEdge<E>> extends IterableEntryBase<VertexKey, V | undefined> implements IGraph<V, E, VO, EO> {
/**
* Construct a graph with runtime defaults.
* @param options - `GraphOptions<V>` in `options.graph` (e.g. `vertexValueInitializer`, `defaultEdgeWeight`).
* @remarks Time O(1), Space O(1)
*/
constructor(options?: Partial<Record<string, unknown>>);
protected _options: GraphOptions<V>;
get options(): Readonly<GraphOptions<V>>;
protected _vertexMap: Map<VertexKey, VO>;
get vertexMap(): Map<VertexKey, VO>;
set vertexMap(v: Map<VertexKey, VO>);
get size(): number;
/**
* Create a new vertex instance (implementation specific).
* @param key - Vertex identifier.
* @param value - Optional payload.
* @returns Concrete vertex instance.
* @remarks Time O(1), Space O(1)
*/
abstract createVertex(key: VertexKey, value?: V): VO;
/**
* Create a new edge instance (implementation specific).
* @param srcOrV1 - Source/endpoint A key.
* @param destOrV2 - Destination/endpoint B key.
* @param weight - Edge weight (defaults may apply).
* @param value - Edge payload.
* @returns Concrete edge instance.
* @remarks Time O(1), Space O(1)
*/
abstract createEdge(srcOrV1: VertexKey, destOrV2: VertexKey, weight?: number, value?: E): EO;
/**
* Delete an edge by instance.
* @param edge - Edge instance.
* @returns Removed edge or `undefined`.
* @remarks Time O(1) avg, Space O(1)
*/
abstract deleteEdge(edge: EO): EO | undefined;
/**
* Get an edge between two vertices if present.
* @param srcOrKey - Source/endpoint A vertex or key.
* @param destOrKey - Destination/endpoint B vertex or key.
* @returns Edge instance or `undefined`.
* @remarks Time O(1) avg, Space O(1)
*/
abstract getEdge(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | undefined;
/**
* Degree of a vertex in this graph model.
* @param vertexOrKey - Vertex or key.
* @returns Non-negative integer degree.
* @remarks Time O(1) avg, Space O(1)
*/
abstract degreeOf(vertexOrKey: VO | VertexKey): number;
/**
* All edges in the graph (unique, order not guaranteed).
* @returns Array of edges.
* @remarks Time O(E), Space O(E)
*/
abstract edgeSet(): EO[];
/**
* Incident edges of a vertex.
* @param vertexOrKey - Vertex or key.
* @returns Array of incident edges.
* @remarks Time O(deg), Space O(deg)
*/
abstract edgesOf(vertexOrKey: VO | VertexKey): EO[];
/**
* One-step neighbors of a vertex.
* @param vertexOrKey - Vertex or key.
* @returns Array of neighbor vertices.
* @remarks Time O(deg), Space O(deg)
*/
abstract getNeighbors(vertexOrKey: VO | VertexKey): VO[];
/**
* Resolve endpoints of an edge to vertex instances.
* @param edge - Edge instance.
* @returns `[v1, v2]` or `undefined` if missing.
* @remarks Time O(1), Space O(1)
*/
abstract getEndsOfEdge(edge: EO): [VO, VO] | undefined;
/**
* Get vertex instance by key.
* @param vertexKey - Vertex key.
* @returns Vertex instance or `undefined`.
* @remarks Time O(1), Space O(1)
*/
getVertex(vertexKey: VertexKey): VO | undefined;
/**
* Whether a vertex exists.
* @param vertexOrKey - Vertex or key.
* @returns `true` if present, otherwise `false`.
* @remarks Time O(1) avg, Space O(1)
*/
hasVertex(vertexOrKey: VO | VertexKey): boolean;
addVertex(vertex: VO): boolean;
addVertex(key: VertexKey, value?: V): boolean;
/**
* Type guard: check if a value is a valid vertex key.
* @param potentialKey - Value to test.
* @returns `true` if string/number; else `false`.
* @remarks Time O(1), Space O(1)
*/
isVertexKey(potentialKey: any): potentialKey is VertexKey;
/**
* Delete a vertex and its incident edges.
* @param vertexOrKey - Vertex or key.
* @returns `true` if removed; otherwise `false`.
* @remarks Time O(deg), Space O(1)
*/
abstract deleteVertex(vertexOrKey: VO | VertexKey): boolean;
/**
* Delete multiple vertices.
* @param vertexMap - Array of vertices or keys.
* @returns `true` if any vertex was removed.
* @remarks Time O(sum(deg)), Space O(1)
*/
removeManyVertices(vertexMap: VO[] | VertexKey[]): boolean;
/**
* Whether an edge exists between two vertices.
* @param v1 - Endpoint A vertex or key.
* @param v2 - Endpoint B vertex or key.
* @returns `true` if present; otherwise `false`.
* @remarks Time O(1) avg, Space O(1)
*/
hasEdge(v1: VertexKey | VO, v2: VertexKey | VO): boolean;
addEdge(edge: EO): boolean;
addEdge(src: VO | VertexKey, dest: VO | VertexKey, weight?: number, value?: E): boolean;
/**
* Set the weight of an existing edge.
* @param srcOrKey - Source vertex or key.
* @param destOrKey - Destination vertex or key.
* @param weight - New weight.
* @returns `true` if updated; otherwise `false`.
* @remarks Time O(1) avg, Space O(1)
*/
setEdgeWeight(srcOrKey: VertexKey | VO, destOrKey: VertexKey | VO, weight: number): boolean;
/**
* Enumerate simple paths up to a limit.
* @param v1 - Source vertex or key.
* @param v2 - Destination vertex or key.
* @param limit - Maximum number of paths to collect.
* @returns Array of paths (each path is an array of vertices).
* @remarks Time O(paths) worst-case exponential, Space O(V + paths)
*/
getAllPathsBetween(v1: VO | VertexKey, v2: VO | VertexKey, limit?: number): VO[][];
/**
* Sum the weights along a vertex path.
* @param path - Sequence of vertices.
* @returns Path weight sum (0 if empty or edge missing).
* @remarks Time O(L), Space O(1) where L is path length
*/
getPathSumWeight(path: VO[]): number;
/**
* Minimum hops/weight between two vertices.
* @param v1 - Source vertex or key.
* @param v2 - Destination vertex or key.
* @param isWeight - If `true`, compare by path weight; otherwise by hop count.
* @returns Minimum cost or `undefined` if missing/unreachable.
* @remarks Time O((V + E) log V) weighted / O(V + E) unweighted, Space O(V + E)
*/
getMinCostBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean): number | undefined;
/**
* Minimum path (as vertex sequence) between two vertices.
* @param v1 - Source vertex or key.
* @param v2 - Destination vertex or key.
* @param isWeight - If `true`, compare by path weight; otherwise by hop count.
* @param isDFS - For weighted mode only: if `true`, brute-force all paths; if `false`, use Dijkstra.
* @returns Vertex sequence, or `undefined`/empty when unreachable depending on branch.
* @remarks Time O((V + E) log V) weighted / O(V + E) unweighted, Space O(V + E)
*/
getMinPathBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean, isDFS?: boolean): VO[] | undefined;
/**
* Dijkstra without heap (array-based selection).
* @param src - Source vertex or key.
* @param dest - Optional destination for early stop.
* @param getMinDist - If `true`, compute global minimum distance.
* @param genPaths - If `true`, also generate path arrays.
* @returns Result bag or `undefined` if source missing.
* @remarks Time O(V^2 + E), Space O(V + E)
*/
dijkstraWithoutHeap(src: VO | VertexKey, dest?: VO | VertexKey | undefined, getMinDist?: boolean, genPaths?: boolean): DijkstraResult<VO> | undefined;
dijkstra(src: VO | VertexKey, dest?: VO | VertexKey | undefined, getMinDist?: boolean, genPaths?: boolean): DijkstraResult<VO> | undefined;
/**
* Bellman-Ford single-source shortest paths with option to scan negative cycles.
* @param src - Source vertex or key.
* @param scanNegativeCycle - If `true`, also detect negative cycles.
* @param getMin - If `true`, compute global minimum distance.
* @param genPath - If `true`, generate path arrays via predecessor map.
* @returns Result bag including distances, predecessors, and optional cycle flag.
* @remarks Time O(V * E), Space O(V + E)
*/
bellmanFord(src: VO | VertexKey, scanNegativeCycle?: boolean, getMin?: boolean, genPath?: boolean): {
hasNegativeCycle: boolean | undefined;
distMap: Map<VO, number>;
preMap: Map<VO, VO>;
paths: VO[][];
min: number;
minPath: VO[];
};
/**
* Floyd–Warshall all-pairs shortest paths.
* @returns `{ costs, predecessor }` matrices.
* @remarks Time O(V^3), Space O(V^2)
*/
floydWarshall(): {
costs: number[][];
predecessor: (VO | undefined)[][];
};
/**
* Enumerate simple cycles (may be expensive).
* @param isInclude2Cycle - If `true`, include 2-cycles when graph semantics allow.
* @returns Array of cycles (each as array of vertex keys).
* @remarks Time exponential in worst-case, Space O(V + E)
*/
getCycles(isInclude2Cycle?: boolean): VertexKey[][];
/**
* Induced-subgraph filter: keep vertices where `predicate(key, value)` is true,
* and only keep edges whose endpoints both survive.
* @param predicate - `(key, value, index, self) => boolean`.
* @param thisArg - Optional `this` for callback.
* @returns A new graph of the same concrete class (`this` type).
* @remarks Time O(V + E), Space O(V + E)
*/
filter(predicate: EntryCallback<VertexKey, V | undefined, boolean>, thisArg?: any): this;
/**
* Preserve the old behavior: return filtered entries as an array.
* @remarks Time O(V), Space O(V)
*/
filterEntries(predicate: EntryCallback<VertexKey, V | undefined, boolean>, thisArg?: any): [VertexKey, V | undefined][];
map<T>(callback: EntryCallback<VertexKey, V | undefined, T>, thisArg?: any): T[];
/**
* Create a deep clone of the graph with the same species.
* @remarks Time O(V + E), Space O(V + E)
*/
/**
* Create a deep clone of the graph with the same species.
* @returns A new graph of the same concrete class (`this` type).
* @remarks Time O(V + E), Space O(V + E)
*/
clone(): this;
/**
* Internal iterator over `[key, value]` entries in insertion order.
* @returns Iterator of `[VertexKey, V | undefined]`.
* @remarks Time O(V), Space O(1)
*/
protected _getIterator(): IterableIterator<[VertexKey, V | undefined]>;
/**
* Capture configuration needed to reproduce the current graph.
* Currently the graph has no runtime options, so we return an empty object.
*/
/**
* Capture configuration needed to reproduce the current graph.
* @returns Options bag (opaque to callers).
* @remarks Time O(1), Space O(1)
*/
protected _snapshotOptions(): Record<string, unknown>;
/**
* Create an empty graph instance of the same concrete species (Directed/Undirected/etc).
* @remarks Time O(1), Space O(1)
*/
/**
* Create an empty graph instance of the same concrete species.
* @param _options - Snapshot options from `_snapshotOptions()`.
* @returns A new empty graph instance of `this` type.
* @remarks Time O(1), Space O(1)
*/
protected _createInstance(_options?: Partial<Record<string, unknown>>): this;
/**
* Create a same-species graph populated with the given entries.
* Also preserves edges between kept vertices from the source graph.
* @remarks Time O(V + E), Space O(V + E)
*/
/**
* Create a same-species graph populated with entries; preserves edges among kept vertices.
* @param iter - Optional entries to seed the new graph.
* @param options - Snapshot options.
* @returns A new graph of `this` type.
* @remarks Time O(V + E), Space O(V + E)
*/
protected _createLike(iter?: Iterable<[VertexKey, V | undefined]>, options?: Partial<Record<string, unknown>>): this;
/**
* Internal hook to attach an edge into adjacency structures.
* @param edge - Edge instance.
* @returns `true` if inserted; otherwise `false`.
* @remarks Time O(1) avg, Space O(1)
*/
protected abstract _addEdge(edge: EO): boolean;
/**
* Insert a pre-built vertex into the graph.
* @param newVertex - Concrete vertex instance.
* @returns `true` if inserted; `false` if key already exists.
* @remarks Time O(1) avg, Space O(1)
*/
protected _addVertex(newVertex: VO): boolean;
/**
* Resolve a vertex key or instance to the concrete vertex instance.
* @param vertexOrKey - Vertex key or existing vertex.
* @returns Vertex instance or `undefined`.
* @remarks Time O(1), Space O(1)
*/
protected _getVertex(vertexOrKey: VertexKey | VO): VO | undefined;
/**
* Resolve a vertex key from a key or vertex instance.
* @param vertexOrKey - Vertex key or existing vertex.
* @returns The vertex key.
* @remarks Time O(1), Space O(1)
*/
protected _getVertexKey(vertexOrKey: VO | VertexKey): VertexKey;
}