avl-tree-typed
Version:
Standard AVL tree
133 lines (118 loc) • 4.17 kB
text/typescript
/**
* data-structure-typed
*
* @author Pablo Zeng
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
* @license MIT License
*/
import type { MapGraphCoordinate, VertexKey } from '../../types';
import { DirectedEdge, DirectedGraph, DirectedVertex } from './directed-graph';
export class MapVertex<V = any> extends DirectedVertex<V> {
lat: number;
long: number;
constructor(key: VertexKey, value: V, lat: number, long: number) {
super(key, value);
this.lat = lat;
this.long = long;
}
}
export class MapEdge<E = any> extends DirectedEdge<E> {
constructor(src: VertexKey, dest: VertexKey, weight?: number, value?: E) {
super(src, dest, weight, value);
}
}
/**
* Directed graph variant carrying geospatial coordinates.
* @template V - Vertex value type.
* @template E - Edge value type.
* @template VO - Concrete vertex class (MapVertex<V>).
* @template EO - Concrete edge class (MapEdge<E>).
* @remarks Time O(1), Space O(1)
* @example examples will be generated by unit test
*/
export class MapGraph<
V = any,
E = any,
VO extends MapVertex<V> = MapVertex<V>,
EO extends MapEdge<E> = MapEdge<E>
> extends DirectedGraph<V, E, VO, EO> {
/**
* Construct a MapGraph.
* @param originCoord - Origin coordinate `[lat, long]` used as default.
* @param bottomRight - Optional bottom-right coordinate for bounding boxes.
* @remarks Time O(1), Space O(1)
*/
constructor(originCoord: MapGraphCoordinate, bottomRight?: MapGraphCoordinate) {
super();
this._originCoord = originCoord;
this._bottomRight = bottomRight;
}
protected _originCoord: MapGraphCoordinate = [0, 0];
get originCoord(): MapGraphCoordinate {
return this._originCoord;
}
protected _bottomRight: MapGraphCoordinate | undefined;
get bottomRight(): MapGraphCoordinate | undefined {
return this._bottomRight;
}
/**
* Create a map vertex with optional coordinates.
* @param key - Vertex identifier.
* @param value - Optional payload.
* @param lat - Latitude (defaults to `originCoord[0]`).
* @param long - Longitude (defaults to `originCoord[1]`).
* @returns MapVertex instance.
* @remarks Time O(1), Space O(1)
*/
override createVertex(
key: VertexKey,
value?: V,
lat: number = this.originCoord[0],
long: number = this.originCoord[1]
): VO {
return new MapVertex(key, value, lat, long) as VO;
}
/**
* Create a map edge (directed) with optional weight/value.
* @param src - Source key.
* @param dest - Destination key.
* @param weight - Edge weight.
* @param value - Edge payload.
* @returns MapEdge instance.
* @remarks Time O(1), Space O(1)
*/
override createEdge(src: VertexKey, dest: VertexKey, weight?: number, value?: E): EO {
return new MapEdge(src, dest, weight, value) as EO;
}
/**
* Deep clone as the same concrete class.
* @returns A new graph of the same concrete class (`this` type).
* @remarks Time O(V + E), Space O(V + E)
*/
override clone(): this {
return super.clone();
}
/**
* Include `originCoord` and `bottomRight` so `clone()/filter()` preserve geospatial settings.
* @returns Options bag extending super snapshot.
* @remarks Time O(1), Space O(1)
*/
protected override _snapshotOptions(): Record<string, unknown> {
return { ...(super._snapshotOptions() as any), originCoord: this.originCoord, bottomRight: this.bottomRight };
}
/**
* Re-create a same-species MapGraph instance from snapshot options.
* @param options - Snapshot options providing `originCoord`/`bottomRight`.
* @returns Empty MapGraph instance of `this` type.
* @remarks Time O(1), Space O(1)
*/
protected override _createInstance(options?: Partial<Record<string, unknown>>): this {
const { originCoord, bottomRight } = (options || {}) as {
originCoord?: [number, number];
bottomRight?: [number, number] | undefined;
};
const oc = (originCoord ?? this.originCoord) as [number, number];
const br = (bottomRight ?? this.bottomRight) as [number, number] | undefined;
return new MapGraph<V, E, VO, EO>(oc, br) as this;
}
}