//================================================================ /** * @packageDocumentation * @module std.internal */ //================================================================ import { SetTree } from "./SetTree"; import { XTreeNode } from "./XTreeNode"; import { MultiTreeSet } from "../container/associative/MultiTreeSet"; import { SetElementList } from "../container/associative/SetElementList"; import { Comparator } from "../functional/Comparator"; import { get_uid } from "../../functional/uid"; export class MultiSetTree< Key, Source extends MultiTreeSet< Key, Source, SetElementList.Iterator, SetElementList.ReverseIterator >, > extends SetTree { /* --------------------------------------------------------- CONSTRUCTOR --------------------------------------------------------- */ public constructor(source: Source, comp: Comparator) { super( source, comp, function ( x: SetElementList.Iterator, y: SetElementList.Iterator, ): boolean { const ret: boolean = comp(x.value, y.value); if (!ret && !comp(y.value, x.value)) return get_uid(x) < get_uid(y); else return ret; }, ); } public insert(val: SetElementList.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< SetElementList.Iterator > | null = null; while (true) { const candidate: SetElementList.Iterator = ret.value; let node: XTreeNode< SetElementList.Iterator > | null = null; // COMPARE if (this.key_comp()(key, candidate.value)) node = ret.left; else if (this.key_comp()(candidate.value, key)) node = ret.right; else { // EQUAL, RESERVE THAT POINT matched = ret; node = equal_mover(ret); } // ULTIL CHILD NODE EXISTS if (node === null) break; else ret = node; } // RETURNS -> MATCHED OR NOT return matched !== null ? matched : ret; } public nearest_by_key( val: Key, ): XTreeNode> | null { return this._Nearest_by_key(val, function (node) { return node.left; }); } public upper_bound(val: Key): SetElementList.Iterator { // FIND MATCHED NODE const node: XTreeNode< SetElementList.Iterator > | null = this._Nearest_by_key(val, function (node) { return node.right; }); if (node === null) // NOTHING return this.source().end(); // MUST BE it.first > key const it: SetElementList.Iterator = node.value; if (this.key_comp()(val, it.value)) return it; else return it.next(); } }