//================================================================ /** * @packageDocumentation * @module std.internal */ //================================================================ import { MapTree } from "./MapTree"; import { XTreeNode } from "./XTreeNode"; import { MultiTreeMap } from "../container/associative/MultiTreeMap"; import { MapElementList } from "../container/associative/MapElementList"; import { Comparator } from "../functional/Comparator"; import { get_uid } from "../../functional/uid"; export class MultiMapTree< Key, T, Source extends MultiTreeMap< Key, T, Source, MapElementList.Iterator, MapElementList.ReverseIterator >, > extends MapTree { /* --------------------------------------------------------- CONSTRUCTOR --------------------------------------------------------- */ public constructor(source: Source, comp: Comparator) { super( source, comp, function ( x: MapElementList.Iterator, y: MapElementList.Iterator, ): boolean { const ret: boolean = comp(x.first, y.first); if (!ret && !comp(y.first, x.first)) return get_uid(x) < get_uid(y); else return ret; }, ); } public insert(val: MapElementList.Iterator): void { // ISSUE UID BEFORE INSERTION get_uid(val); super.insert(val); } /* --------------------------------------------------------- FINDERS --------------------------------------------------------- */ private _Nearest_by_key( key: Key, equal_mover: ( node: XTreeNode>, ) => XTreeNode> | null, ): XTreeNode> | null { // NEED NOT TO ITERATE if (this.root_ === null) return null; //---- // ITERATE //---- let ret: XTreeNode> = this.root_; let matched: XTreeNode< MapElementList.Iterator > | null = null; while (true) { const it: MapElementList.Iterator = ret.value; let my_node: XTreeNode< MapElementList.Iterator > | null = null; // COMPARE if (this.key_comp()(key, it.first)) my_node = ret.left; else if (this.key_comp()(it.first, key)) my_node = ret.right; else { // EQUAL, RESERVE THAT POINT matched = ret; my_node = equal_mover(ret); } // ULTIL CHILD NODE EXISTS if (my_node === null) break; else ret = my_node; } // RETURNS -> MATCHED OR NOT return matched !== null ? matched : ret; } public nearest_by_key( key: Key, ): XTreeNode> | null { return this._Nearest_by_key(key, function (node) { return node.left; }); } public upper_bound( key: Key, ): MapElementList.Iterator { // FIND MATCHED NODE const node: XTreeNode< MapElementList.Iterator > | null = this._Nearest_by_key(key, function (node) { return node.right; }); if (node === null) // NOTHING return this.source().end(); // MUST BE it.first > key const it: MapElementList.Iterator = node.value; if (this.key_comp()(key, it.first)) return it; else return it.next(); } }