data-structure-typed 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/dist/cjs/data-structures/binary-tree/binary-tree.js +8 -9
  3. package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  4. package/dist/cjs/data-structures/graph/abstract-graph.js +14 -14
  5. package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
  6. package/dist/cjs/data-structures/hash/hash-map.d.ts +46 -0
  7. package/dist/cjs/data-structures/hash/hash-map.js +46 -0
  8. package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
  9. package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +66 -0
  10. package/dist/cjs/data-structures/linked-list/singly-linked-list.js +66 -0
  11. package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
  12. package/dist/cjs/data-structures/queue/queue.d.ts +47 -0
  13. package/dist/cjs/data-structures/queue/queue.js +47 -0
  14. package/dist/cjs/data-structures/queue/queue.js.map +1 -1
  15. package/dist/cjs/data-structures/stack/stack.d.ts +121 -0
  16. package/dist/cjs/data-structures/stack/stack.js +121 -0
  17. package/dist/cjs/data-structures/stack/stack.js.map +1 -1
  18. package/dist/cjs/types/utils/utils.d.ts +1 -7
  19. package/dist/cjs/utils/utils.d.ts +3 -49
  20. package/dist/cjs/utils/utils.js +13 -82
  21. package/dist/cjs/utils/utils.js.map +1 -1
  22. package/dist/esm/data-structures/binary-tree/binary-tree.js +8 -9
  23. package/dist/esm/data-structures/binary-tree/binary-tree.js.map +1 -1
  24. package/dist/esm/data-structures/graph/abstract-graph.js +14 -14
  25. package/dist/esm/data-structures/graph/abstract-graph.js.map +1 -1
  26. package/dist/esm/data-structures/hash/hash-map.d.ts +46 -0
  27. package/dist/esm/data-structures/hash/hash-map.js +46 -0
  28. package/dist/esm/data-structures/hash/hash-map.js.map +1 -1
  29. package/dist/esm/data-structures/linked-list/singly-linked-list.d.ts +66 -0
  30. package/dist/esm/data-structures/linked-list/singly-linked-list.js +66 -0
  31. package/dist/esm/data-structures/linked-list/singly-linked-list.js.map +1 -1
  32. package/dist/esm/data-structures/queue/queue.d.ts +47 -0
  33. package/dist/esm/data-structures/queue/queue.js +47 -0
  34. package/dist/esm/data-structures/queue/queue.js.map +1 -1
  35. package/dist/esm/data-structures/stack/stack.d.ts +121 -0
  36. package/dist/esm/data-structures/stack/stack.js +121 -0
  37. package/dist/esm/data-structures/stack/stack.js.map +1 -1
  38. package/dist/esm/types/utils/utils.d.ts +1 -7
  39. package/dist/esm/utils/utils.d.ts +3 -49
  40. package/dist/esm/utils/utils.js +10 -68
  41. package/dist/esm/utils/utils.js.map +1 -1
  42. package/dist/umd/data-structure-typed.js +32 -80
  43. package/dist/umd/data-structure-typed.min.js +2 -2
  44. package/dist/umd/data-structure-typed.min.js.map +1 -1
  45. package/package.json +2 -2
  46. package/src/data-structures/binary-tree/binary-tree.ts +9 -10
  47. package/src/data-structures/graph/abstract-graph.ts +14 -14
  48. package/src/data-structures/hash/hash-map.ts +46 -0
  49. package/src/data-structures/linked-list/singly-linked-list.ts +66 -0
  50. package/src/data-structures/queue/queue.ts +47 -0
  51. package/src/data-structures/stack/stack.ts +121 -0
  52. package/src/types/utils/utils.ts +1 -6
  53. package/src/utils/utils.ts +11 -83
  54. package/test/unit/data-structures/graph/directed-graph.test.ts +37 -37
  55. package/test/unit/data-structures/graph/undirected-graph.test.ts +2 -2
  56. package/test/unit/data-structures/hash/hash-map.test.ts +135 -0
  57. package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +72 -1
  58. package/test/unit/data-structures/queue/queue.test.ts +214 -0
  59. package/test/unit/data-structures/stack/stack.test.ts +165 -0
  60. package/test/unit/utils/utils.test.ts +35 -2
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts","../../src/data-structures/base/iterable-entry-base.ts","../../src/data-structures/base/iterable-element-base.ts","../../src/utils/utils.ts","../../src/utils/number.ts","../../src/data-structures/hash/hash-map.ts","../../src/data-structures/base/linear-base.ts","../../src/data-structures/linked-list/singly-linked-list.ts","../../src/data-structures/linked-list/doubly-linked-list.ts","../../src/data-structures/linked-list/skip-linked-list.ts","../../src/data-structures/stack/stack.ts","../../src/data-structures/queue/queue.ts","../../src/data-structures/queue/deque.ts","../../src/data-structures/heap/heap.ts","../../src/data-structures/heap/max-heap.ts","../../src/data-structures/heap/min-heap.ts","../../src/data-structures/graph/abstract-graph.ts","../../src/data-structures/graph/directed-graph.ts","../../src/data-structures/graph/undirected-graph.ts","../../src/data-structures/graph/map-graph.ts","../../src/common/index.ts","../../src/data-structures/binary-tree/binary-tree.ts","../../src/data-structures/binary-tree/bst.ts","../../src/data-structures/binary-tree/binary-indexed-tree.ts","../../src/data-structures/binary-tree/segment-tree.ts","../../src/data-structures/binary-tree/avl-tree.ts","../../src/data-structures/binary-tree/red-black-tree.ts","../../src/data-structures/binary-tree/avl-tree-multi-map.ts","../../src/data-structures/binary-tree/tree-multi-map.ts","../../src/data-structures/binary-tree/tree-counter.ts","../../src/data-structures/binary-tree/avl-tree-counter.ts","../../src/data-structures/priority-queue/priority-queue.ts","../../src/data-structures/priority-queue/min-priority-queue.ts","../../src/data-structures/priority-queue/max-priority-queue.ts","../../src/data-structures/matrix/matrix.ts","../../src/data-structures/matrix/navigator.ts","../../src/data-structures/trie/trie.ts","../../src/data-structures/tree/tree.ts"],"sourcesContent":["export * from './data-structures';\nexport * from './utils';\nexport * from './interfaces';\nexport * from './types';\nexport * from './common';\n","import { EntryCallback, ReduceEntryCallback } from '../../types';\n\nexport abstract class IterableEntryBase<K = any, V = any> {\n abstract get size(): number;\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function is an implementation of the Symbol.iterator method that returns an iterable iterator.\n * @param {any[]} args - The `args` parameter in the code snippet represents a rest parameter. It\n * allows the function to accept any number of arguments as an array. In this case, the `args`\n * parameter is used to pass any additional arguments to the `_getIterator` method.\n */\n *[Symbol.iterator](...args: any[]): IterableIterator<[K, V]> {\n yield* this._getIterator(...args);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function returns an iterator that yields key-value pairs from the object, where the value can\n * be undefined.\n */\n *entries(): IterableIterator<[K, V | undefined]> {\n for (const item of this) {\n yield item;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function returns an iterator that yields the keys of a data structure.\n */\n *keys(): IterableIterator<K> {\n for (const item of this) {\n yield item[0];\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function returns an iterator that yields the values of a collection.\n */\n *values(): IterableIterator<V> {\n for (const item of this) {\n yield item[1];\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `every` function checks if every element in a collection satisfies a given condition.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * `value`, `key`, and `index`. It should return a boolean value indicating whether the condition is\n * met for the current element in the iteration.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be\n * passed as the first argument to the `predicate` function. If `thisArg` is not provided\n * @returns The `every` method is returning a boolean value. It returns `true` if every element in\n * the collection satisfies the provided predicate function, and `false` otherwise.\n */\n every(predicate: EntryCallback<K, V, boolean>, thisArg?: any): boolean {\n let index = 0;\n for (const item of this) {\n if (!predicate.call(thisArg, item[0], item[1], index++, this)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The \"some\" function iterates over a collection and returns true if at least one element satisfies\n * a given predicate.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * `value`, `key`, and `index`. It should return a boolean value indicating whether the condition is\n * met for the current element in the iteration.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as the `this` value when executing the `predicate` function. If `thisArg` is provided,\n * it will be passed as the first argument to the `predicate` function. If `thisArg` is\n * @returns a boolean value. It returns true if the predicate function returns true for any pair in\n * the collection, and false otherwise.\n */\n some(predicate: EntryCallback<K, V, boolean>, thisArg?: any): boolean {\n let index = 0;\n for (const item of this) {\n if (predicate.call(thisArg, item[0], item[1], index++, this)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `forEach` function iterates over each key-value pair in a collection and executes a callback\n * function for each pair.\n * @param callbackfn - The callback function that will be called for each element in the collection.\n * It takes four parameters: the value of the current element, the key of the current element, the\n * index of the current element, and the collection itself.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. If `thisArg` is provided, it will be\n * used as the `this` value when calling the callback function. If `thisArg` is not provided, `\n */\n forEach(callbackfn: EntryCallback<K, V, void>, thisArg?: any): void {\n let index = 0;\n for (const item of this) {\n const [key, value] = item;\n callbackfn.call(thisArg, key, value, index++, this);\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `find` function iterates over the entries of a collection and returns the first value for\n * which the callback function returns true.\n * @param callbackfn - The callback function that will be called for each entry in the collection. It\n * takes three arguments: the value of the entry, the key of the entry, and the index of the entry in\n * the collection. It should return a boolean value indicating whether the current entry matches the\n * desired condition.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will\n * be passed as the `this` value to the `callbackfn` function. If `thisArg\n * @returns The method `find` returns the value of the first element in the iterable that satisfies\n * the provided callback function. If no element satisfies the callback function, `undefined` is\n * returned.\n */\n find(callbackfn: EntryCallback<K, V, boolean>, thisArg?: any): [K, V] | undefined {\n let index = 0;\n for (const item of this) {\n const [key, value] = item;\n if (callbackfn.call(thisArg, key, value, index++, this)) return item;\n }\n return;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function checks if a given key exists in a collection.\n * @param {K} key - The parameter \"key\" is of type K, which means it can be any type. It represents\n * the key that we want to check for existence in the data structure.\n * @returns a boolean value. It returns true if the key is found in the collection, and false\n * otherwise.\n */\n has(key: K): boolean {\n for (const item of this) {\n const [itemKey] = item;\n if (itemKey === key) return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function checks if a given value exists in a collection.\n * @param {V} value - The parameter \"value\" is the value that we want to check if it exists in the\n * collection.\n * @returns a boolean value, either true or false.\n */\n hasValue(value: V): boolean {\n for (const [, elementValue] of this) {\n if (elementValue === value) return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `get` function retrieves the value associated with a given key from a collection.\n * @param {K} key - K (the type of the key) - This parameter represents the key that is being\n * searched for in the collection.\n * @returns The `get` method returns the value associated with the specified key if it exists in the\n * collection, otherwise it returns `undefined`.\n */\n get(key: K): V | undefined {\n for (const item of this) {\n const [itemKey, value] = item;\n if (itemKey === key) return value;\n }\n return;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `reduce` function iterates over key-value pairs and applies a callback function to each pair,\n * accumulating a single value.\n * @param callbackfn - The callback function that will be called for each element in the collection.\n * It takes four arguments: the current accumulator value, the current value of the element, the key\n * of the element, and the index of the element in the collection. It should return the updated\n * accumulator value.\n * @param {U} initialValue - The `initialValue` parameter is the initial value of the accumulator. It\n * is the value that will be used as the first argument to the `callbackfn` function when reducing\n * the elements of the collection.\n * @returns The `reduce` method is returning the final value of the accumulator after iterating over\n * all the elements in the collection.\n */\n reduce<U>(callbackfn: ReduceEntryCallback<K, V, U>, initialValue: U): U {\n let accumulator = initialValue;\n let index = 0;\n for (const item of this) {\n const [key, value] = item;\n accumulator = callbackfn(accumulator, value, key, index++, this);\n }\n return accumulator;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The print function logs the elements of an array to the console.\n */\n toVisual(): [K, V][] | string {\n return [...this];\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The print function logs the elements of an array to the console.\n */\n print(): void {\n console.log(this.toVisual());\n }\n\n abstract isEmpty(): boolean;\n\n abstract clear(): void;\n\n abstract clone(): any;\n\n abstract map(...args: any[]): any;\n\n abstract filter(...args: any[]): any;\n\n protected abstract _getIterator(...args: any[]): IterableIterator<[K, V]>;\n}\n","import { ElementCallback, IterableElementBaseOptions, ReduceElementCallback } from '../../types';\n\nexport abstract class IterableElementBase<E, R> {\n /**\n * The protected constructor initializes the options for the IterableElementBase class, including the\n * toElementFn function.\n * @param [options] - An optional object that contains the following properties:\n */\n protected constructor(options?: IterableElementBaseOptions<E, R>) {\n if (options) {\n const { toElementFn } = options;\n if (typeof toElementFn === 'function') this._toElementFn = toElementFn;\n else if (toElementFn) throw new TypeError('toElementFn must be a function type');\n }\n }\n\n protected _toElementFn?: (rawElement: R) => E;\n\n get toElementFn(): ((rawElement: R) => E) | undefined {\n return this._toElementFn;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function is an implementation of the Symbol.iterator method that returns an IterableIterator.\n * @param {any[]} args - The `args` parameter in the code snippet represents a rest parameter. It\n * allows the function to accept any number of arguments as an array. In this case, the `args`\n * parameter is used to pass any number of arguments to the `_getIterator` method.\n */\n *[Symbol.iterator](...args: any[]): IterableIterator<E> {\n yield* this._getIterator(...args);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function returns an iterator that yields all the values in the object.\n */\n *values(): IterableIterator<E> {\n for (const item of this) {\n yield item;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `every` function checks if every element in the array satisfies a given predicate.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * the current element being processed, its index, and the array it belongs to. It should return a\n * boolean value indicating whether the element satisfies a certain condition or not.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `predicate` function. If `thisArg` is\n * @returns The `every` method is returning a boolean value. It returns `true` if every element in\n * the array satisfies the provided predicate function, and `false` otherwise.\n */\n every(predicate: ElementCallback<E, R, boolean>, thisArg?: any): boolean {\n let index = 0;\n for (const item of this) {\n if (!predicate.call(thisArg, item, index++, this)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The \"some\" function checks if at least one element in a collection satisfies a given predicate.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * `value`, `index`, and `array`. It should return a boolean value indicating whether the current\n * element satisfies the condition.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as the `this` value when executing the `predicate` function. If `thisArg` is provided,\n * it will be passed as the `this` value to the `predicate` function. If `thisArg\n * @returns a boolean value. It returns true if the predicate function returns true for any element\n * in the collection, and false otherwise.\n */\n some(predicate: ElementCallback<E, R, boolean>, thisArg?: any): boolean {\n let index = 0;\n for (const item of this) {\n if (predicate.call(thisArg, item, index++, this)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `forEach` function iterates over each element in an array-like object and calls a callback\n * function for each element.\n * @param callbackfn - The callbackfn parameter is a function that will be called for each element in\n * the array. It takes three arguments: the current element being processed, the index of the current\n * element, and the array that forEach was called upon.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will\n * be passed as the `this` value to the `callbackfn` function. If `thisArg\n */\n forEach(callbackfn: ElementCallback<E, R, void>, thisArg?: any): void {\n let index = 0;\n for (const item of this) {\n callbackfn.call(thisArg, item, index++, this);\n }\n }\n\n find<S extends E>(predicate: ElementCallback<E, R, S>, thisArg?: any): S | undefined;\n find(predicate: ElementCallback<E, R, unknown>, thisArg?: any): E | undefined;\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `find` function iterates over the elements of an array-like object and returns the first\n * element that satisfies the provided callback function.\n * @param predicate - The predicate parameter is a function that will be called for each element in\n * the array. It takes three arguments: the current element being processed, the index of the current\n * element, and the array itself. The function should return a boolean value indicating whether the\n * current element matches the desired condition.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will\n * be passed as the `this` value to the `callbackfn` function. If `thisArg\n * @returns The `find` method returns the first element in the array that satisfies the provided\n * callback function. If no element satisfies the callback function, `undefined` is returned.\n */\n find(predicate: ElementCallback<E, R, boolean>, thisArg?: any): E | undefined {\n let index = 0;\n for (const item of this) {\n if (predicate.call(thisArg, item, index++, this)) return item;\n }\n\n return;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function checks if a given element exists in a collection.\n * @param {E} element - The parameter \"element\" is of type E, which means it can be any type. It\n * represents the element that we want to check for existence in the collection.\n * @returns a boolean value. It returns true if the element is found in the collection, and false\n * otherwise.\n */\n has(element: E): boolean {\n for (const ele of this) {\n if (ele === element) return true;\n }\n return false;\n }\n\n reduce(callbackfn: ReduceElementCallback<E, R>): E;\n reduce(callbackfn: ReduceElementCallback<E, R>, initialValue: E): E;\n reduce<U>(callbackfn: ReduceElementCallback<E, R, U>, initialValue: U): U;\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `reduce` function iterates over the elements of an array-like object and applies a callback\n * function to reduce them into a single value.\n * @param callbackfn - The callbackfn parameter is a function that will be called for each element in\n * the array. It takes four arguments:\n * @param {U} initialValue - The initialValue parameter is the initial value of the accumulator. It\n * is the value that the accumulator starts with before the reduction operation begins.\n * @returns The `reduce` method is returning the final value of the accumulator after iterating over\n * all the elements in the array and applying the callback function to each element.\n */\n reduce<U>(callbackfn: ReduceElementCallback<E, R, U>, initialValue?: U): U {\n let accumulator = initialValue ?? (0 as U);\n let index = 0;\n for (const item of this) {\n accumulator = callbackfn(accumulator, item, index++, this);\n }\n return accumulator;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `toArray` function converts a linked list into an array.\n * @returns The `toArray()` method is returning an array of type `E[]`.\n */\n toArray(): E[] {\n return [...this];\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The print function logs the elements of an array to the console.\n */\n toVisual(): E[] {\n return [...this];\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The print function logs the elements of an array to the console.\n */\n print(): void {\n console.log(this.toVisual());\n }\n\n abstract isEmpty(): boolean;\n\n abstract clear(): void;\n\n abstract clone(): IterableElementBase<E, R>;\n\n abstract map(...args: any[]): any;\n\n abstract filter(...args: any[]): any;\n\n protected abstract _getIterator(...args: any[]): IterableIterator<E>;\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { Comparable, ComparablePrimitive, Thunk, ToThunkFn, TrlAsyncFn, TrlFn } from '../types';\n\n/**\n * The function generates a random UUID (Universally Unique Identifier) in TypeScript.\n * @returns A randomly generated UUID (Universally Unique Identifier) in the format\n * 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' where each 'x' is replaced with a random hexadecimal\n * character.\n */\nexport const uuidV4 = function () {\n return 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, function (c) {\n const r = (Math.random() * 16) | 0,\n v = c == 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n\n/**\n * The `arrayRemove` function removes elements from an array based on a specified predicate function\n * and returns the removed elements.\n * @param {T[]} array - An array of elements that you want to filter based on the provided predicate\n * function.\n * @param predicate - The `predicate` parameter is a function that takes three arguments:\n * @returns The `arrayRemove` function returns an array containing the elements that satisfy the given\n * `predicate` function.\n */\nexport const arrayRemove = function <T>(array: T[], predicate: (item: T, index: number, array: T[]) => boolean): T[] {\n let i = -1,\n len = array ? array.length : 0;\n const result = [];\n\n while (++i < len) {\n const value = array[i];\n if (predicate(value, i, array)) {\n result.push(value);\n Array.prototype.splice.call(array, i--, 1);\n len--;\n }\n }\n\n return result;\n};\n\nexport const THUNK_SYMBOL = Symbol('thunk');\n\n/**\n * The function `isThunk` checks if a given value is a function with a specific symbol property.\n * @param {any} fnOrValue - The `fnOrValue` parameter in the `isThunk` function can be either a\n * function or a value that you want to check if it is a thunk. Thunks are functions that are wrapped\n * around a value or computation for lazy evaluation. The function checks if the `fnOrValue` is\n * @returns The function `isThunk` is checking if the input `fnOrValue` is a function and if it has a\n * property `__THUNK__` equal to `THUNK_SYMBOL`. The return value will be `true` if both conditions are\n * met, otherwise it will be `false`.\n */\nexport const isThunk = (fnOrValue: any) => {\n return typeof fnOrValue === 'function' && fnOrValue.__THUNK__ === THUNK_SYMBOL;\n};\n\n/**\n * The `toThunk` function in TypeScript converts a function into a thunk by wrapping it in a closure.\n * @param {ToThunkFn} fn - `fn` is a function that will be converted into a thunk.\n * @returns A thunk function is being returned. Thunk functions are functions that delay the evaluation\n * of an expression or operation until it is explicitly called or invoked. In this case, the `toThunk`\n * function takes a function `fn` as an argument and returns a thunk function that, when called, will\n * execute the `fn` function provided as an argument.\n */\nexport const toThunk = (fn: ToThunkFn): Thunk => {\n const thunk = () => fn();\n thunk.__THUNK__ = THUNK_SYMBOL;\n return thunk;\n};\n\n/**\n * The `trampoline` function in TypeScript enables tail call optimization by using thunks to avoid\n * stack overflow.\n * @param {TrlFn} fn - The `fn` parameter in the `trampoline` function is a function that takes any\n * number of arguments and returns a value.\n * @returns The `trampoline` function returns an object with two properties:\n * 1. A function that executes the provided function `fn` and continues to execute any thunks returned\n * by `fn` until a non-thunk value is returned.\n * 2. A `cont` property that is a function which creates a thunk for the provided function `fn`.\n */\nexport const trampoline = (fn: TrlFn) => {\n const cont = (...args: [...Parameters<TrlFn>]): ReturnType<TrlFn> => toThunk(() => fn(...args));\n\n return Object.assign(\n (...args: [...Parameters<TrlFn>]) => {\n let result = fn(...args);\n\n while (isThunk(result) && typeof result === 'function') {\n result = result();\n }\n\n return result;\n },\n { cont }\n );\n};\n\n/**\n * The `trampolineAsync` function in TypeScript allows for asynchronous trampolining of a given\n * function.\n * @param {TrlAsyncFn} fn - The `fn` parameter in the `trampolineAsync` function is expected to be a\n * function that returns a Promise. This function will be called recursively until a non-thunk value is\n * returned.\n * @returns The `trampolineAsync` function returns an object with two properties:\n * 1. An async function that executes the provided `TrlAsyncFn` function and continues to execute any\n * thunks returned by the function until a non-thunk value is returned.\n * 2. A `cont` property that is a function which wraps the provided `TrlAsyncFn` function in a thunk\n * and returns it.\n */\nexport const trampolineAsync = (fn: TrlAsyncFn) => {\n const cont = (...args: [...Parameters<TrlAsyncFn>]): ReturnType<TrlAsyncFn> => toThunk(() => fn(...args));\n\n return Object.assign(\n async (...args: [...Parameters<TrlAsyncFn>]) => {\n let result = await fn(...args);\n\n while (isThunk(result) && typeof result === 'function') {\n result = await result();\n }\n\n return result;\n },\n { cont }\n );\n};\n\n/**\n * The function `getMSB` returns the most significant bit of a given number.\n * @param {number} value - The `value` parameter is a number for which we want to find the position of\n * the Most Significant Bit (MSB). The function `getMSB` takes this number as input and calculates the\n * position of the MSB in its binary representation.\n * @returns The function `getMSB` returns the most significant bit (MSB) of the input `value`. If the\n * input value is less than or equal to 0, it returns 0. Otherwise, it calculates the position of the\n * MSB using the `Math.clz32` function and bitwise left shifts 1 to that position.\n */\nexport const getMSB = (value: number): number => {\n if (value <= 0) {\n return 0;\n }\n return 1 << (31 - Math.clz32(value));\n};\n\n/**\n * The `rangeCheck` function in TypeScript is used to validate if an index is within a specified range\n * and throws a `RangeError` with a custom message if it is out of bounds.\n * @param {number} index - The `index` parameter represents the value that you want to check if it\n * falls within a specified range.\n * @param {number} min - The `min` parameter represents the minimum value that the `index` should be\n * compared against in the `rangeCheck` function.\n * @param {number} max - The `max` parameter in the `rangeCheck` function represents the maximum value\n * that the `index` parameter is allowed to have. If the `index` is greater than this `max` value, a\n * `RangeError` will be thrown.\n * @param [message=Index out of bounds.] - The `message` parameter is a string that represents the\n * error message to be thrown if the index is out of bounds. By default, if no message is provided when\n * calling the `rangeCheck` function, the message \"Index out of bounds.\" will be used.\n */\nexport const rangeCheck = (index: number, min: number, max: number, message = 'Index out of bounds.'): void => {\n if (index < min || index > max) throw new RangeError(message);\n};\n\n/**\n * The function `throwRangeError` throws a RangeError with a custom message if called.\n * @param [message=The value is off-limits.] - The `message` parameter is a string that represents the\n * error message to be displayed when a `RangeError` is thrown. If no message is provided, the default\n * message is 'The value is off-limits.'.\n */\nexport const throwRangeError = (message = 'The value is off-limits.'): void => {\n throw new RangeError(message);\n};\n\n/**\n * The function `isWeakKey` checks if the input is an object or a function in TypeScript.\n * @param {unknown} input - The `input` parameter in the `isWeakKey` function is of type `unknown`,\n * which means it can be any type. The function checks if the `input` is an object (excluding `null`)\n * or a function, and returns a boolean indicating whether the `input` is a weak\n * @returns The function `isWeakKey` returns a boolean value indicating whether the input is an object\n * or a function.\n */\nexport const isWeakKey = (input: unknown): input is object => {\n const inputType = typeof input;\n return (inputType === 'object' && input !== null) || inputType === 'function';\n};\n\n/**\n * The function `calcMinUnitsRequired` calculates the minimum number of units required to accommodate a\n * given total quantity based on a specified unit size.\n * @param {number} totalQuantity - The `totalQuantity` parameter represents the total quantity of items\n * that need to be processed or handled.\n * @param {number} unitSize - The `unitSize` parameter represents the size of each unit or package. It\n * is used in the `calcMinUnitsRequired` function to calculate the minimum number of units required to\n * accommodate a total quantity of items.\n */\nexport const calcMinUnitsRequired = (totalQuantity: number, unitSize: number) =>\n Math.floor((totalQuantity + unitSize - 1) / unitSize);\n\n/**\n * The `roundFixed` function in TypeScript rounds a number to a specified number of decimal places.\n * @param {number} num - The `num` parameter is a number that you want to round to a certain number of\n * decimal places.\n * @param {number} [digit=10] - The `digit` parameter in the `roundFixed` function specifies the number\n * of decimal places to round the number to. By default, it is set to 10 if not provided explicitly.\n * @returns The function `roundFixed` returns a number that is rounded to the specified number of\n * decimal places (default is 10 decimal places).\n */\nexport const roundFixed = (num: number, digit: number = 10) => {\n const multiplier = Math.pow(10, digit);\n return Math.round(num * multiplier) / multiplier;\n};\n\n/**\n * The function `isPrimitiveComparable` checks if a value is a primitive type that can be compared.\n * @param {unknown} value - The `value` parameter in the `isPrimitiveComparable` function is of type\n * `unknown`, which means it can be any type. The function checks if the `value` is a primitive type\n * that can be compared, such as number, bigint, string, or boolean.\n * @returns The function `isPrimitiveComparable` returns a boolean value indicating whether the input\n * `value` is a primitive value that can be compared using standard comparison operators (<, >, <=,\n * >=).\n */\nfunction isPrimitiveComparable(value: unknown): value is ComparablePrimitive {\n const valueType = typeof value;\n if (valueType === 'number') return true;\n // if (valueType === 'number') return !Number.isNaN(value);\n return valueType === 'bigint' || valueType === 'string' || valueType === 'boolean';\n}\n\n/**\n * The function `tryObjectToPrimitive` attempts to convert an object to a comparable primitive value by\n * first checking the `valueOf` method and then the `toString` method.\n * @param {object} obj - The `obj` parameter in the `tryObjectToPrimitive` function is an object that\n * you want to convert to a primitive value. The function attempts to convert the object to a primitive\n * value by first checking if the object has a `valueOf` method. If the `valueOf` method exists, it\n * @returns The function `tryObjectToPrimitive` returns a value of type `ComparablePrimitive` if a\n * primitive comparable value is found within the object, or a string value if the object has a custom\n * `toString` method that does not return `'[object Object]'`. If neither condition is met, the\n * function returns `null`.\n */\nfunction tryObjectToPrimitive(obj: object): ComparablePrimitive | null {\n if (typeof obj.valueOf === 'function') {\n const valueOfResult = obj.valueOf();\n if (valueOfResult !== obj) {\n if (isPrimitiveComparable(valueOfResult)) return valueOfResult;\n if (typeof valueOfResult === 'object' && valueOfResult !== null) return tryObjectToPrimitive(valueOfResult);\n }\n }\n if (typeof obj.toString === 'function') {\n const stringResult = obj.toString();\n if (stringResult !== '[object Object]') return stringResult;\n }\n return null;\n}\n\n/**\n * The function `isComparable` in TypeScript checks if a value is comparable, handling primitive values\n * and objects with optional force comparison.\n * @param {unknown} value - The `value` parameter in the `isComparable` function represents the value\n * that you want to check if it is comparable. It can be of any type (`unknown`), and the function will\n * determine if it is comparable based on certain conditions.\n * @param [isForceObjectComparable=false] - The `isForceObjectComparable` parameter in the\n * `isComparable` function is a boolean flag that determines whether to treat non-primitive values as\n * comparable objects. When set to `true`, it forces the function to consider non-primitive values as\n * comparable objects, regardless of their type.\n * @returns The function `isComparable` returns a boolean value indicating whether the `value` is\n * considered comparable or not.\n */\nexport function isComparable(value: unknown, isForceObjectComparable = false): value is Comparable {\n if (value === null || value === undefined) return false;\n if (isPrimitiveComparable(value)) return true;\n\n if (typeof value !== 'object') return false;\n if (value instanceof Date) return true;\n // if (value instanceof Date) return !Number.isNaN(value.getTime());\n if (isForceObjectComparable) return true;\n const comparableValue = tryObjectToPrimitive(value);\n if (comparableValue === null || comparableValue === undefined) return false;\n return isPrimitiveComparable(comparableValue);\n}\n","/**\n * The function `toBinaryString` converts a number to a binary string representation with a specified\n * number of digits.\n * @param {number} num - The `num` parameter in the `toBinaryString` function represents the number\n * that you want to convert to a binary string.\n * @param [digit=32] - The `digit` parameter in the `toBinaryString` function represents the number of\n * digits the binary string should have. By default, it is set to 32, meaning that the binary string\n * will be padded with zeros at the beginning to ensure it is 32 bits long. You can provide a\n * @returns The function `toBinaryString` takes a number as input and converts it to a binary string\n * representation with a specified number of digits (default is 32). The binary string is padded with\n * zeros at the beginning to ensure it has the specified number of digits. The function returns the\n * binary string representation of the input number.\n */\nexport function toBinaryString(num: number, digit = 32) {\n // Convert number to binary string\n let binaryString = (num >>> 0).toString(2); // Use the unsigned right shift operator to ensure you get a binary representation of a 32-bit unsigned integer\n\n // Use pad Start to ensure the string length is 32 bits\n binaryString = binaryString.padStart(digit, '0');\n\n return binaryString;\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type {\n EntryCallback,\n HashMapLinkedNode,\n HashMapOptions,\n HashMapStoreItem,\n LinkedHashMapOptions\n} from '../../types';\nimport { IterableEntryBase } from '../base';\nimport { isWeakKey, rangeCheck } from '../../utils';\n\n/**\n * 1. Key-Value Pair Storage: HashMap stores key-value pairs. Each key map to a value.\n * 2. Fast Lookup: It's used when you need to quickly find, insert, or delete entries based on a key.\n * 3. Unique Keys: Keys are unique.\n * If you try to insert another entry with the same key, the new one will replace the old entry.\n * 4. Unordered Collection: HashMap does not guarantee the order of entries, and the order may change over time.\n */\nexport class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K, V> {\n /**\n * The constructor function initializes a HashMap object with an optional initial collection and\n * options.\n * @param entryOrRawElements - The `entryOrRawElements` parameter is an iterable collection of elements of a type\n * `T`. It is an optional parameter and its default value is an empty array `[]`.\n * @param [options] - The `options` parameter is an optional object that can contain two properties:\n */\n constructor(entryOrRawElements: Iterable<R | [K, V]> = [], options?: HashMapOptions<K, V, R>) {\n super();\n if (options) {\n const { hashFn, toEntryFn } = options;\n if (hashFn) this._hashFn = hashFn;\n if (toEntryFn) this._toEntryFn = toEntryFn;\n }\n if (entryOrRawElements) {\n this.setMany(entryOrRawElements);\n }\n }\n\n protected _store: { [key: string]: HashMapStoreItem<K, V> } = {};\n\n /**\n * The function returns the store object, which is a dictionary of HashMapStoreItem objects.\n * @returns The store property is being returned. It is a dictionary-like object with string keys and\n * values of type HashMapStoreItem<K, V>.\n */\n get store(): { [p: string]: HashMapStoreItem<K, V> } {\n return this._store;\n }\n\n protected _objMap: Map<object, V> = new Map();\n\n /**\n * The function returns the object map.\n * @returns The `objMap` property is being returned, which is a `Map` object with keys of type\n * `object` and values of type `V`.\n */\n get objMap(): Map<object, V> {\n return this._objMap;\n }\n\n protected _toEntryFn?: (rawElement: R) => [K, V];\n\n /**\n * The function returns the value of the _toEntryFn property.\n * @returns The function being returned is `this._toEntryFn`.\n */\n get toEntryFn() {\n return this._toEntryFn;\n }\n\n protected _size = 0;\n\n /**\n * The function returns the size of an object.\n * @returns The size of the object, which is a number.\n */\n get size(): number {\n return this._size;\n }\n\n protected _hashFn: (key: K) => string = (key: K) => String(key);\n\n /**\n * The hasFn function is a function that takes in an item and returns a boolean\n * indicating whether the item is contained within the hash table.\n *\n * @return The hash function\n */\n get hashFn() {\n return this._hashFn;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if a given element is an array with exactly two elements.\n * @param {any} rawElement - The `rawElement` parameter is of type `any`, which means it can be any\n * data type.\n * @returns a boolean value.\n */\n isEntry(rawElement: any): rawElement is [K, V] {\n return Array.isArray(rawElement) && rawElement.length === 2;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if the size of an object is equal to zero and returns a boolean value.\n * @returns A boolean value indicating whether the size of the object is 0 or not.\n */\n isEmpty(): boolean {\n return this._size === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear() function resets the state of an object by clearing its internal store, object map, and\n * size.\n */\n clear() {\n this._store = {};\n this._objMap.clear();\n this._size = 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `set` function adds a key-value pair to a map-like data structure, incrementing the size if\n * the key is not already present.\n * @param {K} key - The key parameter is the key used to identify the value in the data structure. It\n * can be of any type, but if it is an object, it will be stored in a Map, otherwise it will be\n * stored in a regular JavaScript object.\n * @param {V} value - The value parameter represents the value that you want to associate with the\n * key in the data structure.\n */\n set(key: K, value: V): boolean {\n if (this._isObjKey(key)) {\n if (!this.objMap.has(key)) {\n this._size++;\n }\n this.objMap.set(key, value);\n } else {\n const strKey = this._getNoObjKey(key);\n if (this.store[strKey] === undefined) {\n this._size++;\n }\n this._store[strKey] = { key, value };\n }\n return true;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The function `setMany` takes an iterable collection of objects, maps each object to a key-value\n * pair using a mapping function, and sets each key-value pair in the current object.\n * @param entryOrRawElements - The `entryOrRawElements` parameter is an iterable collection of elements of a type\n * `T`.\n * @returns The `setMany` function is returning an array of booleans.\n */\n setMany(entryOrRawElements: Iterable<R | [K, V]>): boolean[] {\n const results: boolean[] = [];\n for (const rawEle of entryOrRawElements) {\n let key: K | undefined, value: V | undefined;\n if (this.isEntry(rawEle)) {\n key = rawEle[0];\n value = rawEle[1];\n } else if (this._toEntryFn) {\n const item = this._toEntryFn(rawEle);\n key = item[0];\n value = item[1];\n }\n\n if (key !== undefined && value !== undefined) results.push(this.set(key, value));\n }\n return results;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `get` function retrieves a value from a map based on a given key, either from an object map or\n * a string map.\n * @param {K} key - The `key` parameter is the key used to retrieve a value from the map. It can be\n * of any type, but it should be compatible with the key type used when the map was created.\n * @returns The method `get(key: K)` returns a value of type `V` if the key exists in the `_objMap`\n * or `_store`, otherwise it returns `undefined`.\n */\n override get(key: K): V | undefined {\n if (this._isObjKey(key)) {\n return this.objMap.get(key);\n } else {\n const strKey = this._getNoObjKey(key);\n return this._store[strKey]?.value;\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `has` function checks if a given key exists in the `_objMap` or `_store` based on whether it\n * is an object key or not.\n * @param {K} key - The parameter \"key\" is of type K, which means it can be any type.\n * @returns The `has` method is returning a boolean value.\n */\n override has(key: K): boolean {\n if (this._isObjKey(key)) {\n return this.objMap.has(key);\n } else {\n const strKey = this._getNoObjKey(key);\n return strKey in this.store;\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `delete` function removes an element from a map-like data structure based on the provided key.\n * @param {K} key - The `key` parameter is the key of the element that you want to delete from the\n * data structure.\n * @returns The `delete` method returns a boolean value. It returns `true` if the key was\n * successfully deleted from the map, and `false` if the key was not found in the map.\n */\n delete(key: K): boolean {\n if (this._isObjKey(key)) {\n if (this.objMap.has(key)) {\n this._size--;\n }\n\n return this.objMap.delete(key);\n } else {\n const strKey = this._getNoObjKey(key);\n if (strKey in this.store) {\n delete this.store[strKey];\n this._size--;\n return true;\n }\n return false;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The clone function creates a new HashMap with the same key-value pairs as\n * this one. The clone function is useful for creating a copy of an existing\n * HashMap, and then modifying that copy without affecting the original.\n *\n * @return A new hashmap with the same values as this one\n */\n clone(): HashMap<K, V, R> {\n return new HashMap<K, V, R>(this, { hashFn: this._hashFn, toEntryFn: this._toEntryFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function in TypeScript creates a new HashMap by applying a callback function to each\n * key-value pair in the original HashMap.\n * @param callbackfn - The callback function that will be called for each key-value pair in the\n * HashMap. It takes four parameters:\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will\n * be passed as the `this` value to the `callbackfn` function. If `thisArg\n * @returns The `map` method is returning a new `HashMap` object with the transformed values based on\n * the provided callback function.\n */\n map<VM>(callbackfn: EntryCallback<K, V, VM>, thisArg?: any): HashMap<K, VM> {\n const resultMap = new HashMap<K, VM>();\n let index = 0;\n for (const [key, value] of this) {\n resultMap.set(key, callbackfn.call(thisArg, key, value, index++, this));\n }\n return resultMap;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new HashMap containing key-value pairs from the original HashMap\n * that satisfy a given predicate function.\n * @param predicate - The predicate parameter is a function that takes four arguments: value, key,\n * index, and map. It is used to determine whether an element should be included in the filtered map\n * or not. The function should return a boolean value - true if the element should be included, and\n * false otherwise.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `predicate` function. If `thisArg` is\n * @returns The `filter` method is returning a new `HashMap` object that contains the key-value pairs\n * from the original `HashMap` that pass the provided `predicate` function.\n */\n filter(predicate: EntryCallback<K, V, boolean>, thisArg?: any): HashMap<K, V> {\n const filteredMap = new HashMap<K, V>();\n let index = 0;\n for (const [key, value] of this) {\n if (predicate.call(thisArg, key, value, index++, this)) {\n filteredMap.set(key, value);\n }\n }\n return filteredMap;\n }\n\n /**\n * The function returns an iterator that yields key-value pairs from both an object store and an\n * object map.\n */\n protected *_getIterator(): IterableIterator<[K, V]> {\n for (const node of Object.values(this.store)) {\n yield [node.key, node.value] as [K, V];\n }\n for (const node of this.objMap) {\n yield node as [K, V];\n }\n }\n\n /**\n * The function checks if a given key is an object or a function.\n * @param {any} key - The parameter \"key\" can be of any type.\n * @returns a boolean value.\n */\n protected _isObjKey(key: any): key is object | ((...args: any[]) => any) {\n const keyType = typeof key;\n return (keyType === 'object' || keyType === 'function') && key !== null;\n }\n\n /**\n * The function `_getNoObjKey` takes a key and returns a string representation of the key, handling\n * different types of keys.\n * @param {K} key - The `key` parameter is of type `K`, which represents the type of the key being\n * passed to the `_getNoObjKey` function.\n * @returns a string value.\n */\n protected _getNoObjKey(key: K): string {\n const keyType = typeof key;\n\n let strKey: string;\n if (keyType !== 'string' && keyType !== 'number' && keyType !== 'symbol') {\n strKey = this._hashFn(key);\n } else {\n if (keyType === 'number') {\n // TODO numeric key should has its own hash\n strKey = <string>key;\n } else {\n strKey = <string>key;\n }\n }\n return strKey;\n }\n}\n\n/**\n * 1. Maintaining the Order of Element Insertion: Unlike HashMap, LinkedHashMap maintains the order in which entries are inserted. Therefore, when you traverse it, entries will be returned in the order they were inserted into the map.\n * 2. Based on Hash Table and Linked List: It combines the structures of a hash table and a linked list, using the hash table to ensure fast access, while maintaining the order of entries through the linked list.\n * 3. Time Complexity: Similar to HashMap, LinkedHashMap offers constant-time performance for get and put operations in most cases.\n */\nexport class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K, V> {\n protected readonly _sentinel: HashMapLinkedNode<K, V | undefined>;\n\n /**\n * The constructor initializes a LinkedHashMap object with an optional raw collection and options.\n * @param entryOrRawElements - The `entryOrRawElements` parameter is an iterable collection of elements. It is\n * used to initialize the HashMapLinked instance with key-value pairs. Each element in the\n * `entryOrRawElements` is converted to a key-value pair using the `toEntryFn` function (if provided) and\n * then added to the HashMap\n * @param [options] - The `options` parameter is an optional object that can contain the following\n * properties:\n */\n constructor(entryOrRawElements: Iterable<R | [K, V]> = [], options?: LinkedHashMapOptions<K, V, R>) {\n super();\n this._sentinel = <HashMapLinkedNode<K, V>>{};\n this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel;\n\n if (options) {\n const { hashFn, objHashFn, toEntryFn } = options;\n if (hashFn) this._hashFn = hashFn;\n if (objHashFn) this._objHashFn = objHashFn;\n\n if (toEntryFn) {\n this._toEntryFn = toEntryFn;\n }\n }\n\n if (entryOrRawElements) {\n this.setMany(entryOrRawElements);\n }\n }\n\n protected _hashFn: (key: K) => string = (key: K) => String(key);\n\n /**\n * The function returns the hash function used for generating a hash value for a given key.\n * @returns The hash function that takes a key of type K and returns a string.\n */\n get hashFn(): (key: K) => string {\n return this._hashFn;\n }\n\n protected _objHashFn: (key: K) => object = (key: K) => <object>key;\n\n /**\n * The function returns the object hash function.\n * @returns The function `objHashFn` is being returned.\n */\n get objHashFn(): (key: K) => object {\n return this._objHashFn;\n }\n\n protected _noObjMap: Record<string, HashMapLinkedNode<K, V | undefined>> = {};\n\n /**\n * The function returns a record of HashMapLinkedNode objects with string keys.\n * @returns The method is returning a Record object, which is a TypeScript type that represents an\n * object with string keys and values that are HashMapLinkedNode objects with keys of type K and\n * values of type V or undefined.\n */\n get noObjMap(): Record<string, HashMapLinkedNode<K, V | undefined>> {\n return this._noObjMap;\n }\n\n protected _objMap = new WeakMap<object, HashMapLinkedNode<K, V | undefined>>();\n\n /**\n * The function returns the WeakMap object used to map objects to HashMapLinkedNode instances.\n * @returns The `objMap` property is being returned.\n */\n get objMap(): WeakMap<object, HashMapLinkedNode<K, V | undefined>> {\n return this._objMap;\n }\n\n protected _head: HashMapLinkedNode<K, V | undefined>;\n\n /**\n * The function returns the head node of a HashMapLinkedNode.\n * @returns The method `getHead()` is returning a `HashMapLinkedNode` object with key type `K` and\n * a value type `V | undefined`.\n */\n get head(): HashMapLinkedNode<K, V | undefined> {\n return this._head;\n }\n\n protected _tail: HashMapLinkedNode<K, V | undefined>;\n\n /**\n * The function returns the tail node of a HashMapLinkedNode.\n * @returns The `_tail` property of type `HashMapLinkedNode<K, V | undefined>` is being returned.\n */\n get tail(): HashMapLinkedNode<K, V | undefined> {\n return this._tail;\n }\n\n protected _toEntryFn?: (rawElement: R) => [K, V] = (rawElement: R) => {\n if (this.isEntry(rawElement)) {\n // TODO, For performance optimization, it may be necessary to only inspect the first element traversed.\n return rawElement;\n } else {\n throw new Error(\n \"If the provided entryOrRawElements does not adhere to the [key, value] type format, the toEntryFn in the constructor's options parameter needs to specified.\"\n );\n }\n };\n\n /**\n * The function returns the value of the _toEntryFn property.\n * @returns The function being returned is `this._toEntryFn`.\n */\n get toEntryFn() {\n return this._toEntryFn;\n }\n\n protected _size = 0;\n\n /**\n * The function returns the size of an object.\n * @returns The size of the object.\n */\n get size() {\n return this._size;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function returns the key-value pair at the front of a data structure.\n * @returns The front element of the data structure, represented as a tuple with a key (K) and a\n * value (V).\n */\n get first() {\n if (this._size === 0) return;\n return <[K, V]>[this.head.key, this.head.value];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function returns the key-value pair at the end of a data structure.\n * @returns The method is returning an array containing the key-value pair of the tail element in the\n * data structure.\n */\n get last() {\n if (this._size === 0) return;\n return <[K, V]>[this.tail.key, this.tail.value];\n }\n\n /**\n * The `begin()` function in TypeScript iterates over a linked list and yields key-value pairs.\n */\n *begin() {\n let node = this.head;\n while (node !== this._sentinel) {\n yield [node.key, node.value];\n node = node.next;\n }\n }\n\n /**\n * The function `reverseBegin()` iterates over a linked list in reverse order, yielding each node's\n * key and value.\n */\n *reverseBegin() {\n let node = this.tail;\n while (node !== this._sentinel) {\n yield [node.key, node.value];\n node = node.prev;\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `set` function adds a new key-value pair to a data structure, either using an object key or a\n * string key.\n * @param {K} key - The `key` parameter is the key to be set in the data structure. It can be of any\n * type, but typically it is a string or symbol.\n * @param {V} [value] - The `value` parameter is an optional parameter of type `V`. It represents the\n * value associated with the key being set in the data structure.\n * @returns the size of the data structure after the key-value pair has been set.\n */\n set(key: K, value?: V): boolean {\n let node;\n const isNewKey = !this.has(key); // Check if the key is new\n\n if (isWeakKey(key)) {\n const hash = this._objHashFn(key);\n node = this.objMap.get(hash);\n\n if (!node && isNewKey) {\n // Create a new node\n node = { key: <K>hash, value, prev: this.tail, next: this._sentinel };\n this.objMap.set(hash, node);\n } else if (node) {\n // Update the value of an existing node\n node.value = value;\n }\n } else {\n const hash = this._hashFn(key);\n node = this.noObjMap[hash];\n\n if (!node && isNewKey) {\n this.noObjMap[hash] = node = { key, value, prev: this.tail, next: this._sentinel };\n } else if (node) {\n // Update the value of an existing node\n node.value = value;\n }\n }\n\n if (node && isNewKey) {\n // Update the head and tail of the linked list\n if (this._size === 0) {\n this._head = node;\n this._sentinel.next = node;\n } else {\n this.tail.next = node;\n node.prev = this.tail; // Make sure that the prev of the new node points to the current tail node\n }\n this._tail = node;\n this._sentinel.prev = node;\n this._size++;\n }\n\n return true;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The function `setMany` takes an iterable collection, converts each element into a key-value pair\n * using a provided function, and sets each key-value pair in the current object, returning an array\n * of booleans indicating the success of each set operation.\n * @param entryOrRawElements - The entryOrRawElements parameter is an iterable collection of elements of type\n * R.\n * @returns The `setMany` function returns an array of booleans.\n */\n setMany(entryOrRawElements: Iterable<R | [K, V]>): boolean[] {\n const results: boolean[] = [];\n for (const rawEle of entryOrRawElements) {\n let key: K | undefined, value: V | undefined;\n if (this.isEntry(rawEle)) {\n key = rawEle[0];\n value = rawEle[1];\n } else if (this._toEntryFn) {\n const item = this._toEntryFn(rawEle);\n key = item[0];\n value = item[1];\n }\n\n if (key !== undefined && value !== undefined) results.push(this.set(key, value));\n }\n return results;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if a given key exists in a map, using different logic depending on whether the\n * key is a weak key or not.\n * @param {K} key - The `key` parameter is the key that is being checked for existence in the map.\n * @returns The method `has` is returning a boolean value.\n */\n override has(key: K): boolean {\n if (isWeakKey(key)) {\n const hash = this._objHashFn(key);\n return this.objMap.has(hash);\n } else {\n const hash = this._hashFn(key);\n return hash in this.noObjMap;\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `get` retrieves the value associated with a given key from a map, either by using the\n * key directly or by using an index stored in the key object.\n * @param {K} key - The `key` parameter is the key used to retrieve a value from the map. It can be\n * of any type, but typically it is a string or symbol.\n * @returns The value associated with the given key is being returned. If the key is an object key,\n * the value is retrieved from the `_nodes` array using the index stored in the `OBJ_KEY_INDEX`\n * property of the key. If the key is a string key, the value is retrieved from the `_noObjMap` object\n * using the key itself. If the key is not found, `undefined` is\n */\n override get(key: K): V | undefined {\n if (isWeakKey(key)) {\n const hash = this._objHashFn(key);\n const node = this.objMap.get(hash);\n return node ? node.value : undefined;\n } else {\n const hash = this._hashFn(key);\n const node = this.noObjMap[hash];\n return node ? node.value : undefined;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `at` retrieves the key-value pair at a specified index in a linked list.\n * @param {number} index - The index parameter is a number that represents the position of the\n * element we want to retrieve from the data structure.\n * @returns The method `at(index: number)` is returning an array containing the key-value pair at\n * the specified index in the data structure. The key-value pair is represented as a tuple `[K, V]`,\n * where `K` is the key and `V` is the value.\n */\n at(index: number): V | undefined {\n rangeCheck(index, 0, this._size - 1);\n let node = this.head;\n while (index--) {\n node = node.next;\n }\n return node.value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `delete` function removes a key-value pair from a map-like data structure.\n * @param {K} key - The `key` parameter is the key that you want to delete from the data structure.\n * It can be of any type, but typically it is a string or an object.\n * @returns a boolean value. It returns `true` if the deletion was successful, and `false` if the key\n * was not found.\n */\n delete(key: K): boolean {\n let node;\n\n if (isWeakKey(key)) {\n const hash = this._objHashFn(key);\n // Get nodes from WeakMap\n node = this.objMap.get(hash);\n\n if (!node) {\n return false; // If the node does not exist, return false\n }\n\n // Remove nodes from WeakMap\n this.objMap.delete(hash);\n } else {\n const hash = this._hashFn(key);\n // Get nodes from noObjMap\n node = this.noObjMap[hash];\n\n if (!node) {\n return false; // If the node does not exist, return false\n }\n\n // Remove nodes from orgMap\n delete this.noObjMap[hash];\n }\n\n // Remove node from doubly linked list\n this._deleteNode(node);\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `deleteAt` function deletes a node at a specified index in a linked list.\n * @param {number} index - The index parameter represents the position at which the node should be\n * deleted in the linked list.\n * @returns The size of the list after deleting the element at the specified index.\n */\n deleteAt(index: number): boolean {\n rangeCheck(index, 0, this._size - 1);\n let node = this.head;\n while (index--) {\n node = node.next;\n }\n return this._deleteNode(node);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if a data structure is empty by comparing its size to zero.\n * @returns The method is returning a boolean value indicating whether the size of the object is 0 or\n * not.\n */\n isEmpty(): boolean {\n return this._size === 0;\n }\n\n /**\n * The function checks if a given element is an array with exactly two elements.\n * @param {any} rawElement - The `rawElement` parameter is of type `any`, which means it can be any\n * data type.\n * @returns a boolean value.\n */\n isEntry(rawElement: any): rawElement is [K, V] {\n return Array.isArray(rawElement) && rawElement.length === 2;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `clear` function clears all the entries in a data structure and resets its properties.\n */\n clear(): void {\n this._noObjMap = {};\n this._size = 0;\n this._head = this._tail = this._sentinel.prev = this._sentinel.next = this._sentinel;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `clone` function creates a new instance of a `LinkedHashMap` with the same key-value pairs as\n * the original.\n * @returns The `clone()` method is returning a new instance of `LinkedHashMap<K, V>` that is a clone\n * of the original `LinkedHashMap` object.\n */\n clone(): LinkedHashMap<K, V> {\n const cloned = new LinkedHashMap<K, V>([], { hashFn: this._hashFn, objHashFn: this._objHashFn });\n for (const entry of this) {\n const [key, value] = entry;\n cloned.set(key, value);\n }\n return cloned;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new `LinkedHashMap` containing key-value pairs from the original\n * map that satisfy a given predicate function.\n * @param predicate - The `predicate` parameter is a callback function that takes four arguments:\n * `value`, `key`, `index`, and `this`. It should return a boolean value indicating whether the\n * current element should be included in the filtered map or not.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the `predicate` function. It is used when you want to bind a\n * specific object as the context for the `predicate` function. If `thisArg` is not provided, `this\n * @returns a new `LinkedHashMap` object that contains the key-value pairs from the original\n * `LinkedHashMap` object that satisfy the given predicate function.\n */\n filter(predicate: EntryCallback<K, V, boolean>, thisArg?: any): LinkedHashMap<K, V> {\n const filteredMap = new LinkedHashMap<K, V>();\n let index = 0;\n for (const [key, value] of this) {\n if (predicate.call(thisArg, key, value, index, this)) {\n filteredMap.set(key, value);\n }\n index++;\n }\n return filteredMap;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function in TypeScript creates a new `LinkedHashMap` by applying a callback function to\n * each key-value pair in the original map.\n * @param callback - The callback parameter is a function that will be called for each key-value pair\n * in the map. It takes four arguments: the value of the current key-value pair, the key of the\n * current key-value pair, the index of the current key-value pair, and the map itself. The callback\n * function should\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. If provided, the callback function will\n * be called with `thisArg` as its `this` value. If not provided, `this` will refer to the current\n * map\n * @returns a new `LinkedHashMap` object with the values mapped according to the provided callback\n * function.\n */\n map<MK, MV>(callback: EntryCallback<K, V, [MK, MV]>, thisArg?: any): LinkedHashMap<MK, MV> {\n const mappedMap = new LinkedHashMap<MK, MV>();\n let index = 0;\n for (const [key, value] of this) {\n const [newKey, newValue] = callback.call(thisArg, key, value, index, this);\n mappedMap.set(newKey, newValue);\n index++;\n }\n return mappedMap;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n * where n is the number of entries in the LinkedHashMap.\n *\n * The above function is an iterator that yields key-value pairs from a linked list.\n */\n protected *_getIterator() {\n let node = this.head;\n while (node !== this._sentinel) {\n yield [node.key, node.value] as [K, V];\n node = node.next;\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_deleteNode` function removes a node from a doubly linked list and updates the head and tail\n * pointers if necessary.\n * @param node - The `node` parameter is an instance of the `HashMapLinkedNode` class, which\n * represents a node in a linked list. It contains a key-value pair and references to the previous\n * and next nodes in the list.\n */\n protected _deleteNode(node: HashMapLinkedNode<K, V | undefined>): boolean {\n const { prev, next } = node;\n prev.next = next;\n next.prev = prev;\n\n if (node === this.head) {\n this._head = next;\n }\n\n if (node === this.tail) {\n this._tail = prev;\n }\n\n this._size -= 1;\n return true;\n }\n}\n","import { ElementCallback, LinearBaseOptions, ReduceLinearCallback } from '../../types';\nimport { IterableElementBase } from './iterable-element-base';\n\nexport class LinkedListNode<E = any> {\n constructor(value: E) {\n this._value = value;\n this._next = undefined;\n }\n\n protected _value: E;\n\n get value(): E {\n return this._value;\n }\n\n set value(value: E) {\n this._value = value;\n }\n\n protected _next: LinkedListNode<E> | undefined;\n\n get next(): LinkedListNode<E> | undefined {\n return this._next;\n }\n\n set next(value: LinkedListNode<E> | undefined) {\n this._next = value;\n }\n}\n\nexport abstract class LinearBase<\n E,\n R = any,\n NODE extends LinkedListNode<E> = LinkedListNode<E>\n> extends IterableElementBase<E, R> {\n /**\n * The constructor initializes the LinearBase class with optional options, setting the maximum length\n * if provided.\n * @param [options] - The `options` parameter is an optional object that can be passed to the\n * constructor. It is of type `LinearBaseOptions<E, R>`. The constructor checks if the `options`\n * object is provided and then extracts the `maxLen` property from it. If `maxLen` is a\n */\n protected constructor(options?: LinearBaseOptions<E, R>) {\n super(options);\n if (options) {\n const { maxLen } = options;\n if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0) this._maxLen = maxLen;\n }\n }\n\n abstract get length(): number;\n\n protected _maxLen: number = -1;\n\n get maxLen() {\n return this._maxLen;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function indexOf searches for a specified element starting from a given index in an array-like\n * object and returns the index of the first occurrence, or -1 if not found.\n * @param {E} searchElement - The `searchElement` parameter in the `indexOf` function represents the\n * element that you want to find within the array. The function will search for this element starting\n * from the `fromIndex` (if provided) up to the end of the array. If the `searchElement` is found\n * within the\n * @param {number} [fromIndex=0] - The `fromIndex` parameter in the `indexOf` function represents the\n * index at which to start searching for the `searchElement` within the array. If provided, the\n * search will begin at this index and continue to the end of the array. If `fromIndex` is not\n * specified, the default\n * @returns The `indexOf` method is returning the index of the `searchElement` if it is found in the\n * array starting from the `fromIndex`. If the `searchElement` is not found, it returns -1.\n */\n indexOf(searchElement: E, fromIndex: number = 0): number {\n // Boundary checks and adjustments\n if (this.length === 0) return -1;\n if (fromIndex < 0) fromIndex = this.length + fromIndex;\n if (fromIndex < 0) fromIndex = 0;\n\n // Iterating from the specified index to the end\n for (let i = fromIndex; i < this.length; i++) {\n const element = this.at(i);\n if (element === searchElement) return i;\n }\n\n return -1; // Not found\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `lastIndexOf` in TypeScript returns the index of the last occurrence of a specified\n * element in an array.\n * @param {E} searchElement - The `searchElement` parameter is the element that you want to find the\n * last index of within the array. The `lastIndexOf` method will search the array starting from the\n * `fromIndex` (or the end of the array if not specified) and return the index of the last occurrence\n * of the\n * @param {number} fromIndex - The `fromIndex` parameter in the `lastIndexOf` method specifies the\n * index at which to start searching for the `searchElement` in the array. By default, it starts\n * searching from the last element of the array (`this.length - 1`). If a specific `fromIndex` is\n * provided\n * @returns The last index of the `searchElement` in the array is being returned. If the\n * `searchElement` is not found in the array, -1 is returned.\n */\n lastIndexOf(searchElement: E, fromIndex: number = this.length - 1): number {\n if (this.length === 0) return -1;\n if (fromIndex >= this.length) fromIndex = this.length - 1;\n if (fromIndex < 0) fromIndex = this.length + fromIndex;\n\n for (let i = fromIndex; i >= 0; i--) {\n const element = this.at(i);\n if (element === searchElement) return i;\n }\n\n return -1;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `findIndex` function iterates over an array and returns the index of the first element that\n * satisfies the provided predicate function.\n * @param predicate - The `predicate` parameter in the `findIndex` function is a callback function\n * that takes three arguments: `item`, `index`, and the array `this`. It should return a boolean\n * value indicating whether the current element satisfies the condition being checked for.\n * @param {any} [thisArg] - The `thisArg` parameter in the `findIndex` function is an optional\n * parameter that specifies the value to use as `this` when executing the `predicate` function. If\n * provided, the `predicate` function will be called with `thisArg` as its `this` value. If `\n * @returns The `findIndex` method is returning the index of the first element in the array that\n * satisfies the provided predicate function. If no such element is found, it returns -1.\n */\n findIndex(predicate: ElementCallback<E, R, boolean>, thisArg?: any): number {\n for (let i = 0; i < this.length; i++) {\n const item = this.at(i);\n if (item !== undefined && predicate.call(thisArg, item, i, this)) return i;\n }\n return -1;\n }\n\n concat(...items: this[]): this;\n\n /**\n * Time Complexity: O(n + m)\n * Space Complexity: O(n + m)\n *\n * The `concat` function in TypeScript concatenates multiple items into a new list, handling both\n * individual elements and instances of `LinearBase`.\n * @param {(E | this)[]} items - The `concat` method takes in an array of items, where\n * each item can be either of type `E` or an instance of `LinearBase<E, R>`.\n * @returns The `concat` method is returning a new instance of the class that it belongs to, with the\n * items passed as arguments concatenated to it.\n */\n concat(...items: (E | this)[]): this {\n const newList = this.clone();\n\n for (const item of items) {\n if (item instanceof LinearBase) {\n newList.pushMany(item);\n } else {\n newList.push(item);\n }\n }\n\n return newList;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * The `sort` function in TypeScript sorts the elements of a collection using a specified comparison\n * function.\n * @param [compareFn] - The `compareFn` parameter is a function that defines the sort order. It takes\n * two elements `a` and `b` as input and returns a number indicating their relative order. If the\n * returned value is negative, `a` comes before `b`. If the returned value is positive, `\n * @returns The `sort` method is returning the instance of the object on which it is called (this),\n * after sorting the elements based on the provided comparison function (compareFn).\n */\n sort(compareFn?: (a: E, b: E) => number): this {\n const arr = this.toArray();\n arr.sort(compareFn);\n this.clear();\n for (const item of arr) this.push(item);\n return this;\n }\n\n /**\n * Time Complexity: O(n + m)\n * Space Complexity: O(m)\n *\n * The `splice` function in TypeScript removes elements from an array and optionally inserts new\n * elements at the specified index.\n * @param {number} start - The `start` parameter in the `splice` method indicates the index at which\n * to start modifying the array. If `start` is a negative number, it will count from the end of the\n * array.\n * @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the\n * number of elements to remove from the array starting at the specified `start` index. If\n * `deleteCount` is not provided or is 0, no elements are removed, and only new elements are inserted\n * at the `start`\n * @param {E[]} items - The `items` parameter in the `splice` method represents the elements that\n * will be inserted into the array at the specified `start` index. These elements can be of any type\n * and you can pass multiple elements separated by commas. The `splice` method will insert these\n * items into the array at the\n * @returns The `splice` method returns a list of elements that were removed from the original list\n * during the operation.\n */\n splice(start: number, deleteCount: number = 0, ...items: E[]): this {\n const removedList = this._createInstance();\n\n // Handling negative indexes and bounds\n start = start < 0 ? this.length + start : start;\n start = Math.max(0, Math.min(start, this.length));\n deleteCount = Math.max(0, Math.min(deleteCount, this.length - start));\n\n // Delete elements\n for (let i = 0; i < deleteCount; i++) {\n const removed = this.deleteAt(start); // Always delete the start position\n if (removed !== undefined) {\n removedList.push(removed); // Add removed elements to the returned list\n }\n }\n\n // Insert new element\n for (let i = 0; i < items.length; i++) {\n this.addAt(start + i, items[i]); // Insert new elements one by one at the current position\n }\n\n return removedList; // Returns a list of removed elements\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `join` function in TypeScript returns a string by joining the elements of an array with a\n * specified separator.\n * @param {string} [separator=,] - The `separator` parameter is a string that specifies the character\n * or characters that will be used to separate each element when joining them into a single string.\n * By default, the separator is set to a comma (`,`), but you can provide a different separator if\n * needed.\n * @returns The `join` method is being returned, which takes an optional `separator` parameter\n * (defaulting to a comma) and returns a string created by joining all elements of the array after\n * converting it to an array.\n */\n join(separator: string = ','): string {\n return this.toArray().join(separator);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `toReversedArray` takes an array and returns a new array with its elements in reverse\n * order.\n * @returns The `toReversedArray()` function returns an array of elements of type `E` in reverse\n * order.\n */\n toReversedArray(): E[] {\n const array: E[] = [];\n for (let i = this.length - 1; i >= 0; i--) {\n array.push(this.at(i)!);\n }\n return array;\n }\n\n reduceRight(callbackfn: ReduceLinearCallback<E>): E;\n\n reduceRight(callbackfn: ReduceLinearCallback<E>, initialValue: E): E;\n\n reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue: U): U;\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `reduceRight` function in TypeScript iterates over an array from right to left and applies a\n * callback function to each element, accumulating a single result.\n * @param callbackfn - The `callbackfn` parameter in the `reduceRight` method is a function that will\n * be called on each element in the array from right to left. It takes four arguments:\n * @param {U} [initialValue] - The `initialValue` parameter in the `reduceRight` method is an\n * optional parameter that specifies the initial value of the accumulator. If provided, the\n * `accumulator` will start with this initial value before iterating over the elements of the array.\n * If `initialValue` is not provided, the accumulator will\n * @returns The `reduceRight` method is returning the final accumulated value after applying the\n * callback function to each element in the array from right to left.\n */\n reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue?: U): U {\n let accumulator = initialValue ?? (0 as U);\n for (let i = this.length - 1; i >= 0; i--) {\n accumulator = callbackfn(accumulator, this.at(i)!, i, this);\n }\n return accumulator;\n }\n\n /**\n * Time Complexity: O(m)\n * Space Complexity: O(m)\n *\n * The `slice` function in TypeScript creates a new instance by extracting a portion of elements from\n * the original instance based on the specified start and end indices.\n * @param {number} [start=0] - The `start` parameter in the `slice` method represents the index at\n * which to begin extracting elements from an array-like object. If no `start` parameter is provided,\n * the default value is 0, meaning the extraction will start from the beginning of the array.\n * @param {number} end - The `end` parameter in the `slice` method represents the index at which to\n * end the slicing. By default, if no `end` parameter is provided, it will slice until the end of the\n * array (i.e., `this.length`).\n * @returns The `slice` method is returning a new instance of the object with elements sliced from\n * the specified start index (default is 0) to the specified end index (default is the length of the\n * object).\n */\n slice(start: number = 0, end: number = this.length): this {\n start = start < 0 ? this.length + start : start;\n end = end < 0 ? this.length + end : end;\n\n const newList = this._createInstance();\n for (let i = start; i < end; i++) {\n newList.push(this.at(i)!);\n }\n return newList;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `fill` function in TypeScript fills a specified range in an array-like object with a given\n * value.\n * @param {E} value - The `value` parameter in the `fill` method represents the element that will be\n * used to fill the specified range in the array.\n * @param [start=0] - The `start` parameter specifies the index at which to start filling the array\n * with the specified value. If not provided, it defaults to 0, indicating the beginning of the\n * array.\n * @param end - The `end` parameter in the `fill` function represents the index at which the filling\n * of values should stop. It specifies the end of the range within the array where the `value` should\n * be filled.\n * @returns The `fill` method is returning the modified object (`this`) after filling the specified\n * range with the provided value.\n */\n fill(value: E, start = 0, end = this.length): this {\n // Handling negative indexes\n start = start < 0 ? this.length + start : start;\n end = end < 0 ? this.length + end : end;\n\n // Boundary processing\n if (start < 0) start = 0;\n if (end > this.length) end = this.length;\n if (start >= end) return this;\n\n // Iterate through the specified range and fill in the values\n for (let i = start; i < end; i++) {\n this.setAt(i, value);\n }\n\n return this;\n }\n\n abstract setAt(index: number, value: E): boolean;\n\n abstract override clone(): this;\n\n abstract reverse(): this;\n\n abstract push(elementOrNode: E | NODE): boolean;\n\n abstract pushMany(elements: Iterable<E> | Iterable<R> | Iterable<NODE>): boolean[];\n\n abstract delete(elementOrNode: E | NODE | undefined): boolean;\n\n abstract at(index: number): E | undefined;\n\n abstract deleteAt(pos: number): E | undefined;\n\n abstract addAt(index: number, newElementOrNode: E | NODE): boolean;\n\n protected abstract _createInstance(options?: LinearBaseOptions<E, R>): this;\n\n protected abstract _getReverseIterator(...args: any[]): IterableIterator<E>;\n}\n\nexport abstract class LinearLinkedBase<\n E,\n R = any,\n NODE extends LinkedListNode<E> = LinkedListNode<E>\n> extends LinearBase<E, R, NODE> {\n /**\n * The constructor initializes the LinearBase class with optional options, setting the maximum length\n * if provided and valid.\n * @param [options] - The `options` parameter is an optional object that can be passed to the\n * constructor. It is of type `LinearBaseOptions<E, R>`. This object may contain properties such as\n * `maxLen`, which is a number representing the maximum length. If `maxLen` is a positive integer,\n */\n protected constructor(options?: LinearBaseOptions<E, R>) {\n super(options);\n if (options) {\n const { maxLen } = options;\n if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0) this._maxLen = maxLen;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function overrides the indexOf method to improve performance by searching for an element in a\n * custom array implementation starting from a specified index.\n * @param {E} searchElement - The `searchElement` parameter is the element that you are searching for\n * within the array. The `indexOf` method will return the index of the first occurrence of this\n * element within the array.\n * @param {number} [fromIndex=0] - The `fromIndex` parameter in the `indexOf` method specifies the\n * index in the array at which to start the search for the `searchElement`. If provided, the search\n * will begin at the specified index and continue to the end of the array. If not provided, the\n * search will start at index\n * @returns The `indexOf` method is returning the index of the `searchElement` if it is found in the\n * array starting from the `fromIndex`. If the `searchElement` is not found, it returns -1.\n */\n override indexOf(searchElement: E, fromIndex: number = 0): number {\n // In order to improve performance, it is best to override this method in the subclass of the array implementation\n const iterator = this._getIterator();\n let current = iterator.next();\n\n let index = 0;\n while (index < fromIndex) {\n current = iterator.next();\n index++;\n }\n\n while (!current.done) {\n if (current.value === searchElement) return index;\n current = iterator.next();\n index++;\n }\n\n return -1;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function overrides the lastIndexOf method in TypeScript to improve performance by searching\n * for an element in reverse order starting from a specified index.\n * @param {E} searchElement - The `searchElement` parameter is the element that you want to find\n * within the array. The `lastIndexOf` method searches the array for this element starting from the\n * end of the array (or from the specified `fromIndex` if provided) and returns the index of the last\n * occurrence of the element\n * @param {number} fromIndex - The `fromIndex` parameter in the `lastIndexOf` method specifies the\n * index at which to start searching for the `searchElement` in the array. If provided, the search\n * will begin at this index and move towards the beginning of the array. If not provided, the search\n * will start at the\n * @returns The `lastIndexOf` method is being overridden to search for the `searchElement` starting\n * from the specified `fromIndex` (defaulting to the end of the array). It iterates over the array in\n * reverse order using a custom iterator `_getReverseIterator` and returns the index of the last\n * occurrence of the `searchElement` if found, or -1 if not found.\n */\n override lastIndexOf(searchElement: E, fromIndex: number = this.length - 1): number {\n // In order to improve performance, it is best to override this method in the subclass of the array implementation\n const iterator = this._getReverseIterator();\n let current = iterator.next();\n\n let index = this.length - 1;\n while (index > fromIndex) {\n current = iterator.next();\n index--;\n }\n\n while (!current.done) {\n if (current.value === searchElement) return index;\n current = iterator.next();\n index--;\n }\n\n return -1;\n }\n\n override concat(...items: LinearBase<E, R>[]): this;\n\n /**\n * Time Complexity: O(n + m)\n * Space Complexity: O(n + m)\n *\n * The `concat` function in TypeScript overrides the default behavior to concatenate items into a new\n * list, handling both individual elements and instances of `LinearBase`.\n * @param {(E | LinearBase<E, R>)[]} items - The `concat` method you provided takes in a variable\n * number of arguments of type `E` or `LinearBase<E, R>`. The method concatenates these items to the\n * current list and returns a new list with the concatenated items.\n * @returns The `concat` method is returning a new instance of the class that it belongs to, with the\n * items passed as arguments concatenated to it.\n */\n override concat(...items: (E | LinearBase<E, R>)[]): this {\n const newList = this.clone();\n\n for (const item of items) {\n if (item instanceof LinearBase) {\n newList.pushMany(item);\n } else {\n newList.push(item);\n }\n }\n\n return newList;\n }\n\n /**\n * Time Complexity: O(m)\n * Space Complexity: O(m)\n *\n * The `slice` method is overridden to improve performance by creating a new instance and iterating\n * through the array to extract a subset based on the specified start and end indices.\n * @param {number} [start=0] - The `start` parameter in the `slice` method specifies the index at\n * which to begin extracting elements from the array. If no `start` parameter is provided, the\n * default value is 0, indicating that extraction should start from the beginning of the array.\n * @param {number} end - The `end` parameter in the `slice` method represents the index at which to\n * end the slicing of the array. If not provided, it defaults to the length of the array.\n * @returns The `slice` method is returning a new instance of the array implementation with elements\n * sliced from the original array based on the `start` and `end` parameters.\n */\n override slice(start: number = 0, end: number = this.length): this {\n // In order to improve performance, it is best to override this method in the subclass of the array implementation\n start = start < 0 ? this.length + start : start;\n end = end < 0 ? this.length + end : end;\n\n const newList = this._createInstance();\n const iterator = this._getIterator();\n let current = iterator.next();\n let c = 0;\n while (c < start) {\n current = iterator.next();\n c++;\n }\n for (let i = start; i < end; i++) {\n newList.push(current.value);\n current = iterator.next();\n }\n\n return newList;\n }\n\n /**\n * Time Complexity: O(n + m)\n * Space Complexity: O(m)\n *\n * The function overrides the splice method to handle deletion and insertion of elements in a data\n * structure while returning the removed elements.\n * @param {number} start - The `start` parameter in the `splice` method indicates the index at which\n * to start modifying the array.\n * @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the\n * number of elements to remove from the array starting at the specified `start` index. If\n * `deleteCount` is not provided, it defaults to 0, meaning no elements will be removed but new\n * elements can still be inserted at\n * @param {E[]} items - The `items` parameter in the `splice` method represents the elements that\n * will be inserted into the array at the specified `start` index. These elements can be of any type\n * and there can be multiple elements passed as arguments to be inserted into the array.\n * @returns The `splice` method is returning a new instance of the data structure that was modified\n * by removing elements specified by the `start` and `deleteCount` parameters, and inserting new\n * elements provided in the `items` array.\n */\n override splice(start: number, deleteCount: number = 0, ...items: E[]): this {\n const removedList = this._createInstance(); // Used to store deleted elements\n\n // Handling negative indexes\n start = start < 0 ? this.length + start : start;\n start = Math.max(0, Math.min(start, this.length)); // Correct start range\n deleteCount = Math.max(0, deleteCount); // Make sure deleteCount is non-negative\n\n let currentIndex = 0;\n let currentNode: NODE | undefined = undefined;\n let previousNode: NODE | undefined = undefined;\n\n // Find the starting point using an iterator\n const iterator = this._getNodeIterator();\n for (const node of iterator) {\n if (currentIndex === start) {\n currentNode = node; // Find the starting node\n break;\n }\n previousNode = node; // Update the previous node\n currentIndex++;\n }\n\n // Delete nodes\n for (let i = 0; i < deleteCount && currentNode; i++) {\n removedList.push(currentNode.value); // Store the deleted value in removedList\n const nextNode = currentNode.next; // Save next node\n this.delete(currentNode); // Delete current node\n currentNode = nextNode as NODE;\n }\n\n // Insert new value\n for (let i = 0; i < items.length; i++) {\n if (previousNode) {\n this.addAfter(previousNode, items[i]); // Insert after previousNode\n previousNode = previousNode.next as NODE; // Move to newly inserted node\n } else {\n this.addAt(0, items[i]); // Insert at the head of the linked list\n previousNode = this._getNodeIterator().next().value; // Update the head node to be the first inserted node\n }\n }\n\n return removedList;\n }\n\n override reduceRight(callbackfn: ReduceLinearCallback<E>): E;\n\n override reduceRight(callbackfn: ReduceLinearCallback<E>, initialValue: E): E;\n\n override reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue: U): U;\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `reduceRight` iterates over an array in reverse order and applies a callback function\n * to each element, accumulating a single result.\n * @param callbackfn - The `callbackfn` parameter is a function that will be called on each element\n * of the array from right to left. It takes four arguments:\n * @param {U} [initialValue] - The `initialValue` parameter is an optional value that is used as the\n * initial accumulator value in the reduce operation. If provided, the reduce operation starts with\n * this initial value and iterates over the elements of the array, applying the callback function to\n * each element and the current accumulator value. If `initial\n * @returns The `reduceRight` method is returning the final accumulated value after applying the\n * callback function to each element in the array from right to left.\n */\n override reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue?: U): U {\n let accumulator = initialValue ?? (0 as U);\n let index = this.length - 1;\n for (const item of this._getReverseIterator()) {\n accumulator = callbackfn(accumulator, item, index--, this);\n }\n return accumulator;\n }\n\n abstract override delete(elementOrNode: E | NODE | undefined): boolean;\n\n abstract addBefore(existingElementOrNode: E | NODE, newElementOrNode: E | NODE): boolean;\n\n abstract addAfter(existingElementOrNode: E | NODE, newElementOrNode: E | NODE): boolean;\n\n abstract getNodeAt(index: number): NODE | undefined;\n\n protected abstract _getNodeIterator(...args: any[]): IterableIterator<NODE>;\n\n // protected abstract _getReverseNodeIterator(...args: any[]): IterableIterator<NODE>;\n\n protected abstract _getPrevNode(node: NODE): NODE | undefined;\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { ElementCallback, SinglyLinkedListOptions } from '../../types';\nimport { LinearLinkedBase, LinkedListNode } from '../base/linear-base';\n\nexport class SinglyLinkedListNode<E = any> extends LinkedListNode<E> {\n /**\n * The constructor function initializes an instance of a class with a given value and sets the next property to undefined.\n * @param {E} value - The \"value\" parameter is of type E, which means it can be any data type. It represents the value that\n * will be stored in the node of a linked list.\n */\n constructor(value: E) {\n super(value);\n this._value = value;\n this._next = undefined;\n }\n\n protected override _next: SinglyLinkedListNode<E> | undefined;\n\n override get next(): SinglyLinkedListNode<E> | undefined {\n return this._next;\n }\n\n override set next(value: SinglyLinkedListNode<E> | undefined) {\n this._next = value;\n }\n}\n\n/**\n * 1. Node Structure: Each node contains three parts: a data field, a pointer (or reference) to the previous node, and a pointer to the next node. This structure allows traversal of the linked list in both directions.\n * 2. Bidirectional Traversal: Unlike doubly linked lists, singly linked lists can be easily traversed forwards but not backwards.\n * 3. No Centralized Index: Unlike arrays, elements in a linked list are not stored contiguously, so there is no centralized index. Accessing elements in a linked list typically requires traversing from the head or tail node.\n * 4. High Efficiency in Insertion and Deletion: Adding or removing elements in a linked list does not require moving other elements, making these operations more efficient than in arrays.\n * Caution: Although our linked list classes provide methods such as at, setAt, addAt, and indexOf that are based on array indices, their time complexity, like that of the native Array.lastIndexOf, is 𝑂(𝑛). If you need to use these methods frequently, you might want to consider other data structures, such as Deque or Queue (designed for random access). Similarly, since the native Array.shift method has a time complexity of 𝑂(𝑛), using an array to simulate a queue can be inefficient. In such cases, you should use Queue or Deque, as these data structures leverage deferred array rearrangement, effectively reducing the average time complexity to 𝑂(1).\n *\n */\nexport class SinglyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, SinglyLinkedListNode<E>> {\n constructor(\n elements: Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>> = [],\n options?: SinglyLinkedListOptions<E, R>\n ) {\n super(options);\n\n if (options) {\n }\n\n this.pushMany(elements);\n }\n\n protected _head: SinglyLinkedListNode<E> | undefined;\n\n get head(): SinglyLinkedListNode<E> | undefined {\n return this._head;\n }\n\n protected _tail: SinglyLinkedListNode<E> | undefined;\n\n get tail(): SinglyLinkedListNode<E> | undefined {\n return this._tail;\n }\n\n get first(): E | undefined {\n return this.head?.value;\n }\n\n get last(): E | undefined {\n return this.tail?.value;\n }\n\n protected _length: number = 0;\n\n get length(): number {\n return this._length;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `fromArray` function creates a new SinglyLinkedList instance and populates it with the elements from the given\n * array.\n * @param {E[]} data - The `data` parameter is an array of elements of type `E`.\n * @returns The `fromArray` function returns a `SinglyLinkedList` object.\n */\n static fromArray<E>(data: E[]) {\n const singlyLinkedList = new SinglyLinkedList<E>();\n for (const item of data) {\n singlyLinkedList.push(item);\n }\n return singlyLinkedList;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `push` function adds a new element or node to the end of a singly linked list.\n * @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the `push`\n * method can accept either an element of type `E` or a `SinglyLinkedListNode<E>` object.\n * @returns The `push` method is returning a boolean value, specifically `true`.\n */\n push(elementOrNode: E | SinglyLinkedListNode<E>): boolean {\n const newNode = this._ensureNode(elementOrNode);\n if (!this.head) {\n this._head = newNode;\n this._tail = newNode;\n } else {\n this.tail!.next = newNode;\n this._tail = newNode;\n }\n this._length++;\n if (this._maxLen > 0 && this.length > this._maxLen) this.shift();\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `pop` function removes and returns the value of the last element in a linked list.\n * @returns The method is returning the value of the element that is being popped from the end of the\n * list.\n */\n pop(): E | undefined {\n if (!this.head) return undefined;\n if (this.head === this.tail) {\n const value = this.head.value;\n this._head = undefined;\n this._tail = undefined;\n this._length--;\n return value;\n }\n\n let current = this.head;\n while (current.next !== this.tail) {\n current = current.next!;\n }\n const value = this.tail!.value;\n current.next = undefined;\n this._tail = current;\n this._length--;\n return value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `shift()` function removes and returns the value of the first element in a linked list.\n * @returns The value of the removed node.\n */\n shift(): E | undefined {\n if (!this.head) return undefined;\n const removedNode = this.head;\n this._head = this.head.next;\n this._length--;\n return removedNode.value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The unshift function adds a new element or node to the beginning of a singly linked list in\n * TypeScript.\n * @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the\n * `unshift` method can be either an element of type `E` or a `SinglyLinkedListNode` containing an\n * element of type `E`.\n * @returns The `unshift` method is returning a boolean value, specifically `true`.\n */\n unshift(elementOrNode: E | SinglyLinkedListNode<E>): boolean {\n const newNode = this._ensureNode(elementOrNode);\n if (!this.head) {\n this._head = newNode;\n this._tail = newNode;\n } else {\n newNode.next = this.head;\n this._head = newNode;\n }\n this._length++;\n return true;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The function `pushMany` iterates over elements and pushes them into a data structure, applying a\n * transformation function if provided.\n * @param {Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>>} elements - The `elements`\n * parameter in the `pushMany` function can accept an iterable containing elements of type `E`, `R`,\n * or `SinglyLinkedListNode<E>`.\n * @returns The `pushMany` function returns an array of boolean values indicating whether each\n * element was successfully pushed into the data structure.\n */\n pushMany(elements: Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>>) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) {\n ans.push(this.push(this.toElementFn(el as R)));\n continue;\n }\n ans.push(this.push(el as E | SinglyLinkedListNode<E>));\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The function `unshiftMany` iterates over elements and adds them to a data structure, optionally\n * converting them using a provided function.\n * @param {Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>>} elements - The `elements`\n * parameter in the `unshiftMany` function can accept an iterable containing elements of type `E`,\n * `R`, or `SinglyLinkedListNode<E>`. The function iterates over each element in the iterable and\n * performs an `unshift` operation on the linked list for each\n * @returns The `unshiftMany` function is returning an array of boolean values, where each value\n * represents the result of calling the `unshift` method on the current instance of the class.\n */\n unshiftMany(elements: Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>>) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) {\n ans.push(this.unshift(this.toElementFn(el as R)));\n continue;\n }\n ans.push(this.unshift(el as E | SinglyLinkedListNode<E>));\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * This function searches for a specific element in a singly linked list based on a given node or\n * predicate.\n * @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `get` method can be one of\n * the following types:\n * @returns The `get` method returns the value of the first node in the singly linked list that\n * satisfies the provided predicate function. If no such node is found, it returns `undefined`.\n */\n search(\n elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)\n ): E | undefined {\n const predicate = this._ensurePredicate(elementNodeOrPredicate);\n let current = this.head;\n while (current) {\n if (predicate(current)) return current.value;\n current = current.next;\n }\n return undefined;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `at` returns the value at a specified index in a linked list, or undefined if the index is out of range.\n * @param {number} index - The index parameter is a number that represents the position of the element we want to\n * retrieve from the list.\n * @returns The method `at(index: number): E | undefined` returns the value at the specified index in the linked list, or\n * `undefined` if the index is out of bounds.\n */\n at(index: number): E | undefined {\n if (index < 0 || index >= this._length) return undefined;\n let current = this.head;\n for (let i = 0; i < index; i++) {\n current = current!.next;\n }\n return current!.value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `isNode` in TypeScript checks if the input is an instance of `SinglyLinkedListNode`.\n * @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `isNode` function can be\n * one of the following types:\n * @returns The `isNode` function is checking if the `elementNodeOrPredicate` parameter is an\n * instance of `SinglyLinkedListNode<E>`. If it is, the function returns `true`, indicating that the\n * parameter is a `SinglyLinkedListNode<E>`. If it is not an instance of `SinglyLinkedListNode<E>`,\n * the function returns `false`.\n */\n isNode(\n elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)\n ): elementNodeOrPredicate is SinglyLinkedListNode<E> {\n return elementNodeOrPredicate instanceof SinglyLinkedListNode;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `getNodeAt` returns the node at a given index in a singly linked list.\n * @param {number} index - The `index` parameter is a number that represents the position of the node we want to\n * retrieve from the linked list. It indicates the zero-based index of the node we want to access.\n * @returns The method `getNodeAt(index: number)` returns a `SinglyLinkedListNode<E>` object if the node at the\n * specified index exists, or `undefined` if the index is out of bounds.\n */\n getNodeAt(index: number): SinglyLinkedListNode<E> | undefined {\n let current = this.head;\n for (let i = 0; i < index; i++) {\n current = current!.next;\n }\n return current;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `deleteAt` function removes an element at a specified index from a linked list and returns the removed element.\n * @param {number} index - The index parameter represents the position of the element that needs to be deleted in the\n * data structure. It is of type number.\n * @returns The method `deleteAt` returns the value of the node that was deleted, or `undefined` if the index is out of\n * bounds.\n */\n deleteAt(index: number): E | undefined {\n if (index < 0 || index >= this._length) return;\n let deleted: E | undefined;\n if (index === 0) {\n deleted = this.first;\n this.shift();\n return deleted;\n }\n\n const targetNode = this.getNodeAt(index);\n const prevNode = this._getPrevNode(targetNode!);\n\n if (prevNode && targetNode) {\n deleted = targetNode.value;\n prevNode.next = targetNode.next;\n if (targetNode === this.tail) this._tail = prevNode;\n this._length--;\n return deleted;\n }\n\n return;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The delete function removes a node with a specific value from a singly linked list.\n * @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter can accept either a value of type `E`\n * or a `SinglyLinkedListNode<E>` object.\n * @returns The `delete` method returns a boolean value. It returns `true` if the value or node is found and\n * successfully deleted from the linked list, and `false` if the value or node is not found in the linked list.\n */\n delete(elementOrNode: E | SinglyLinkedListNode<E> | undefined): boolean {\n if (elementOrNode === undefined || !this.head) return false;\n\n const node = this.isNode(elementOrNode) ? elementOrNode : this.getNode(elementOrNode);\n\n if (!node) return false;\n\n const prevNode = this._getPrevNode(node);\n\n if (!prevNode) {\n // The node is the head\n this._head = node.next;\n if (node === this.tail) this._tail = undefined;\n } else {\n prevNode.next = node.next;\n if (node === this.tail) this._tail = prevNode;\n }\n\n this._length--;\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `addAt` function inserts a new element or node at a specified index in a singly linked list.\n * @param {number} index - The `index` parameter represents the position at which you want to add a\n * new element or node in the linked list. It is a number that indicates the index where the new\n * element or node should be inserted.\n * @param {E | SinglyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the\n * `addAt` method can be either a value of type `E` or a `SinglyLinkedListNode<E>` object. This\n * parameter represents the element or node that you want to add to the linked list at the specified\n * index.\n * @returns The `addAt` method returns a boolean value - `true` if the element or node was\n * successfully added at the specified index, and `false` if the index is out of bounds.\n */\n addAt(index: number, newElementOrNode: E | SinglyLinkedListNode<E>): boolean {\n if (index < 0 || index > this._length) return false;\n\n if (index === 0) {\n this.unshift(newElementOrNode);\n return true;\n }\n if (index === this._length) {\n this.push(newElementOrNode);\n return true;\n }\n\n const newNode = this._ensureNode(newElementOrNode);\n const prevNode = this.getNodeAt(index - 1);\n newNode.next = prevNode!.next;\n prevNode!.next = newNode;\n this._length++;\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function setAt(index, value) updates the value at a specified index in a data structure if the\n * index exists.\n * @param {number} index - The `index` parameter in the `setAt` method refers to the position in the\n * data structure where you want to set a new value.\n * @param {E} value - The `value` parameter in the `setAt` method represents the new value that you\n * want to set at the specified index in the data structure.\n * @returns The `setAt` method returns a boolean value - `true` if the value at the specified index\n * is successfully updated, and `false` if the index is out of bounds (i.e., the node at that index\n * does not exist).\n */\n setAt(index: number, value: E): boolean {\n const node = this.getNodeAt(index);\n if (node) {\n node.value = value;\n return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if the length of a data structure is equal to zero and returns a boolean value indicating\n * whether it is empty or not.\n * @returns A boolean value indicating whether the length of the object is equal to 0.\n */\n isEmpty(): boolean {\n return this._length === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `clear` function resets the linked list by setting the head, tail, and length to undefined and 0 respectively.\n */\n clear(): void {\n this._head = undefined;\n this._tail = undefined;\n this._length = 0;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `reverse` function reverses the order of the nodes in a singly linked list.\n * @returns The reverse() method does not return anything. It has a return type of void.\n */\n reverse(): this {\n if (!this.head || this.head === this.tail) return this;\n\n let prev: SinglyLinkedListNode<E> | undefined = undefined;\n let current: SinglyLinkedListNode<E> | undefined = this.head;\n let next: SinglyLinkedListNode<E> | undefined = undefined;\n\n while (current) {\n next = current.next;\n current.next = prev;\n prev = current;\n current = next;\n }\n\n [this._head, this._tail] = [this.tail!, this.head!];\n return this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `getNode` in TypeScript searches for a node in a singly linked list based on a given\n * element, node, or predicate.\n * @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean) | undefined} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `getNode` method can be one\n * of the following types:\n * @returns The `getNode` method returns either a `SinglyLinkedListNode<E>` if a matching node is\n * found based on the provided predicate, or it returns `undefined` if no matching node is found or\n * if the input parameter is `undefined`.\n */\n getNode(\n elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean) | undefined\n ): SinglyLinkedListNode<E> | undefined {\n if (elementNodeOrPredicate === undefined) return;\n if (this.isNode(elementNodeOrPredicate)) return elementNodeOrPredicate;\n const predicate = this._ensurePredicate(elementNodeOrPredicate);\n let current = this.head;\n\n while (current) {\n if (predicate(current)) {\n return current;\n }\n current = current.next;\n }\n\n return undefined;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `addBefore` in TypeScript adds a new element or node before an existing element or\n * node in a singly linked list.\n * @param {E | SinglyLinkedListNode<E>} existingElementOrNode - existingElementOrNode represents the\n * element or node in the linked list before which you want to add a new element or node.\n * @param {E | SinglyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the\n * `addBefore` method represents the element or node that you want to insert before the existing\n * element or node in the linked list. This new element can be of type `E` or a\n * `SinglyLinkedListNode<E>`.\n * @returns The `addBefore` method returns a boolean value - `true` if the new element or node was\n * successfully added before the existing element or node, and `false` if the operation was\n * unsuccessful.\n */\n addBefore(\n existingElementOrNode: E | SinglyLinkedListNode<E>,\n newElementOrNode: E | SinglyLinkedListNode<E>\n ): boolean {\n const existingNode = this.getNode(existingElementOrNode);\n if (!existingNode) return false;\n\n const prevNode = this._getPrevNode(existingNode);\n const newNode = this._ensureNode(newElementOrNode);\n\n if (!prevNode) {\n // Add at the head\n this.unshift(newNode);\n } else {\n prevNode.next = newNode;\n newNode.next = existingNode;\n this._length++;\n }\n\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `addAfter` function in TypeScript adds a new element or node after an existing element or node\n * in a singly linked list.\n * @param {E | SinglyLinkedListNode<E>} existingElementOrNode - existingElementOrNode can be either\n * an element of type E or a SinglyLinkedListNode of type E.\n * @param {E | SinglyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the\n * `addAfter` method represents the element or node that you want to add after the existing element\n * or node in a singly linked list. This parameter can be either the value of the new element or a\n * reference to a `SinglyLinkedListNode` containing\n * @returns The `addAfter` method returns a boolean value - `true` if the new element or node was\n * successfully added after the existing element or node, and `false` if the existing element or node\n * was not found.\n */\n addAfter(existingElementOrNode: E | SinglyLinkedListNode<E>, newElementOrNode: E | SinglyLinkedListNode<E>): boolean {\n const existingNode: SinglyLinkedListNode<E> | undefined = this.getNode(existingElementOrNode);\n\n if (existingNode) {\n const newNode = this._ensureNode(newElementOrNode);\n newNode.next = existingNode.next;\n existingNode.next = newNode;\n if (existingNode === this.tail) {\n this._tail = newNode;\n }\n this._length++;\n return true;\n }\n\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `splice` in TypeScript overrides the default behavior to remove and insert elements\n * in a singly linked list while handling boundary cases.\n * @param {number} start - The `start` parameter in the `splice` method indicates the index at which\n * to start modifying the list. It specifies the position where elements will be added or removed.\n * @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the\n * number of elements to remove from the array starting at the specified `start` index. If\n * `deleteCount` is not provided, it defaults to 0, meaning no elements will be removed but new\n * elements can still be inserted at\n * @param {E[]} items - The `items` parameter in the `splice` method represents the elements to be\n * inserted into the list at the specified `start` index. These elements will be inserted in place of\n * the elements that are removed from the list. The `splice` method allows you to add new elements to\n * the list while\n * @returns The `splice` method is returning a `SinglyLinkedList` containing the elements that were\n * removed from the original list during the splice operation.\n */\n override splice(start: number, deleteCount: number = 0, ...items: E[]): this {\n const removedList = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });\n\n // If `start` is out of range, perform boundary processing\n start = Math.max(0, Math.min(start, this.length));\n deleteCount = Math.max(0, deleteCount);\n\n // Find the predecessor node of `start`\n const prevNode = start === 0 ? undefined : this.getNodeAt(start - 1);\n const startNode = prevNode ? prevNode.next : this.head;\n\n let current = startNode;\n for (let i = 0; i < deleteCount && current; i++) {\n removedList.push(current.value);\n current = current.next;\n }\n\n const nextNode = current;\n let lastInsertedNode: SinglyLinkedListNode<E> | undefined = undefined;\n\n for (const item of items) {\n const newNode = this._ensureNode(item);\n if (!lastInsertedNode) {\n if (prevNode) {\n prevNode.next = newNode;\n } else {\n this._head = newNode;\n }\n } else {\n lastInsertedNode.next = newNode;\n }\n lastInsertedNode = newNode;\n }\n\n // Connect new node to `nextNode`\n if (lastInsertedNode) {\n lastInsertedNode.next = nextNode;\n } else if (prevNode) {\n prevNode.next = nextNode;\n }\n\n // Update tail node and length\n if (!nextNode) {\n this._tail = lastInsertedNode || prevNode;\n }\n this._length += items.length - removedList.length;\n\n return removedList as this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `countOccurrences` iterates through a singly linked list and counts the occurrences\n * of a specified element or nodes that satisfy a given predicate.\n * @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementOrNode\n * - The `elementOrNode` parameter in the `countOccurrences` method can accept three types of values:\n * @returns The `countOccurrences` method returns the number of occurrences of the specified element,\n * node, or predicate function in the singly linked list.\n */\n countOccurrences(elementOrNode: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)): number {\n const predicate = this._ensurePredicate(elementOrNode);\n let count = 0;\n let current = this.head;\n\n while (current) {\n if (predicate(current)) {\n count++;\n }\n current = current.next;\n }\n\n return count;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `clone` function returns a new instance of the `SinglyLinkedList` class with the same values\n * as the original list.\n * @returns The `clone()` method is returning a new instance of the `SinglyLinkedList` class, which\n * is a clone of the original list.\n */\n clone(): this {\n return new SinglyLinkedList<E, R>(this, { toElementFn: this.toElementFn, maxLen: this._maxLen }) as this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new SinglyLinkedList by iterating over the elements of the current\n * list and applying a callback function to each element to determine if it should be included in the\n * filtered list.\n * @param callback - The callback parameter is a function that will be called for each element in the\n * list. It takes three arguments: the current element, the index of the current element, and the\n * list itself. The callback function should return a boolean value indicating whether the current\n * element should be included in the filtered list or not\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `SinglyLinkedList` object that contains the\n * elements that pass the filter condition specified by the `callback` function.\n */\n filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): SinglyLinkedList<E, R> {\n const filteredList = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredList.push(current);\n }\n index++;\n }\n return filteredList;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function takes a callback function and returns a new SinglyLinkedList with the results\n * of applying the callback to each element in the original list.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the original list. It takes three arguments: `current` (the current element being processed),\n * `index` (the index of the current element), and `this` (the original list). It should return a\n * value\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to\n * convert the raw element (`RR`) to the desired element type (`T`). It takes the raw element as\n * input and returns the converted element. If this parameter is not provided, the raw element will\n * be used as is.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `SinglyLinkedList` class with the mapped elements.\n */\n map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): SinglyLinkedList<EM, RM> {\n const mappedList = new SinglyLinkedList<EM, RM>([], { toElementFn, maxLen: this._maxLen });\n let index = 0;\n for (const current of this) {\n mappedList.push(callback.call(thisArg, current, index, this));\n index++;\n }\n\n return mappedList;\n }\n\n /**\n * The function `_createInstance` returns a new instance of `SinglyLinkedList` with the specified\n * options.\n * @param [options] - The `options` parameter in the `_createInstance` method is of type\n * `SinglyLinkedListOptions<E, R>`, which is used to configure the behavior of the `SinglyLinkedList`\n * instance being created. It is an optional parameter, meaning it can be omitted when calling the\n * method.\n * @returns An instance of the `SinglyLinkedList` class with an empty array and the provided options\n * is being returned.\n */\n protected override _createInstance(options?: SinglyLinkedListOptions<E, R>): this {\n return new SinglyLinkedList<E, R>([], options) as this;\n }\n\n /**\n * The function `_getIterator` returns an iterable iterator that yields the values of a linked list.\n */\n protected *_getIterator(): IterableIterator<E> {\n let current = this.head;\n\n while (current) {\n yield current.value;\n current = current.next;\n }\n }\n\n /**\n * The function returns an iterator that iterates over the elements of a collection in reverse order.\n */\n protected *_getReverseIterator(): IterableIterator<E> {\n const reversedArr = [...this].reverse();\n\n for (const item of reversedArr) {\n yield item;\n }\n }\n\n /**\n * The function `_getNodeIterator` returns an iterator that iterates over the nodes of a singly\n * linked list.\n */\n protected *_getNodeIterator(): IterableIterator<SinglyLinkedListNode<E>> {\n let current = this.head;\n\n while (current) {\n yield current;\n current = current.next;\n }\n }\n\n // protected *_getReverseNodeIterator(): IterableIterator<SinglyLinkedListNode<E>> {\n // const reversedArr = [...this._getNodeIterator()].reverse();\n //\n // for (const item of reversedArr) {\n // yield item;\n // }\n // }\n\n /**\n * The _isPredicate function in TypeScript checks if the input is a function that takes a\n * SinglyLinkedListNode as an argument and returns a boolean.\n * @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following types:\n * @returns The _isPredicate method is returning a boolean value based on whether the\n * elementNodeOrPredicate parameter is a function or not. If the elementNodeOrPredicate is a\n * function, the method will return true, indicating that it is a predicate function. If it is not a\n * function, the method will return false.\n */\n protected _isPredicate(\n elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)\n ): elementNodeOrPredicate is (node: SinglyLinkedListNode<E>) => boolean {\n return typeof elementNodeOrPredicate === 'function';\n }\n\n /**\n * The function `_ensureNode` ensures that the input is a valid node and returns it, creating a new\n * node if necessary.\n * @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter can be either\n * an element of type `E` or a `SinglyLinkedListNode` containing an element of type `E`.\n * @returns A SinglyLinkedListNode<E> object is being returned.\n */\n protected _ensureNode(elementOrNode: E | SinglyLinkedListNode<E>) {\n if (this.isNode(elementOrNode)) return elementOrNode;\n\n return new SinglyLinkedListNode<E>(elementOrNode);\n }\n\n /**\n * The function `_ensurePredicate` in TypeScript ensures that the input is either a node, a predicate\n * function, or a value to compare with the node's value.\n * @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following types:\n * @returns A function is being returned. If the input `elementNodeOrPredicate` is already a node, a\n * function is returned that checks if a given node is equal to the input node. If the input is a\n * predicate function, it is returned as is. If the input is neither a node nor a predicate function,\n * a function is returned that checks if a given node's value is equal to the input\n */\n protected _ensurePredicate(\n elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)\n ) {\n if (this.isNode(elementNodeOrPredicate)) return (node: SinglyLinkedListNode<E>) => node === elementNodeOrPredicate;\n\n if (this._isPredicate(elementNodeOrPredicate)) return elementNodeOrPredicate;\n\n return (node: SinglyLinkedListNode<E>) => node.value === elementNodeOrPredicate;\n }\n\n /**\n * The function `_getPrevNode` returns the node before a given node in a singly linked list.\n * @param node - The `node` parameter in the `_getPrevNode` method is a reference to a node in a\n * singly linked list. The method is used to find the node that comes before the given node in the\n * linked list.\n * @returns The `_getPrevNode` method returns either the previous node of the input node in a singly\n * linked list or `undefined` if the input node is the head of the list or if the input node is not\n * found in the list.\n */\n protected _getPrevNode(node: SinglyLinkedListNode<E>): SinglyLinkedListNode<E> | undefined {\n if (!this.head || this.head === node) return undefined;\n\n let current = this.head;\n while (current.next && current.next !== node) {\n current = current.next;\n }\n\n return current.next === node ? current : undefined;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { DoublyLinkedListOptions, ElementCallback } from '../../types';\nimport { LinearLinkedBase, LinkedListNode } from '../base/linear-base';\n\nexport class DoublyLinkedListNode<E = any> extends LinkedListNode<E> {\n /**\n * The constructor function initializes the value, next, and previous properties of an object.\n * @param {E} value - The \"value\" parameter is the value that will be stored in the node. It can be of any data type, as it\n * is defined as a generic type \"E\".\n */\n constructor(value: E) {\n super(value);\n this._value = value;\n this._next = undefined;\n this._prev = undefined;\n }\n\n protected override _next: DoublyLinkedListNode<E> | undefined;\n\n override get next(): DoublyLinkedListNode<E> | undefined {\n return this._next;\n }\n\n override set next(value: DoublyLinkedListNode<E> | undefined) {\n this._next = value;\n }\n\n protected _prev: DoublyLinkedListNode<E> | undefined;\n\n get prev(): DoublyLinkedListNode<E> | undefined {\n return this._prev;\n }\n\n set prev(value: DoublyLinkedListNode<E> | undefined) {\n this._prev = value;\n }\n}\n\n/**\n * 1. Node Structure: Each node contains three parts: a data field, a pointer (or reference) to the previous node, and a pointer to the next node. This structure allows traversal of the linked list in both directions.\n * 2. Bidirectional Traversal: Unlike singly linked lists, doubly linked lists can be easily traversed forwards or backwards. This makes insertions and deletions in the list more flexible and efficient.\n * 3. No Centralized Index: Unlike arrays, elements in a linked list are not stored contiguously, so there is no centralized index. Accessing elements in a linked list typically requires traversing from the head or tail node.\n * 4. High Efficiency in Insertion and Deletion: Adding or removing elements in a linked list does not require moving other elements, making these operations more efficient than in arrays.\n * Caution: Although our linked list classes provide methods such as at, setAt, addAt, and indexOf that are based on array indices, their time complexity, like that of the native Array.lastIndexOf, is 𝑂(𝑛). If you need to use these methods frequently, you might want to consider other data structures, such as Deque or Queue (designed for random access). Similarly, since the native Array.shift method has a time complexity of 𝑂(𝑛), using an array to simulate a queue can be inefficient. In such cases, you should use Queue or Deque, as these data structures leverage deferred array rearrangement, effectively reducing the average time complexity to 𝑂(1).\n * @example\n * // text editor operation history\n * const actions = [\n * { type: 'insert', content: 'first line of text' },\n * { type: 'insert', content: 'second line of text' },\n * { type: 'delete', content: 'delete the first line' }\n * ];\n * const editorHistory = new DoublyLinkedList<{ type: string; content: string }>(actions);\n *\n * console.log(editorHistory.last?.type); // 'delete'\n * console.log(editorHistory.pop()?.content); // 'delete the first line'\n * console.log(editorHistory.last?.type); // 'insert'\n * @example\n * // Browser history\n * const browserHistory = new DoublyLinkedList<string>();\n *\n * browserHistory.push('home page');\n * browserHistory.push('search page');\n * browserHistory.push('details page');\n *\n * console.log(browserHistory.last); // 'details page'\n * console.log(browserHistory.pop()); // 'details page'\n * console.log(browserHistory.last); // 'search page'\n * @example\n * // Use DoublyLinkedList to implement music player\n * // Define the Song interface\n * interface Song {\n * title: string;\n * artist: string;\n * duration: number; // duration in seconds\n * }\n *\n * class Player {\n * private playlist: DoublyLinkedList<Song>;\n * private currentSong: ReturnType<typeof this.playlist.getNodeAt> | undefined;\n *\n * constructor(songs: Song[]) {\n * this.playlist = new DoublyLinkedList<Song>();\n * songs.forEach(song => this.playlist.push(song));\n * this.currentSong = this.playlist.head;\n * }\n *\n * // Play the next song in the playlist\n * playNext(): Song | undefined {\n * if (!this.currentSong?.next) {\n * this.currentSong = this.playlist.head; // Loop to the first song\n * } else {\n * this.currentSong = this.currentSong.next;\n * }\n * return this.currentSong?.value;\n * }\n *\n * // Play the previous song in the playlist\n * playPrevious(): Song | undefined {\n * if (!this.currentSong?.prev) {\n * this.currentSong = this.playlist.tail; // Loop to the last song\n * } else {\n * this.currentSong = this.currentSong.prev;\n * }\n * return this.currentSong?.value;\n * }\n *\n * // Get the current song\n * getCurrentSong(): Song | undefined {\n * return this.currentSong?.value;\n * }\n *\n * // Loop through the playlist twice\n * loopThroughPlaylist(): Song[] {\n * const playedSongs: Song[] = [];\n * const initialNode = this.currentSong;\n *\n * // Loop through the playlist twice\n * for (let i = 0; i < this.playlist.length * 2; i++) {\n * playedSongs.push(this.currentSong!.value);\n * this.currentSong = this.currentSong!.next || this.playlist.head; // Loop back to the start if needed\n * }\n *\n * // Reset the current song to the initial song\n * this.currentSong = initialNode;\n * return playedSongs;\n * }\n * }\n *\n * const songs = [\n * { title: 'Bohemian Rhapsody', artist: 'Queen', duration: 354 },\n * { title: 'Hotel California', artist: 'Eagles', duration: 391 },\n * { title: 'Shape of You', artist: 'Ed Sheeran', duration: 233 },\n * { title: 'Billie Jean', artist: 'Michael Jackson', duration: 294 }\n * ];\n * let player = new Player(songs);\n * // should play the next song\n * player = new Player(songs);\n * const firstSong = player.getCurrentSong();\n * const nextSong = player.playNext();\n *\n * // Expect the next song to be \"Hotel California by Eagles\"\n * console.log(nextSong); // { title: 'Hotel California', artist: 'Eagles', duration: 391 }\n * console.log(firstSong); // { title: 'Bohemian Rhapsody', artist: 'Queen', duration: 354 }\n *\n * // should play the previous song\n * player = new Player(songs);\n * player.playNext(); // Move to the second song\n * const currentSong = player.getCurrentSong();\n * const previousSong = player.playPrevious();\n *\n * // Expect the previous song to be \"Bohemian Rhapsody by Queen\"\n * console.log(previousSong); // { title: 'Bohemian Rhapsody', artist: 'Queen', duration: 354 }\n * console.log(currentSong); // { title: 'Hotel California', artist: 'Eagles', duration: 391 }\n *\n * // should loop to the first song when playing next from the last song\n * player = new Player(songs);\n * player.playNext(); // Move to the second song\n * player.playNext(); // Move to the third song\n * player.playNext(); // Move to the fourth song\n *\n * const nextSongToFirst = player.playNext(); // Should loop to the first song\n *\n * // Expect the next song to be \"Bohemian Rhapsody by Queen\"\n * console.log(nextSongToFirst); // { title: 'Bohemian Rhapsody', artist: 'Queen', duration: 354 }\n *\n * // should loop to the last song when playing previous from the first song\n * player = new Player(songs);\n * player.playNext(); // Move to the first song\n * player.playNext(); // Move to the second song\n * player.playNext(); // Move to the third song\n * player.playNext(); // Move to the fourth song\n *\n * const previousToLast = player.playPrevious(); // Should loop to the last song\n *\n * // Expect the previous song to be \"Billie Jean by Michael Jackson\"\n * console.log(previousToLast); // { title: 'Billie Jean', artist: 'Michael Jackson', duration: 294 }\n *\n * // should loop through the entire playlist\n * player = new Player(songs);\n * const playedSongs = player.loopThroughPlaylist();\n *\n * // The expected order of songs for two loops\n * console.log(playedSongs); // [\n * // { title: 'Bohemian Rhapsody', artist: 'Queen', duration: 354 },\n * // { title: 'Hotel California', artist: 'Eagles', duration: 391 },\n * // { title: 'Shape of You', artist: 'Ed Sheeran', duration: 233 },\n * // { title: 'Billie Jean', artist: 'Michael Jackson', duration: 294 },\n * // { title: 'Bohemian Rhapsody', artist: 'Queen', duration: 354 },\n * // { title: 'Hotel California', artist: 'Eagles', duration: 391 },\n * // { title: 'Shape of You', artist: 'Ed Sheeran', duration: 233 },\n * // { title: 'Billie Jean', artist: 'Michael Jackson', duration: 294 }\n * // ]\n * @example\n * // Use DoublyLinkedList to implement LRU cache\n * interface CacheEntry<K, V> {\n * key: K;\n * value: V;\n * }\n *\n * class LRUCache<K = string, V = any> {\n * private readonly capacity: number;\n * private list: DoublyLinkedList<CacheEntry<K, V>>;\n * private map: Map<K, DoublyLinkedListNode<CacheEntry<K, V>>>;\n *\n * constructor(capacity: number) {\n * if (capacity <= 0) {\n * throw new Error('lru cache capacity must be greater than 0');\n * }\n * this.capacity = capacity;\n * this.list = new DoublyLinkedList<CacheEntry<K, V>>();\n * this.map = new Map<K, DoublyLinkedListNode<CacheEntry<K, V>>>();\n * }\n *\n * // Get cached value\n * get(key: K): V | undefined {\n * const node = this.map.get(key);\n *\n * if (!node) return undefined;\n *\n * // Move the visited node to the head of the linked list (most recently used)\n * this.moveToFront(node);\n *\n * return node.value.value;\n * }\n *\n * // Set cache value\n * set(key: K, value: V): void {\n * // Check if it already exists\n * const node = this.map.get(key);\n *\n * if (node) {\n * // Update value and move to head\n * node.value.value = value;\n * this.moveToFront(node);\n * return;\n * }\n *\n * // Check capacity\n * if (this.list.length >= this.capacity) {\n * // Delete the least recently used element (the tail of the linked list)\n * const removedNode = this.list.tail;\n * if (removedNode) {\n * this.map.delete(removedNode.value.key);\n * this.list.pop();\n * }\n * }\n *\n * // Create new node and add to head\n * const newEntry: CacheEntry<K, V> = { key, value };\n * this.list.unshift(newEntry);\n *\n * // Save node reference in map\n * const newNode = this.list.head;\n * if (newNode) {\n * this.map.set(key, newNode);\n * }\n * }\n *\n * // Move the node to the head of the linked list\n * private moveToFront(node: DoublyLinkedListNode<CacheEntry<K, V>>): void {\n * this.list.delete(node);\n * this.list.unshift(node.value);\n * }\n *\n * // Delete specific key\n * delete(key: K): boolean {\n * const node = this.map.get(key);\n * if (!node) return false;\n *\n * // Remove from linked list\n * this.list.delete(node);\n * // Remove from map\n * this.map.delete(key);\n *\n * return true;\n * }\n *\n * // Clear cache\n * clear(): void {\n * this.list.clear();\n * this.map.clear();\n * }\n *\n * // Get the current cache length\n * get length(): number {\n * return this.list.length;\n * }\n *\n * // Check if it is empty\n * get isEmpty(): boolean {\n * return this.list.isEmpty();\n * }\n * }\n *\n * // should set and get values correctly\n * const cache = new LRUCache<string, number>(3);\n * cache.set('a', 1);\n * cache.set('b', 2);\n * cache.set('c', 3);\n *\n * console.log(cache.get('a')); // 1\n * console.log(cache.get('b')); // 2\n * console.log(cache.get('c')); // 3\n *\n * // The least recently used element should be evicted when capacity is exceeded\n * cache.clear();\n * cache.set('a', 1);\n * cache.set('b', 2);\n * cache.set('c', 3);\n * cache.set('d', 4); // This will eliminate 'a'\n *\n * console.log(cache.get('a')); // undefined\n * console.log(cache.get('b')); // 2\n * console.log(cache.get('c')); // 3\n * console.log(cache.get('d')); // 4\n *\n * // The priority of an element should be updated when it is accessed\n * cache.clear();\n * cache.set('a', 1);\n * cache.set('b', 2);\n * cache.set('c', 3);\n *\n * cache.get('a'); // access 'a'\n * cache.set('d', 4); // This will eliminate 'b'\n *\n * console.log(cache.get('a')); // 1\n * console.log(cache.get('b')); // undefined\n * console.log(cache.get('c')); // 3\n * console.log(cache.get('d')); // 4\n *\n * // Should support updating existing keys\n * cache.clear();\n * cache.set('a', 1);\n * cache.set('a', 10);\n *\n * console.log(cache.get('a')); // 10\n *\n * // Should support deleting specified keys\n * cache.clear();\n * cache.set('a', 1);\n * cache.set('b', 2);\n *\n * console.log(cache.delete('a')); // true\n * console.log(cache.get('a')); // undefined\n * console.log(cache.length); // 1\n *\n * // Should support clearing cache\n * cache.clear();\n * cache.set('a', 1);\n * cache.set('b', 2);\n * cache.clear();\n *\n * console.log(cache.length); // 0\n * console.log(cache.isEmpty); // true\n * @example\n * // finding lyrics by timestamp in Coldplay's \"Fix You\"\n * // Create a DoublyLinkedList to store song lyrics with timestamps\n * const lyricsList = new DoublyLinkedList<{ time: number; text: string }>();\n *\n * // Detailed lyrics with precise timestamps (in milliseconds)\n * const lyrics = [\n * { time: 0, text: \"When you try your best, but you don't succeed\" },\n * { time: 4000, text: 'When you get what you want, but not what you need' },\n * { time: 8000, text: \"When you feel so tired, but you can't sleep\" },\n * { time: 12000, text: 'Stuck in reverse' },\n * { time: 16000, text: 'And the tears come streaming down your face' },\n * { time: 20000, text: \"When you lose something you can't replace\" },\n * { time: 24000, text: 'When you love someone, but it goes to waste' },\n * { time: 28000, text: 'Could it be worse?' },\n * { time: 32000, text: 'Lights will guide you home' },\n * { time: 36000, text: 'And ignite your bones' },\n * { time: 40000, text: 'And I will try to fix you' }\n * ];\n *\n * // Populate the DoublyLinkedList with lyrics\n * lyrics.forEach(lyric => lyricsList.push(lyric));\n *\n * // Test different scenarios of lyric synchronization\n *\n * // 1. Find lyric at exact timestamp\n * const exactTimeLyric = lyricsList.getBackward(lyric => lyric.value.time <= 36000);\n * console.log(exactTimeLyric?.text); // 'And ignite your bones'\n *\n * // 2. Find lyric between timestamps\n * const betweenTimeLyric = lyricsList.getBackward(lyric => lyric.value.time <= 22000);\n * console.log(betweenTimeLyric?.text); // \"When you lose something you can't replace\"\n *\n * // 3. Find first lyric when timestamp is less than first entry\n * const earlyTimeLyric = lyricsList.getBackward(lyric => lyric.value.time <= -1000);\n * console.log(earlyTimeLyric); // undefined\n *\n * // 4. Find last lyric when timestamp is after last entry\n * const lateTimeLyric = lyricsList.getBackward(lyric => lyric.value.time <= 50000);\n * console.log(lateTimeLyric?.text); // 'And I will try to fix you'\n * @example\n * // cpu process schedules\n * class Process {\n * constructor(\n * public id: number,\n * public priority: number\n * ) {}\n *\n * execute(): string {\n * return `Process ${this.id} executed.`;\n * }\n * }\n *\n * class Scheduler {\n * private queue: DoublyLinkedList<Process>;\n *\n * constructor() {\n * this.queue = new DoublyLinkedList<Process>();\n * }\n *\n * addProcess(process: Process): void {\n * // Insert processes into a queue based on priority, keeping priority in descending order\n * let current = this.queue.head;\n * while (current && current.value.priority >= process.priority) {\n * current = current.next;\n * }\n *\n * if (!current) {\n * this.queue.push(process);\n * } else {\n * this.queue.addBefore(current, process);\n * }\n * }\n *\n * executeNext(): string | undefined {\n * // Execute tasks at the head of the queue in order\n * const process = this.queue.shift();\n * return process ? process.execute() : undefined;\n * }\n *\n * listProcesses(): string[] {\n * return this.queue.toArray().map(process => `Process ${process.id} (Priority: ${process.priority})`);\n * }\n *\n * clear(): void {\n * this.queue.clear();\n * }\n * }\n *\n * // should add processes based on priority\n * let scheduler = new Scheduler();\n * scheduler.addProcess(new Process(1, 10));\n * scheduler.addProcess(new Process(2, 20));\n * scheduler.addProcess(new Process(3, 15));\n *\n * console.log(scheduler.listProcesses()); // [\n * // 'Process 2 (Priority: 20)',\n * // 'Process 3 (Priority: 15)',\n * // 'Process 1 (Priority: 10)'\n * // ]\n *\n * // should execute the highest priority process\n * scheduler = new Scheduler();\n * scheduler.addProcess(new Process(1, 10));\n * scheduler.addProcess(new Process(2, 20));\n *\n * console.log(scheduler.executeNext()); // 'Process 2 executed.'\n * console.log(scheduler.listProcesses()); // ['Process 1 (Priority: 10)']\n *\n * // should clear all processes\n * scheduler = new Scheduler();\n * scheduler.addProcess(new Process(1, 10));\n * scheduler.addProcess(new Process(2, 20));\n *\n * scheduler.clear();\n * console.log(scheduler.listProcesses()); // []\n */\nexport class DoublyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, DoublyLinkedListNode<E>> {\n /**\n * This TypeScript constructor initializes a DoublyLinkedList with optional elements and options.\n * @param {Iterable<E> | Iterable<R>} elements - The `elements` parameter in the constructor is an\n * iterable collection of elements of type `E` or `R`. It is used to initialize the DoublyLinkedList\n * with the elements provided in the iterable. If no elements are provided, the default value is an\n * empty iterable.\n * @param [options] - The `options` parameter in the constructor is of type\n * `DoublyLinkedListOptions<E, R>`. It is an optional parameter that allows you to pass additional\n * configuration options to customize the behavior of the DoublyLinkedList.\n */\n constructor(\n elements: Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>> = [],\n options?: DoublyLinkedListOptions<E, R>\n ) {\n super(options);\n this._head = undefined;\n this._tail = undefined;\n this._length = 0;\n\n if (options) {\n const { maxLen } = options;\n if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0) this._maxLen = maxLen;\n }\n\n this.pushMany(elements);\n }\n\n protected _head: DoublyLinkedListNode<E> | undefined;\n\n get head(): DoublyLinkedListNode<E> | undefined {\n return this._head;\n }\n\n protected _tail: DoublyLinkedListNode<E> | undefined;\n\n get tail(): DoublyLinkedListNode<E> | undefined {\n return this._tail;\n }\n\n protected _length: number;\n\n get length(): number {\n return this._length;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `get first` function returns the first node in a doubly linked list, or undefined if the list is empty.\n * @returns The method `get first()` returns the first node of the doubly linked list, or `undefined` if the list is empty.\n */\n get first(): E | undefined {\n return this.head?.value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `get last` function returns the last node in a doubly linked list, or undefined if the list is empty.\n * @returns The method `get last()` returns the last node of the doubly linked list, or `undefined` if the list is empty.\n */\n get last(): E | undefined {\n return this.tail?.value;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `fromArray` function creates a new instance of a DoublyLinkedList and populates it with the elements from the\n * given array.\n * @param {E[]} data - The `data` parameter is an array of elements of type `E`.\n * @returns The `fromArray` function returns a DoublyLinkedList object.\n */\n static fromArray<E>(data: E[]) {\n return new DoublyLinkedList<E>(data);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `isNode` in TypeScript checks if a given input is an instance of\n * `DoublyLinkedListNode`.\n * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `isNode` function can\n * be one of the following types:\n * @returns The `isNode` function is checking if the `elementNodeOrPredicate` parameter is an\n * instance of `DoublyLinkedListNode<E>`. If it is, the function returns `true`, indicating that the\n * parameter is a `DoublyLinkedListNode<E>`. If it is not an instance of `DoublyLinkedListNode<E>`,\n * the function returns `false`.\n */\n isNode(\n elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)\n ): elementNodeOrPredicate is DoublyLinkedListNode<E> {\n return elementNodeOrPredicate instanceof DoublyLinkedListNode;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `push` function adds a new element or node to the end of a doubly linked list.\n * @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the `push`\n * method can accept either an element of type `E` or a `DoublyLinkedListNode<E>` object.\n * @returns The `push` method is returning a boolean value, specifically `true`.\n */\n push(elementOrNode: E | DoublyLinkedListNode<E>): boolean {\n const newNode = this._ensureNode(elementOrNode);\n if (!this.head) {\n this._head = newNode;\n this._tail = newNode;\n } else {\n newNode.prev = this.tail;\n this.tail!.next = newNode;\n this._tail = newNode;\n }\n this._length++;\n if (this._maxLen > 0 && this.length > this._maxLen) this.shift();\n return true;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `pop()` function removes and returns the value of the last element in a linked list.\n * @returns The method is returning the value of the removed node.\n */\n pop(): E | undefined {\n if (!this.tail) return undefined;\n const removedNode = this.tail;\n if (this.head === this.tail) {\n this._head = undefined;\n this._tail = undefined;\n } else {\n this._tail = removedNode.prev;\n this.tail!.next = undefined;\n }\n this._length--;\n return removedNode.value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `shift()` function removes and returns the value of the first element in a doubly linked list.\n * @returns The value of the removed node.\n */\n shift(): E | undefined {\n if (!this.head) return undefined;\n const removedNode = this.head;\n if (this.head === this.tail) {\n this._head = undefined;\n this._tail = undefined;\n } else {\n this._head = removedNode.next;\n this.head!.prev = undefined;\n }\n this._length--;\n return removedNode.value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The unshift function adds a new element or node to the beginning of a doubly linked list.\n * @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the\n * `unshift` method can be either an element of type `E` or a `DoublyLinkedListNode` containing an\n * element of type `E`.\n * @returns The `unshift` method is returning a boolean value, specifically `true`.\n */\n unshift(elementOrNode: E | DoublyLinkedListNode<E>): boolean {\n const newNode = this._ensureNode(elementOrNode);\n if (!this.head) {\n this._head = newNode;\n this._tail = newNode;\n } else {\n newNode.next = this.head;\n this.head!.prev = newNode;\n this._head = newNode;\n }\n this._length++;\n if (this._maxLen > 0 && this._length > this._maxLen) this.pop();\n return true;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The function `pushMany` iterates over elements and pushes them into a data structure, applying a\n * transformation function if provided.\n * @param {Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>} elements - The `elements`\n * parameter in the `pushMany` function can accept an iterable containing elements of type `E`, `R`,\n * or `DoublyLinkedListNode<E>`. The function iterates over each element in the iterable and pushes\n * it onto the linked list. If a transformation function `to\n * @returns The `pushMany` function is returning an array of boolean values (`ans`) which indicate\n * the success or failure of pushing each element into the data structure.\n */\n pushMany(elements: Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) {\n ans.push(this.push(this.toElementFn(el as R)));\n continue;\n }\n ans.push(this.push(el as E | DoublyLinkedListNode<E>));\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The function `unshiftMany` iterates through a collection of elements and adds them to the\n * beginning of a Doubly Linked List, returning an array of boolean values indicating the success of\n * each insertion.\n * @param {Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>} elements - The `elements`\n * parameter in the `unshiftMany` function can accept an iterable containing elements of type `E`,\n * `R`, or `DoublyLinkedListNode<E>`. The function iterates over each element in the iterable and\n * performs an `unshift` operation on the doubly linked list\n * @returns The `unshiftMany` function returns an array of boolean values indicating the success of\n * each unshift operation performed on the elements passed as input.\n */\n unshiftMany(elements: Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) {\n ans.push(this.unshift(this.toElementFn(el as R)));\n continue;\n }\n ans.push(this.unshift(el as E | DoublyLinkedListNode<E>));\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `at` function returns the value at a specified index in a linked list, or undefined if the index is out of bounds.\n * @param {number} index - The index parameter is a number that represents the position of the element we want to\n * retrieve from the list.\n * @returns The method is returning the value at the specified index in the linked list. If the index is out of bounds\n * or the linked list is empty, it will return undefined.\n */\n at(index: number): E | undefined {\n if (index < 0 || index >= this._length) return undefined;\n let current = this.head;\n for (let i = 0; i < index; i++) {\n current = current!.next;\n }\n return current!.value;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `getNodeAt` returns the node at a given index in a doubly linked list, or undefined if the index is out of\n * range.\n * @param {number} index - The `index` parameter is a number that represents the position of the node we want to\n * retrieve from the doubly linked list. It indicates the zero-based index of the node we want to access.\n * @returns The method `getNodeAt(index: number)` returns a `DoublyLinkedListNode<E>` object if the index is within the\n * valid range of the linked list, otherwise it returns `undefined`.\n */\n getNodeAt(index: number): DoublyLinkedListNode<E> | undefined {\n if (index < 0 || index >= this._length) return undefined;\n let current = this.head;\n for (let i = 0; i < index; i++) {\n current = current!.next;\n }\n return current;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * This TypeScript function searches for a node in a doubly linked list based on a given element node\n * or predicate.\n * @param {| E\n * | DoublyLinkedListNode<E>\n * | ((node: DoublyLinkedListNode<E>) => boolean)\n * | undefined} elementNodeOrPredicate - The `getNode` method you provided is used to find a\n * node in a doubly linked list based on a given element, node, or predicate function. The\n * `elementNodeOrPredicate` parameter can be one of the following:\n * @returns The `getNode` method returns a `DoublyLinkedListNode<E>` or `undefined` based on the\n * input `elementNodeOrPredicate`. If the input is `undefined`, the method returns `undefined`.\n * Otherwise, it iterates through the linked list starting from the head node and applies the\n * provided predicate function to each node. If a node satisfies the predicate, that node is\n * returned. If\n */\n getNode(\n elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean) | undefined\n ): DoublyLinkedListNode<E> | undefined {\n if (elementNodeOrPredicate === undefined) return;\n if (this.isNode(elementNodeOrPredicate)) return elementNodeOrPredicate;\n const predicate = this._ensurePredicate(elementNodeOrPredicate);\n let current = this.head;\n\n while (current) {\n if (predicate(current)) {\n return current;\n }\n current = current.next;\n }\n\n return undefined;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `addAt` function inserts a new element or node at a specified index in a doubly linked list.\n * @param {number} index - The `index` parameter in the `addAt` method represents the position at\n * which you want to add a new element or node in the doubly linked list. It indicates the location\n * where the new element or node should be inserted.\n * @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the\n * `addAt` method can be either a value of type `E` or a `DoublyLinkedListNode<E>` object.\n * @returns The `addAt` method returns a boolean value. It returns `true` if the element or node was\n * successfully added at the specified index, and `false` if the index is out of bounds (less than 0\n * or greater than the length of the list).\n */\n addAt(index: number, newElementOrNode: E | DoublyLinkedListNode<E>): boolean {\n if (index < 0 || index > this._length) return false;\n if (index === 0) {\n this.unshift(newElementOrNode);\n return true;\n }\n if (index === this._length) {\n this.push(newElementOrNode);\n return true;\n }\n\n const newNode = this._ensureNode(newElementOrNode);\n const prevNode = this.getNodeAt(index - 1);\n const nextNode = prevNode!.next;\n newNode.prev = prevNode;\n newNode.next = nextNode;\n prevNode!.next = newNode;\n nextNode!.prev = newNode;\n this._length++;\n return true;\n }\n\n /**\n * Time Complexity: O(1) or O(n)\n * Space Complexity: O(1)\n *\n * The `addBefore` function in TypeScript adds a new element or node before an existing element or\n * node in a doubly linked list.\n * @param {E | DoublyLinkedListNode<E>} existingElementOrNode - The `existingElementOrNode` parameter\n * in the `addBefore` method can be either an element of type `E` or a `DoublyLinkedListNode<E>`.\n * @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter\n * represents the element or node that you want to add before the `existingElementOrNode` in a doubly\n * linked list.\n * @returns The `addBefore` method returns a boolean value - `true` if the new element or node was\n * successfully added before the existing element or node, and `false` if the existing element or\n * node was not found.\n */\n addBefore(\n existingElementOrNode: E | DoublyLinkedListNode<E>,\n newElementOrNode: E | DoublyLinkedListNode<E>\n ): boolean {\n const existingNode: DoublyLinkedListNode<E> | undefined = this.isNode(existingElementOrNode)\n ? existingElementOrNode\n : this.getNode(existingElementOrNode);\n\n if (existingNode) {\n const newNode = this._ensureNode(newElementOrNode);\n newNode.prev = existingNode.prev;\n if (existingNode.prev) {\n existingNode.prev.next = newNode;\n }\n newNode.next = existingNode;\n existingNode.prev = newNode;\n if (existingNode === this.head) {\n this._head = newNode;\n }\n this._length++;\n return true;\n }\n\n return false;\n }\n\n /**\n * Time Complexity: O(1) or O(n)\n * Space Complexity: O(1)\n *\n * The `addAfter` function in TypeScript adds a new element or node after an existing element or node\n * in a doubly linked list.\n * @param {E | DoublyLinkedListNode<E>} existingElementOrNode - existingElementOrNode represents the\n * element or node in the doubly linked list after which you want to add a new element or node.\n * @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the\n * `addAfter` method represents the element or node that you want to add after the existing element\n * or node in a doubly linked list. This parameter can be either an element value or a\n * `DoublyLinkedListNode` object that you want to insert\n * @returns The `addAfter` method returns a boolean value - `true` if the new element or node was\n * successfully added after the existing element or node, and `false` if the existing element or node\n * was not found in the linked list.\n */\n addAfter(existingElementOrNode: E | DoublyLinkedListNode<E>, newElementOrNode: E | DoublyLinkedListNode<E>): boolean {\n const existingNode: DoublyLinkedListNode<E> | undefined = this.isNode(existingElementOrNode)\n ? existingElementOrNode\n : this.getNode(existingElementOrNode);\n\n if (existingNode) {\n const newNode = this._ensureNode(newElementOrNode);\n newNode.next = existingNode.next;\n if (existingNode.next) {\n existingNode.next.prev = newNode;\n }\n newNode.prev = existingNode;\n existingNode.next = newNode;\n if (existingNode === this.tail) {\n this._tail = newNode;\n }\n this._length++;\n return true;\n }\n\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `setAt` updates the value at a specified index in a data structure if the index\n * exists.\n * @param {number} index - The `index` parameter in the `setAt` method refers to the position in the\n * data structure where you want to set a new value.\n * @param {E} value - The `value` parameter in the `setAt` method represents the new value that you\n * want to set at the specified index in the data structure.\n * @returns The `setAt` method returns a boolean value - `true` if the value at the specified index\n * is successfully updated, and `false` if the index is out of bounds.\n */\n setAt(index: number, value: E): boolean {\n const node = this.getNodeAt(index);\n if (node) {\n node.value = value;\n return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `deleteAt` function removes an element at a specified index from a linked list and returns the removed element.\n * @param {number} index - The index parameter represents the position of the element that needs to be deleted in the\n * data structure. It is of type number.\n * @returns The method `deleteAt` returns the value of the node that was deleted, or `undefined` if the index is out of\n * bounds.\n */\n deleteAt(index: number): E | undefined {\n if (index < 0 || index >= this._length) return;\n let deleted: E | undefined;\n if (index === 0) {\n deleted = this.first;\n this.shift();\n return deleted;\n }\n if (index === this._length - 1) {\n deleted = this.last;\n this.pop();\n return deleted;\n }\n\n const removedNode = this.getNodeAt(index);\n const prevNode = removedNode!.prev;\n const nextNode = removedNode!.next;\n prevNode!.next = nextNode;\n nextNode!.prev = prevNode;\n this._length--;\n return removedNode?.value;\n }\n\n /**\n * Time Complexity: O(1) or O(n)\n * Space Complexity: O(1)\n *\n * The `delete` function removes a specified element or node from a doubly linked list if it exists.\n * @param {E | DoublyLinkedListNode<E> | undefined} elementOrNode - The `elementOrNode` parameter in\n * the `delete` method can accept an element of type `E`, a `DoublyLinkedListNode` of type `E`, or it\n * can be `undefined`. This parameter is used to identify the node that needs to be deleted from the\n * doubly linked list\n * @returns The `delete` method returns a boolean value - `true` if the element or node was\n * successfully deleted from the doubly linked list, and `false` if the element or node was not found\n * in the list.\n */\n delete(elementOrNode: E | DoublyLinkedListNode<E> | undefined): boolean {\n const node: DoublyLinkedListNode<E> | undefined = this.getNode(elementOrNode);\n\n if (node) {\n if (node === this.head) {\n this.shift();\n } else if (node === this.tail) {\n this.pop();\n } else {\n const prevNode = node.prev;\n const nextNode = node.next;\n if (prevNode) prevNode.next = nextNode;\n if (nextNode) nextNode.prev = prevNode;\n this._length--;\n }\n return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if a variable has a length greater than zero and returns a boolean value.\n * @returns A boolean value is being returned.\n */\n isEmpty(): boolean {\n return this._length === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `clear` function resets the linked list by setting the head, tail, and length to undefined and 0 respectively.\n */\n clear(): void {\n this._head = undefined;\n this._tail = undefined;\n this._length = 0;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * This function retrieves an element from a doubly linked list based on a given element\n * node or predicate.\n * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `get` method takes in a parameter called `elementNodeOrPredicate`,\n * which can be one of the following types:\n * @returns The `get` method returns the value of the first node in the doubly linked list that\n * satisfies the provided predicate function. If no such node is found, it returns `undefined`.\n */\n search(\n elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)\n ): E | undefined {\n const predicate = this._ensurePredicate(elementNodeOrPredicate);\n let current = this.head;\n while (current) {\n if (predicate(current)) return current.value;\n current = current.next;\n }\n return undefined;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `getBackward` function searches for a specific element in a doubly linked list starting from\n * the tail and moving backwards.\n * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `getBackward`\n * function can be one of the following types:\n * @returns The `getBackward` method returns the value of the element node that matches the provided\n * predicate when traversing the doubly linked list backwards. If no matching element is found, it\n * returns `undefined`.\n */\n getBackward(\n elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)\n ): E | undefined {\n const predicate = this._ensurePredicate(elementNodeOrPredicate);\n let current = this.tail;\n while (current) {\n if (predicate(current)) return current.value;\n current = current.prev;\n }\n return undefined;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `reverse` function reverses the order of the elements in a doubly linked list.\n */\n reverse(): this {\n let current = this.head;\n [this._head, this._tail] = [this.tail, this.head];\n while (current) {\n const next = current.next;\n [current.prev, current.next] = [current.next, current.prev];\n current = next;\n }\n return this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `clone` function creates a new instance of the `DoublyLinkedList` class with the same values\n * as the original list.\n * @returns The `clone()` method is returning a new instance of the `DoublyLinkedList` class, which\n * is a copy of the original list.\n */\n clone(): this {\n return new DoublyLinkedList<E, R>(this, { toElementFn: this._toElementFn, maxLen: this._maxLen }) as this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new DoublyLinkedList by iterating over the elements of the current\n * list and applying a callback function to each element, returning only the elements for which the\n * callback function returns true.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the DoublyLinkedList. It takes three arguments: the current element, the index of the current\n * element, and the DoublyLinkedList itself. The callback function should return a boolean value\n * indicating whether the current element should be included\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `DoublyLinkedList` object that contains the\n * elements that pass the filter condition specified by the `callback` function.\n */\n filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): DoublyLinkedList<E, R> {\n const filteredList = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredList.push(current);\n }\n index++;\n }\n return filteredList;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function takes a callback function and returns a new DoublyLinkedList with the results\n * of applying the callback to each element in the original list.\n * @param callback - The callback parameter is a function that will be called for each element in the\n * original DoublyLinkedList. It takes three arguments: current (the current element being\n * processed), index (the index of the current element), and this (the original DoublyLinkedList).\n * The callback function should return a value of type\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to\n * convert the raw element (`RR`) to the desired element type (`T`). It takes the raw element as\n * input and returns the converted element. If this parameter is not provided, the raw element will\n * be used as is.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `DoublyLinkedList` class with elements of type `T` and `RR`.\n */\n map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): DoublyLinkedList<EM, RM> {\n const mappedList = new DoublyLinkedList<EM, RM>([], { toElementFn, maxLen: this._maxLen });\n let index = 0;\n for (const current of this) {\n mappedList.push(callback.call(thisArg, current, index, this));\n index++;\n }\n\n return mappedList;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `countOccurrences` iterates through a doubly linked list and counts the occurrences\n * of a specified element or nodes that satisfy a given predicate.\n * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementOrNode\n * - The `elementOrNode` parameter in the `countOccurrences` method can accept three types of values:\n * @returns The `countOccurrences` method returns the number of occurrences of the specified element,\n * node, or predicate function in the doubly linked list.\n */\n countOccurrences(elementOrNode: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)): number {\n const predicate = this._ensurePredicate(elementOrNode);\n let count = 0;\n let current = this.head;\n\n while (current) {\n if (predicate(current)) {\n count++;\n }\n current = current.next;\n }\n\n return count;\n }\n\n /**\n * The function returns an iterator that iterates over the values of a linked list.\n */\n protected *_getIterator(): IterableIterator<E> {\n let current = this.head;\n\n while (current) {\n yield current.value;\n current = current.next;\n }\n }\n\n /**\n * The function returns an iterator that iterates over the elements of a data structure in reverse\n * order.\n */\n protected *_getReverseIterator(): IterableIterator<E> {\n let current = this.tail;\n\n while (current) {\n yield current.value;\n current = current.prev;\n }\n }\n\n /**\n * The function returns an iterator that iterates over the nodes of a doubly linked list starting\n * from the head.\n */\n protected *_getNodeIterator(): IterableIterator<DoublyLinkedListNode<E>> {\n let current = this.head;\n\n while (current) {\n yield current;\n current = current.next;\n }\n }\n\n // protected *_getReverseNodeIterator(): IterableIterator<DoublyLinkedListNode<E>> {\n // const reversedArr = [...this._getNodeIterator()].reverse();\n //\n // for (const item of reversedArr) {\n // yield item;\n // }\n // }\n\n /**\n * The function `_isPredicate` checks if the input is a function that takes a `DoublyLinkedListNode`\n * as an argument and returns a boolean.\n * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following\n * types:\n * @returns The _isPredicate method is returning a boolean value indicating whether the\n * elementNodeOrPredicate parameter is a function or not. If the elementNodeOrPredicate is a\n * function, the method will return true, indicating that it is a predicate function.\n */\n protected _isPredicate(\n elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)\n ): elementNodeOrPredicate is (node: DoublyLinkedListNode<E>) => boolean {\n return typeof elementNodeOrPredicate === 'function';\n }\n\n /**\n * The function `_ensureNode` ensures that the input is a valid node in a doubly linked list.\n * @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter can be either\n * an element of type `E` or a `DoublyLinkedListNode` containing an element of type `E`.\n * @returns If the `elementOrNode` parameter is already a `DoublyLinkedListNode`, it will be returned\n * as is. Otherwise, a new `DoublyLinkedListNode` instance will be created with the `elementOrNode`\n * value and returned.\n */\n protected _ensureNode(elementOrNode: E | DoublyLinkedListNode<E>) {\n if (this.isNode(elementOrNode)) return elementOrNode;\n\n return new DoublyLinkedListNode<E>(elementOrNode);\n }\n\n /**\n * The function `_ensurePredicate` in TypeScript ensures that the input is either a node, a predicate\n * function, or a value to compare with the node's value.\n * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following\n * types:\n * @returns A function is being returned that takes a `DoublyLinkedListNode` as a parameter and\n * returns a boolean value based on the conditions specified in the code.\n */\n protected _ensurePredicate(\n elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)\n ) {\n if (this.isNode(elementNodeOrPredicate)) return (node: DoublyLinkedListNode<E>) => node === elementNodeOrPredicate;\n\n if (this._isPredicate(elementNodeOrPredicate)) return elementNodeOrPredicate;\n\n return (node: DoublyLinkedListNode<E>) => node.value === elementNodeOrPredicate;\n }\n\n /**\n * The function `_createInstance` returns a new instance of `DoublyLinkedList` with the specified\n * options.\n * @param [options] - The `options` parameter in the `_createInstance` method is of type\n * `DoublyLinkedListOptions<E, R>`. It is an optional parameter that allows you to pass additional\n * configuration options when creating a new instance of the `DoublyLinkedList` class.\n * @returns An instance of the `DoublyLinkedList` class with an empty array and the provided options\n * is being returned, cast as the current class type.\n */\n protected override _createInstance(options?: DoublyLinkedListOptions<E, R>): this {\n return new DoublyLinkedList<E, R>([], options) as this;\n }\n\n /**\n * The function `_getPrevNode` returns the previous node of a given node in a doubly linked list.\n * @param node - The parameter `node` in the `_getPrevNode` method is of type\n * `DoublyLinkedListNode<E>`, which represents a node in a doubly linked list containing an element\n * of type `E`.\n * @returns The `_getPrevNode` method is returning the previous node of the input `node` in a doubly\n * linked list. If the input node has a previous node, it will return that node. Otherwise, it will\n * return `undefined`.\n */\n protected _getPrevNode(node: DoublyLinkedListNode<E>): DoublyLinkedListNode<E> | undefined {\n return node.prev;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { SkipLinkedListOptions } from '../../types';\n\nexport class SkipListNode<K, V> {\n key: K;\n value: V;\n forward: SkipListNode<K, V>[];\n\n constructor(key: K, value: V, level: number) {\n this.key = key;\n this.value = value;\n this.forward = new Array(level);\n }\n}\n\n/**\n *\n */\nexport class SkipList<K, V> {\n /**\n * The constructor function initializes a SkipLinkedList object with optional options and elements.\n * @param elements - The `elements` parameter is an iterable containing key-value pairs `[K, V]`. It\n * is used to initialize the SkipLinkedList with the given key-value pairs. If no elements are\n * provided, the SkipLinkedList will be empty.\n * @param {SkipLinkedListOptions} [options] - The `options` parameter is an optional object that can\n * contain two properties:\n */\n constructor(elements: Iterable<[K, V]> = [], options?: SkipLinkedListOptions) {\n if (options) {\n const { maxLevel, probability } = options;\n if (typeof maxLevel === 'number') this._maxLevel = maxLevel;\n if (typeof probability === 'number') this._probability = probability;\n }\n\n if (elements) {\n for (const [key, value] of elements) this.add(key, value);\n }\n }\n\n protected _head: SkipListNode<K, V> = new SkipListNode<K, V>(undefined as any, undefined as any, this.maxLevel);\n\n /**\n * The function returns the head node of a SkipList.\n * @returns The method is returning a SkipListNode object with generic key type K and value type V.\n */\n get head(): SkipListNode<K, V> {\n return this._head;\n }\n\n protected _level: number = 0;\n\n /**\n * The function returns the value of the protected variable _level.\n * @returns The level property of the object.\n */\n get level(): number {\n return this._level;\n }\n\n protected _maxLevel: number = 16;\n\n /**\n * The function returns the maximum level.\n * @returns The value of the variable `_maxLevel` is being returned.\n */\n get maxLevel(): number {\n return this._maxLevel;\n }\n\n protected _probability: number = 0.5;\n\n /**\n * The function returns the probability value.\n * @returns The probability value stored in the protected variable `_probability` is being returned.\n */\n get probability(): number {\n return this._probability;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Get the value of the first element (the smallest element) in the Skip List.\n * @returns The value of the first element, or undefined if the Skip List is empty.\n */\n get first(): V | undefined {\n const firstNode = this.head.forward[0];\n return firstNode ? firstNode.value : undefined;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Get the value of the last element (the largest element) in the Skip List.\n * @returns The value of the last element, or undefined if the Skip List is empty.\n */\n get last(): V | undefined {\n let current = this.head;\n for (let i = this.level - 1; i >= 0; i--) {\n while (current.forward[i]) {\n current = current.forward[i];\n }\n }\n return current.value;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The add function adds a new node with a given key and value to a Skip List data structure.\n * @param {K} key - The key parameter represents the key of the node that needs to be added to the skip list.\n * @param {V} value - The \"value\" parameter represents the value associated with the key that is being added to the Skip\n * List.\n */\n add(key: K, value: V): void {\n const newNode = new SkipListNode(key, value, this._randomLevel());\n const update: SkipListNode<K, V>[] = new Array(this.maxLevel).fill(this.head);\n let current = this.head;\n\n for (let i = this.level - 1; i >= 0; i--) {\n while (current.forward[i] && current.forward[i].key < key) {\n current = current.forward[i];\n }\n update[i] = current;\n }\n\n for (let i = 0; i < newNode.forward.length; i++) {\n newNode.forward[i] = update[i].forward[i];\n update[i].forward[i] = newNode;\n }\n\n if (!newNode.forward[0]) {\n this._level = Math.max(this.level, newNode.forward.length);\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The function `get` retrieves the value associated with a given key from a skip list data structure.\n * @param {K} key - The `key` parameter is the key of the element that we want to retrieve from the data structure.\n * @returns The method `get(key: K)` returns the value associated with the given key if it exists in the data structure,\n * otherwise it returns `undefined`.\n */\n get(key: K): V | undefined {\n let current = this.head;\n for (let i = this.level - 1; i >= 0; i--) {\n while (current.forward[i] && current.forward[i].key < key) {\n current = current.forward[i];\n }\n }\n\n current = current.forward[0];\n\n if (current && current.key === key) {\n return current.value;\n }\n\n return undefined;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The function checks if a key exists in a data structure.\n * @param {K} key - The parameter \"key\" is of type K, which represents the type of the key being\n * checked.\n * @returns a boolean value.\n */\n has(key: K): boolean {\n return this.get(key) !== undefined;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The `delete` function removes a node with a specific key from a Skip List data structure.\n * @param {K} key - The key parameter represents the key of the node that needs to be removed from the skip list.\n * @returns The `delete` method returns a boolean value. It returns `true` if the key was successfully removed from the\n * skip list, and `false` if the key was not found in the skip list.\n */\n delete(key: K): boolean {\n const update: SkipListNode<K, V>[] = new Array(this.maxLevel).fill(this.head);\n let current = this.head;\n\n for (let i = this.level - 1; i >= 0; i--) {\n while (current.forward[i] && current.forward[i].key < key) {\n current = current.forward[i];\n }\n update[i] = current;\n }\n\n current = current.forward[0];\n\n if (current && current.key === key) {\n for (let i = 0; i < this.level; i++) {\n if (update[i].forward[i] !== current) {\n break;\n }\n update[i].forward[i] = current.forward[i];\n }\n while (this.level > 0 && !this.head.forward[this.level - 1]) {\n this._level--;\n }\n return true;\n }\n\n return false;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Get the value of the first element in the Skip List that is greater than the given key.\n * @param key - the given key.\n * @returns The value of the first element greater than the given key, or undefined if there is no such element.\n */\n higher(key: K): V | undefined {\n let current = this.head;\n for (let i = this.level - 1; i >= 0; i--) {\n while (current.forward[i] && current.forward[i].key <= key) {\n current = current.forward[i];\n }\n }\n const nextNode = current.forward[0];\n return nextNode ? nextNode.value : undefined;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Get the value of the last element in the Skip List that is less than the given key.\n * @param key - the given key.\n * @returns The value of the last element less than the given key, or undefined if there is no such element.\n */\n lower(key: K): V | undefined {\n let current = this.head;\n let lastLess = undefined;\n\n for (let i = this.level - 1; i >= 0; i--) {\n while (current.forward[i] && current.forward[i].key < key) {\n current = current.forward[i];\n }\n if (current.key < key) {\n lastLess = current;\n }\n }\n\n return lastLess ? lastLess.value : undefined;\n }\n\n /**\n * Time Complexity: O(maxLevel)\n * Space Complexity: O(1)\n *\n * The function \"_randomLevel\" generates a random level based on a given probability and maximum level.\n * @returns the level, which is a number.\n */\n protected _randomLevel(): number {\n let level = 1;\n while (Math.random() < this.probability && level < this.maxLevel) {\n level++;\n }\n return level;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { ElementCallback, StackOptions } from '../../types';\nimport { IterableElementBase } from '../base';\n\n/**\n * 1. Last In, First Out (LIFO): The core characteristic of a stack is its last in, first out nature, meaning the last element added to the stack will be the first to be removed.\n * 2. Uses: Stacks are commonly used for managing a series of tasks or elements that need to be processed in a last in, first out manner. They are widely used in various scenarios, such as in function calls in programming languages, evaluation of arithmetic expressions, and backtracking algorithms.\n * 3. Performance: Stack operations are typically O(1) in time complexity, meaning that regardless of the stack's size, adding, removing, and viewing the top element are very fast operations.\n * 4. Function Calls: In most modern programming languages, the records of function calls are managed through a stack. When a function is called, its record (including parameters, local variables, and return address) is 'pushed' into the stack. When the function returns, its record is 'popped' from the stack.\n * 5. Expression Evaluation: Used for the evaluation of arithmetic or logical expressions, especially when dealing with parenthesis matching and operator precedence.\n * 6. Backtracking Algorithms: In problems where multiple branches need to be explored but only one branch can be explored at a time, stacks can be used to save the state at each branching point.\n */\nexport class Stack<E = any, R = any> extends IterableElementBase<E, R> {\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: StackOptions<E, R>) {\n super(options);\n this.pushMany(elements);\n }\n\n protected _elements: E[] = [];\n\n /**\n * The elements function returns the elements of this set.\n * @return An array of elements\n */\n get elements(): E[] {\n return this._elements;\n }\n\n /**\n * The size() function returns the number of elements in an array.\n * @returns The size of the elements array.\n */\n get size(): number {\n return this.elements.length;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function \"fromArray\" creates a new Stack object from an array of elements.\n * @param {E[]} elements - The `elements` parameter is an array of elements of type `E`.\n * @returns {Stack} The method is returning a new instance of the Stack class, initialized with the elements from the input\n * array.\n */\n static fromArray<E>(elements: E[]): Stack<E> {\n return new Stack(elements);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if an array is empty and returns a boolean value.\n * @returns A boolean value indicating whether the `_elements` array is empty or not.\n */\n isEmpty(): boolean {\n return this.elements.length === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `peek` function returns the last element of an array, or undefined if the array is empty.\n * @returns The `peek()` function returns the last element of the `_elements` array, or `undefined` if the array is empty.\n */\n peek(): E | undefined {\n if (this.isEmpty()) return undefined;\n\n return this.elements[this.elements.length - 1];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The push function adds an element to the stack and returns the updated stack.\n * @param {E} element - The parameter \"element\" is of type E, which means it can be any data type.\n * @returns The `push` method is returning the updated `Stack<E>` object.\n */\n push(element: E): boolean {\n this.elements.push(element);\n return true;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `pop` function removes and returns the last element from an array, or returns undefined if the array is empty.\n * @returns The `pop()` method is returning the last element of the array `_elements` if the array is not empty. If the\n * array is empty, it returns `undefined`.\n */\n pop(): E | undefined {\n if (this.isEmpty()) return;\n\n return this.elements.pop();\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(1)\n *\n * The function `pushMany` iterates over elements and pushes them into an array after applying a\n * transformation function if provided.\n * @param {Iterable<E> | Iterable<R>} elements - The `elements` parameter in the `pushMany` function\n * is an iterable containing elements of type `E` or `R`. The function iterates over each element in\n * the iterable and pushes it into the data structure. If a transformation function `toElementFn` is\n * provided, it is used to\n * @returns The `pushMany` function is returning an array of boolean values indicating whether each\n * element was successfully pushed into the data structure.\n */\n pushMany(elements: Iterable<E> | Iterable<R>) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) {\n ans.push(this.push(this.toElementFn(el as R)));\n } else {\n ans.push(this.push(el as E));\n }\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The toArray function returns a copy of the elements in an array.\n * @returns An array of type E.\n */\n delete(element: E): boolean {\n const index = this.elements.indexOf(element);\n return this.deleteAt(index);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The toArray function returns a copy of the elements in an array.\n * @returns An array of type E.\n */\n deleteAt(index: number): boolean {\n const spliced = this.elements.splice(index, 1);\n return spliced.length === 1;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear function clears the elements array.\n */\n clear(): void {\n this._elements = [];\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `clone()` function returns a new `Stack` object with the same elements as the original stack.\n * @returns The `clone()` method is returning a new `Stack` object with a copy of the `_elements` array.\n */\n clone(): Stack<E, R> {\n return new Stack<E, R>(this, { toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new stack containing elements from the original stack that satisfy\n * a given predicate function.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * the current element being iterated over, the index of the current element, and the stack itself.\n * It should return a boolean value indicating whether the element should be included in the filtered\n * stack or not.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `predicate` function. If `thisArg` is\n * @returns The `filter` method is returning a new `Stack` object that contains the elements that\n * satisfy the given predicate function.\n */\n filter(predicate: ElementCallback<E, R, boolean>, thisArg?: any): Stack<E, R> {\n const newStack = new Stack<E, R>([], { toElementFn: this.toElementFn });\n let index = 0;\n for (const el of this) {\n if (predicate.call(thisArg, el, index, this)) {\n newStack.push(el);\n }\n index++;\n }\n return newStack;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function takes a callback function and applies it to each element in the stack,\n * returning a new stack with the results.\n * @param callback - The callback parameter is a function that will be called for each element in the\n * stack. It takes three arguments: the current element, the index of the element, and the stack\n * itself. It should return a new value that will be added to the new stack.\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to\n * transform the raw element (`RM`) into a new element (`EM`) before pushing it into the new stack.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new Stack object with elements of type EM and raw elements of type RM.\n */\n map<EM, RM>(callback: ElementCallback<E, R, EM>, toElementFn?: (rawElement: RM) => EM, thisArg?: any): Stack<EM, RM> {\n const newStack = new Stack<EM, RM>([], { toElementFn });\n let index = 0;\n for (const el of this) {\n newStack.push(callback.call(thisArg, el, index, this));\n index++;\n }\n return newStack;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * Custom iterator for the Stack class.\n * @returns An iterator object.\n */\n protected *_getIterator(): IterableIterator<E> {\n for (let i = 0; i < this.elements.length; i++) {\n yield this.elements[i];\n }\n }\n}\n","/**\n * @license MIT\n * @copyright Pablo Zeng <zrwusa@gmail.com>\n * @class\n */\nimport type { ElementCallback, QueueOptions } from '../../types';\nimport { SinglyLinkedList } from '../linked-list';\nimport { LinearBase } from '../base/linear-base';\n\n/**\n * 1. First In, First Out (FIFO): The core feature of a queue is its first in, first out nature. The element added to the queue first will be the one to be removed first.\n * 2. Operations: The main operations include enqueue (adding an element to the end of the queue) and dequeue (removing and returning the element at the front of the queue). Typically, there is also a peek operation (looking at the front element without removing it).\n * 3. Uses: Queues are commonly used to manage a series of tasks or elements that need to be processed in order. For example, managing task queues in a multi-threaded environment, or in algorithms for data structures like trees and graphs for breadth-first search.\n * 4. Task Scheduling: Managing the order of task execution in operating systems or applications.\n * 5. Data Buffering: Acting as a buffer for data packets in network communication.\n * 6. Breadth-First Search (BFS): In traversal algorithms for graphs and trees, queues store elements that are to be visited.\n * 7. Real-time Queuing: Like queuing systems in banks or supermarkets.\n */\nexport class Queue<E = any, R = any> extends LinearBase<E, R> {\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: QueueOptions<E, R>) {\n super(options);\n\n if (options) {\n const { autoCompactRatio = 0.5 } = options;\n this._autoCompactRatio = autoCompactRatio;\n }\n\n this.pushMany(elements);\n }\n\n protected _elements: E[] = [];\n\n get elements(): E[] {\n return this._elements;\n }\n\n protected _offset: number = 0;\n\n get offset(): number {\n return this._offset;\n }\n\n get length(): number {\n return this.elements.length - this.offset;\n }\n\n protected _autoCompactRatio: number = 0.5;\n\n get autoCompactRatio(): number {\n return this._autoCompactRatio;\n }\n\n set autoCompactRatio(v: number) {\n this._autoCompactRatio = v;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `first` function returns the first element of the array `_elements` if it exists, otherwise it returns `undefined`.\n * @returns The `get first()` method returns the first element of the data structure, represented by the `_elements` array at\n * the `_offset` index. If the data structure is empty (length is 0), it returns `undefined`.\n */\n get first(): E | undefined {\n return this.length > 0 ? this.elements[this.offset] : undefined;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `last` function returns the last element in an array-like data structure, or undefined if the structure is empty.\n * @returns The method `get last()` returns the last element of the `_elements` array if the array is not empty. If the\n * array is empty, it returns `undefined`.\n */\n get last(): E | undefined {\n return this.length > 0 ? this.elements[this.elements.length - 1] : undefined;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function \"fromArray\" creates a new Queue object from an array of elements.Creates a queue from an existing array.\n * @public\n * @param {E[]} elements - The \"elements\" parameter is an array of elements of type E.\n * @returns The method is returning a new instance of the Queue class, initialized with the elements from the input\n * array.\n */\n static fromArray<E>(elements: E[]): Queue<E> {\n return new Queue(elements);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The push function adds an element to the end of the queue and returns true. Adds an element at the back of the queue.\n * @param {E} element - The `element` parameter represents the element that you want to add to the queue.\n * @returns Always returns true, indicating the element was successfully added.\n */\n push(element: E): boolean {\n this.elements.push(element);\n if (this._maxLen > 0 && this.length > this._maxLen) this.shift();\n return true;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The `pushMany` function iterates over elements and pushes them into an array after applying a\n * transformation function if provided.\n * @param {Iterable<E> | Iterable<R>} elements - The `elements` parameter in the `pushMany` function\n * is an iterable containing elements of type `E` or `R`.\n * @returns The `pushMany` function is returning an array of boolean values indicating whether each\n * element was successfully pushed into the data structure.\n */\n pushMany(elements: Iterable<E> | Iterable<R>) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) ans.push(this.push(this.toElementFn(el as R)));\n else ans.push(this.push(el as E));\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `shift` function removes and returns the first element in the queue, and adjusts the internal data structure if\n * necessary to optimize performance.\n * @returns The function `shift()` returns either the first element in the queue or `undefined` if the queue is empty.\n */\n shift(): E | undefined {\n if (this.length === 0) return undefined;\n\n const first = this.first;\n this._offset += 1;\n\n if (this.offset / this.elements.length > this.autoCompactRatio) this.compact();\n return first;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The delete function removes an element from the list.\n * @param {E} element - Specify the element to be deleted\n * @return A boolean value indicating whether the element was successfully deleted or not\n */\n delete(element: E): boolean {\n const index = this.elements.indexOf(element);\n return !!this.deleteAt(index);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The deleteAt function deletes the element at a given index.\n * @param {number} index - Determine the index of the element to be deleted\n * @return A boolean value\n */\n deleteAt(index: number): E | undefined {\n const deleted = this.elements[index];\n this.elements.splice(index, 1);\n return deleted;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `at` function returns the element at a specified index adjusted by an offset, or `undefined`\n * if the index is out of bounds.\n * @param {number} index - The `index` parameter represents the position of the element you want to\n * retrieve from the data structure.\n * @returns The `at` method is returning the element at the specified index adjusted by the offset\n * `_offset`.\n */\n at(index: number): E | undefined {\n return this.elements[index + this._offset];\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `reverse` function in TypeScript reverses the elements of an array starting from a specified\n * offset.\n * @returns The `reverse()` method is returning the modified object itself (`this`) after reversing\n * the elements in the array and resetting the offset to 0.\n */\n reverse(): this {\n this._elements = this.elements.slice(this.offset).reverse();\n this._offset = 0;\n return this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `addAt` inserts a new element at a specified index in an array, returning true if\n * successful and false if the index is out of bounds.\n * @param {number} index - The `index` parameter represents the position at which the `newElement`\n * should be added in the array.\n * @param {E} newElement - The `newElement` parameter represents the element that you want to insert\n * into the array at the specified index.\n * @returns The `addAt` method returns a boolean value - `true` if the new element was successfully\n * added at the specified index, and `false` if the index is out of bounds (less than 0 or greater\n * than the length of the array).\n */\n addAt(index: number, newElement: E): boolean {\n if (index < 0 || index > this.length) return false;\n this._elements.splice(this.offset + index, 0, newElement);\n return true;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `setAt` updates an element at a specified index in an array-like data structure.\n * @param {number} index - The `index` parameter is a number that represents the position in the\n * array where the new element will be set.\n * @param {E} newElement - The `newElement` parameter represents the new value that you want to set\n * at the specified index in the array.\n * @returns The `setAt` method returns a boolean value - `true` if the element was successfully set\n * at the specified index, and `false` if the index is out of bounds (less than 0 or greater than the\n * length of the array).\n */\n setAt(index: number, newElement: E): boolean {\n if (index < 0 || index > this.length) return false;\n this._elements[this.offset + index] = newElement;\n return true;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if a data structure is empty by comparing its length to zero.\n * @returns {boolean} A boolean value indicating whether the length of the object is 0 or not.\n */\n isEmpty(): boolean {\n return this.length === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear function resets the elements array and offset to their initial values.\n */\n clear(): void {\n this._elements = [];\n this._offset = 0;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `compact` function in TypeScript slices the elements array based on the offset and resets the\n * offset to zero.\n * @returns The `compact()` method is returning a boolean value of `true`.\n */\n compact(): boolean {\n this._elements = this.elements.slice(this.offset);\n this._offset = 0;\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function overrides the splice method to remove and insert elements in a queue-like data\n * structure.\n * @param {number} start - The `start` parameter in the `splice` method specifies the index at which\n * to start changing the array. Items will be added or removed starting from this index.\n * @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the\n * number of elements to remove from the array starting at the specified `start` index. If\n * `deleteCount` is not provided, it defaults to 0, meaning no elements will be removed but new\n * elements can still be inserted at\n * @param {E[]} items - The `items` parameter in the `splice` method represents the elements that\n * will be added to the array at the specified `start` index. These elements will replace the\n * existing elements starting from the `start` index for the `deleteCount` number of elements.\n * @returns The `splice` method is returning the `removedQueue`, which is an instance of the same\n * class as the original object.\n */\n override splice(start: number, deleteCount: number = 0, ...items: E[]): this {\n const removedQueue = this._createInstance();\n\n start = Math.max(0, Math.min(start, this.length));\n deleteCount = Math.max(0, Math.min(deleteCount, this.length - start));\n\n const globalStartIndex = this.offset + start;\n\n const removedElements = this._elements.splice(globalStartIndex, deleteCount, ...items);\n removedQueue.pushMany(removedElements);\n\n this.compact();\n\n return removedQueue;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `clone()` function returns a new Queue object with the same elements as the original Queue.\n * @returns The `clone()` method is returning a new instance of the `Queue` class.\n */\n clone(): this {\n return new Queue(this.elements.slice(this.offset), { toElementFn: this.toElementFn, maxLen: this._maxLen }) as this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new `Queue` object containing elements from the original `Queue`\n * that satisfy a given predicate function.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * the current element being iterated over, the index of the current element, and the queue itself.\n * It should return a boolean value indicating whether the element should be included in the filtered\n * queue or not.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `predicate` function. If `thisArg` is\n * @returns The `filter` method is returning a new `Queue` object that contains the elements that\n * satisfy the given predicate function.\n */\n filter(predicate: ElementCallback<E, R, boolean>, thisArg?: any): Queue<E, R> {\n const newDeque = this._createInstance({\n toElementFn: this._toElementFn,\n autoCompactRatio: this._autoCompactRatio,\n maxLen: this._maxLen\n });\n let index = 0;\n for (const el of this) {\n if (predicate.call(thisArg, el, index, this)) {\n newDeque.push(el);\n }\n index++;\n }\n return newDeque;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function in TypeScript creates a new Queue by applying a callback function to each\n * element in the original Queue.\n * @param callback - The `callback` parameter is a function that will be applied to each element in\n * the queue. It takes the current element, its index, and the queue itself as arguments, and returns\n * a new element.\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be provided to\n * convert a raw element of type `RM` to a new element of type `EM`. This function is used within the\n * `map` method to transform each raw element before passing it to the `callback` function. If\n * @param {any} [thisArg] - The `thisArg` parameter in the `map` function is used to specify the\n * value of `this` when executing the `callback` function. It allows you to set the context (the\n * value of `this`) within the callback function. If `thisArg` is provided, it will be\n * @returns A new Queue object containing elements of type EM, which are the result of applying the\n * callback function to each element in the original Queue object.\n */\n map<EM, RM>(callback: ElementCallback<E, R, EM>, toElementFn?: (rawElement: RM) => EM, thisArg?: any): Queue<EM, RM> {\n const newDeque = new Queue<EM, RM>([], {\n toElementFn,\n autoCompactRatio: this._autoCompactRatio,\n maxLen: this._maxLen\n });\n let index = 0;\n for (const el of this) {\n newDeque.push(callback.call(thisArg, el, index, this));\n index++;\n }\n return newDeque;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `_getIterator` returns an iterable iterator for the elements in the class.\n */\n protected *_getIterator(): IterableIterator<E> {\n for (const item of this.elements.slice(this.offset)) {\n yield item;\n }\n }\n\n /**\n * The function `_createInstance` returns a new instance of the `Queue` class with the specified\n * options.\n * @param [options] - The `options` parameter in the `_createInstance` method is of type\n * `QueueOptions<E, R>`, which is used to configure the behavior of the queue being created. It\n * allows you to specify settings or properties that can influence how the queue operates.\n * @returns An instance of the `Queue` class with an empty array and the provided options is being\n * returned.\n */\n protected override _createInstance(options?: QueueOptions<E, R>): this {\n return new Queue<E, R>([], options) as this;\n }\n\n /**\n * The function `_getReverseIterator` returns an iterator that iterates over elements in reverse\n * order.\n */\n protected *_getReverseIterator(): IterableIterator<E> {\n for (let i = this.length - 1; i >= 0; i--) {\n const cur = this.at(i); // `at()` handles the offset.\n if (cur !== undefined) yield cur;\n }\n }\n}\n\n/**\n * 1. First In, First Out (FIFO) Strategy: Like other queue implementations, LinkedListQueue follows the first in, first out principle, meaning the element that is added to the queue first will be the first to be removed.\n * 2. Based on Linked List: LinkedListQueue uses a linked list to store elements. Each node in the linked list contains data and a pointer to the next node.\n * 3. Memory Usage: Since each element requires additional space to store a pointer to the next element, linked lists may use more memory compared to arrays.\n * 4. Frequent Enqueuing and Dequeuing Operations: If your application involves frequent enqueuing and dequeuing operations and is less concerned with random access, then LinkedListQueue is a good choice.\n */\nexport class LinkedListQueue<E = any, R = any> extends SinglyLinkedList<E, R> {\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n * The `clone` function returns a new instance of the `LinkedListQueue` class with the same values as\n * the current instance.\n * @returns The `clone()` method is returning a new instance of `LinkedListQueue` with the same\n * values as the original `LinkedListQueue`.\n */\n override clone(): this {\n return new LinkedListQueue<E, R>(this, { toElementFn: this.toElementFn, maxLen: this._maxLen }) as this;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { DequeOptions, ElementCallback, IterableWithSizeOrLength } from '../../types';\nimport { calcMinUnitsRequired, rangeCheck } from '../../utils';\nimport { LinearBase } from '../base/linear-base';\n\n/**\n * 1. Operations at Both Ends: Supports adding and removing elements at both the front and back of the queue. This allows it to be used as a stack (last in, first out) and a queue (first in, first out).\n * 2. Efficient Random Access: Being based on an array, it offers fast random access capability, allowing constant time access to any element.\n * 3. Continuous Memory Allocation: Since it is based on an array, all elements are stored contiguously in memory, which can bring cache friendliness and efficient memory access.\n * 4. Efficiency: Adding and removing elements at both ends of a deque is usually very fast. However, when the dynamic array needs to expand, it may involve copying the entire array to a larger one, and this operation has a time complexity of O(n).\n * 5. Performance jitter: Deque may experience performance jitter, but DoublyLinkedList will not\n * @example\n * // prize roulette\n * class PrizeRoulette {\n * private deque: Deque<string>;\n *\n * constructor(prizes: string[]) {\n * // Initialize the deque with prizes\n * this.deque = new Deque<string>(prizes);\n * }\n *\n * // Rotate clockwise to the right (forward)\n * rotateClockwise(steps: number): void {\n * const n = this.deque.length;\n * if (n === 0) return;\n *\n * for (let i = 0; i < steps; i++) {\n * const last = this.deque.pop(); // Remove the last element\n * this.deque.unshift(last!); // Add it to the front\n * }\n * }\n *\n * // Rotate counterclockwise to the left (backward)\n * rotateCounterClockwise(steps: number): void {\n * const n = this.deque.length;\n * if (n === 0) return;\n *\n * for (let i = 0; i < steps; i++) {\n * const first = this.deque.shift(); // Remove the first element\n * this.deque.push(first!); // Add it to the back\n * }\n * }\n *\n * // Display the current prize at the head\n * display() {\n * return this.deque.first;\n * }\n * }\n *\n * // Example usage\n * const prizes = ['Car', 'Bike', 'Laptop', 'Phone', 'Watch', 'Headphones']; // Initialize the prize list\n * const roulette = new PrizeRoulette(prizes);\n *\n * // Display the initial state\n * console.log(roulette.display()); // 'Car' // Car\n *\n * // Rotate clockwise by 3 steps\n * roulette.rotateClockwise(3);\n * console.log(roulette.display()); // 'Phone' // Phone\n *\n * // Rotate counterclockwise by 2 steps\n * roulette.rotateCounterClockwise(2);\n * console.log(roulette.display()); // 'Headphones'\n * @example\n * // sliding window\n * // Maximum function of sliding window\n * function maxSlidingWindow(nums: number[], k: number): number[] {\n * const n = nums.length;\n * if (n * k === 0) return [];\n *\n * const deq = new Deque<number>();\n * const result: number[] = [];\n *\n * for (let i = 0; i < n; i++) {\n * // Delete indexes in the queue that are not within the window range\n * if (deq.length > 0 && deq.first! === i - k) {\n * deq.shift();\n * }\n *\n * // Remove all indices less than the current value from the tail of the queue\n * while (deq.length > 0 && nums[deq.last!] < nums[i]) {\n * deq.pop();\n * }\n *\n * // Add the current index to the end of the queue\n * deq.push(i);\n *\n * // Add the maximum value of the window to the results\n * if (i >= k - 1) {\n * result.push(nums[deq.first!]);\n * }\n * }\n *\n * return result;\n * }\n *\n * const nums = [1, 3, -1, -3, 5, 3, 6, 7];\n * const k = 3;\n * console.log(maxSlidingWindow(nums, k)); // [3, 3, 5, 5, 6, 7]\n */\nexport class Deque<E = any, R = any> extends LinearBase<E, R> {\n /**\n * The constructor initializes a Deque object with optional iterable of elements and options.\n * @param elements - An iterable object (such as an array or a Set) that contains the initial\n * elements to be added to the deque. It can also be an object with a `length` or `size` property\n * that represents the number of elements in the iterable object. If no elements are provided, an\n * empty deque\n * @param {DequeOptions} [options] - The `options` parameter is an optional object that can contain\n * configuration options for the deque. In this code, it is used to set the `bucketSize` option,\n * which determines the size of each bucket in the deque. If the `bucketSize` option is not provided\n * or is not a number\n */\n constructor(elements: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R> = [], options?: DequeOptions<E, R>) {\n super(options);\n\n if (options) {\n const { bucketSize } = options;\n if (typeof bucketSize === 'number') this._bucketSize = bucketSize;\n }\n\n let _size: number;\n if ('length' in elements) {\n if (elements.length instanceof Function) _size = elements.length();\n else _size = elements.length;\n } else {\n if (elements.size instanceof Function) _size = elements.size();\n else _size = elements.size;\n }\n\n this._bucketCount = calcMinUnitsRequired(_size, this._bucketSize) || 1;\n for (let i = 0; i < this._bucketCount; ++i) {\n this._buckets.push(new Array(this._bucketSize));\n }\n const needBucketNum = calcMinUnitsRequired(_size, this._bucketSize);\n this._bucketFirst = this._bucketLast = (this._bucketCount >> 1) - (needBucketNum >> 1);\n this._firstInBucket = this._lastInBucket = (this._bucketSize - (_size % this._bucketSize)) >> 1;\n this.pushMany(elements);\n }\n\n protected _bucketSize: number = 1 << 12;\n\n get bucketSize() {\n return this._bucketSize;\n }\n\n protected _bucketFirst = 0;\n\n get bucketFirst(): number {\n return this._bucketFirst;\n }\n\n protected _firstInBucket = 0;\n\n get firstInBucket(): number {\n return this._firstInBucket;\n }\n\n protected _bucketLast = 0;\n\n get bucketLast(): number {\n return this._bucketLast;\n }\n\n protected _lastInBucket = 0;\n\n get lastInBucket(): number {\n return this._lastInBucket;\n }\n\n protected _bucketCount = 0;\n\n get bucketCount(): number {\n return this._bucketCount;\n }\n\n protected _buckets: E[][] = [];\n\n get buckets() {\n return this._buckets;\n }\n\n protected _length = 0;\n\n get length() {\n return this._length;\n }\n\n /**\n * The function returns the first element in a collection if it exists, otherwise it returns\n * undefined.\n * @returns The first element of the collection, of type E, is being returned.\n */\n get first(): E | undefined {\n if (this._length === 0) return;\n return this._buckets[this._bucketFirst][this._firstInBucket];\n }\n\n /**\n * The last function returns the last element in the queue.\n * @return The last element in the array\n */\n get last(): E | undefined {\n if (this._length === 0) return;\n return this._buckets[this._bucketLast][this._lastInBucket];\n }\n\n /**\n * Time Complexity - Amortized O(1) (possible reallocation),\n * Space Complexity - O(n) (due to potential resizing).\n *\n * The push function adds an element to a data structure and reallocates memory if necessary.\n * @param {E} element - The `element` parameter represents the value that you want to add to the data\n * structure.\n * @returns The size of the data structure after the element has been pushed.\n */\n push(element: E): boolean {\n if (this._length) {\n if (this._lastInBucket < this._bucketSize - 1) {\n this._lastInBucket += 1;\n } else if (this._bucketLast < this._bucketCount - 1) {\n this._bucketLast += 1;\n this._lastInBucket = 0;\n } else {\n this._bucketLast = 0;\n this._lastInBucket = 0;\n }\n if (this._bucketLast === this._bucketFirst && this._lastInBucket === this._firstInBucket) this._reallocate();\n }\n this._length += 1;\n this._buckets[this._bucketLast][this._lastInBucket] = element;\n if (this._maxLen > 0 && this._length > this._maxLen) this.shift();\n return true;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `pop()` function removes and returns the last element from a data structure, updating the\n * internal state variables accordingly.\n * @returns The element that was removed from the data structure is being returned.\n */\n pop(): E | undefined {\n if (this._length === 0) return;\n const element = this._buckets[this._bucketLast][this._lastInBucket];\n if (this._length !== 1) {\n if (this._lastInBucket > 0) {\n this._lastInBucket -= 1;\n } else if (this._bucketLast > 0) {\n this._bucketLast -= 1;\n this._lastInBucket = this._bucketSize - 1;\n } else {\n this._bucketLast = this._bucketCount - 1;\n this._lastInBucket = this._bucketSize - 1;\n }\n }\n this._length -= 1;\n return element;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `shift()` function removes and returns the first element from a data structure, updating the\n * internal state variables accordingly.\n * @returns The element that is being removed from the beginning of the data structure is being\n * returned.\n */\n shift(): E | undefined {\n if (this._length === 0) return;\n const element = this._buckets[this._bucketFirst][this._firstInBucket];\n if (this._length !== 1) {\n if (this._firstInBucket < this._bucketSize - 1) {\n this._firstInBucket += 1;\n } else if (this._bucketFirst < this._bucketCount - 1) {\n this._bucketFirst += 1;\n this._firstInBucket = 0;\n } else {\n this._bucketFirst = 0;\n this._firstInBucket = 0;\n }\n }\n this._length -= 1;\n return element;\n }\n\n /**\n * Time Complexity: Amortized O(1)\n * Space Complexity: O(n)\n *\n * The `unshift` function adds an element to the beginning of an array-like data structure and\n * returns the new size of the structure.\n * @param {E} element - The `element` parameter represents the element that you want to add to the\n * beginning of the data structure.\n * @returns The size of the data structure after the element has been added.\n */\n unshift(element: E): boolean {\n if (this._length) {\n if (this._firstInBucket > 0) {\n this._firstInBucket -= 1;\n } else if (this._bucketFirst > 0) {\n this._bucketFirst -= 1;\n this._firstInBucket = this._bucketSize - 1;\n } else {\n this._bucketFirst = this._bucketCount - 1;\n this._firstInBucket = this._bucketSize - 1;\n }\n if (this._bucketFirst === this._bucketLast && this._firstInBucket === this._lastInBucket) this._reallocate();\n }\n this._length += 1;\n this._buckets[this._bucketFirst][this._firstInBucket] = element;\n if (this._maxLen > 0 && this._length > this._maxLen) this.pop();\n return true;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The function `pushMany` iterates over elements and pushes them into an array after applying a\n * transformation function if provided.\n * @param {IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>} elements - The `elements`\n * parameter in the `pushMany` function is expected to be an iterable containing elements of type `E`\n * or `R`. It can be either an `IterableWithSizeOrLength<E>` or an `IterableWithSizeOrLength<R>`. The\n * function iterates over each element\n * @returns The `pushMany` function is returning an array of boolean values, where each value\n * represents the result of calling the `push` method on the current object instance with the\n * corresponding element from the input `elements` iterable.\n */\n pushMany(elements: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) {\n ans.push(this.push(this.toElementFn(el as R)));\n } else {\n ans.push(this.push(el as E));\n }\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The `unshiftMany` function in TypeScript iterates over elements and adds them to the beginning of\n * an array, optionally converting them using a provided function.\n * @param {IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>} elements - The `elements`\n * parameter in the `unshiftMany` function is an iterable containing elements of type `E` or `R`. It\n * can be an array or any other iterable data structure that has a known size or length. The function\n * iterates over each element in the `elements` iterable and\n * @returns The `unshiftMany` function returns an array of boolean values indicating whether each\n * element was successfully added to the beginning of the array.\n */\n unshiftMany(elements: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R> = []) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) {\n ans.push(this.unshift(this.toElementFn(el as R)));\n } else {\n ans.push(this.unshift(el as E));\n }\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if the size of an object is equal to zero and returns a boolean value.\n * @returns A boolean value indicating whether the size of the object is 0 or not.\n */\n isEmpty(): boolean {\n return this._length === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear() function resets the state of the object by initializing all variables to their default\n * values.\n */\n clear(): void {\n this._buckets = [new Array(this._bucketSize)];\n this._bucketCount = 1;\n this._bucketFirst = this._bucketLast = this._length = 0;\n this._firstInBucket = this._lastInBucket = this._bucketSize >> 1;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `at` function retrieves an element at a specified position in an array-like data structure.\n * @param {number} pos - The `pos` parameter represents the position of the element that you want to\n * retrieve from the data structure. It is of type `number` and should be a valid index within the\n * range of the data structure.\n * @returns The element at the specified position in the data structure is being returned.\n */\n at(pos: number): E {\n rangeCheck(pos, 0, this._length - 1);\n const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);\n return this._buckets[bucketIndex][indexInBucket]!;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `setAt` function sets an element at a specific position in an array-like data structure.\n * @param {number} pos - The `pos` parameter represents the position at which the element needs to be\n * set. It is of type `number`.\n * @param {E} element - The `element` parameter is the value that you want to set at the specified\n * position in the data structure.\n */\n setAt(pos: number, element: E): boolean {\n rangeCheck(pos, 0, this._length - 1);\n const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);\n this._buckets[bucketIndex][indexInBucket] = element;\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `addAt` function inserts one or more elements at a specified position in an array-like data\n * structure.\n * @param {number} pos - The `pos` parameter represents the position at which the element(s) should\n * be inserted. It is of type `number`.\n * @param {E} element - The `element` parameter represents the element that you want to insert into\n * the array at the specified position.\n * @param [num=1] - The `num` parameter represents the number of times the `element` should be\n * inserted at the specified position (`pos`). By default, it is set to 1, meaning that the `element`\n * will be inserted once. However, you can provide a different value for `num` if you want\n * @returns The size of the array after the insertion is being returned.\n */\n addAt(pos: number, element: E, num = 1): boolean {\n const length = this._length;\n rangeCheck(pos, 0, length);\n if (pos === 0) {\n while (num--) this.unshift(element);\n } else if (pos === this._length) {\n while (num--) this.push(element);\n } else {\n const arr: E[] = [];\n for (let i = pos; i < this._length; ++i) {\n arr.push(this.at(i));\n }\n this.cut(pos - 1, true);\n for (let i = 0; i < num; ++i) this.push(element);\n for (let i = 0; i < arr.length; ++i) this.push(arr[i]);\n }\n return true;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `cut` function updates the state of the object based on the given position and returns the\n * updated size.\n * @param {number} pos - The `pos` parameter represents the position at which the string should be\n * cut. It is a number that indicates the index of the character where the cut should be made.\n * @param {boolean} isCutSelf - If true, the original deque will not be cut, and return a new deque\n * @returns The method is returning the updated size of the data structure.\n */\n cut(pos: number, isCutSelf = false): Deque<E> {\n if (isCutSelf) {\n if (pos < 0) {\n this.clear();\n return this;\n }\n const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);\n this._bucketLast = bucketIndex;\n this._lastInBucket = indexInBucket;\n this._length = pos + 1;\n return this;\n } else {\n const newDeque = this._createInstance({\n bucketSize: this._bucketSize,\n toElementFn: this._toElementFn,\n maxLen: this._maxLen\n });\n\n for (let i = 0; i <= pos; i++) {\n newDeque.push(this.at(i));\n }\n\n return newDeque;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `splice` function in TypeScript overrides the default behavior to remove and insert elements\n * in a Deque data structure while ensuring the starting position and delete count are within bounds.\n * @param {number} start - The `start` parameter in the `splice` method represents the index at which\n * to start changing the array. Items will be removed or added starting from this index.\n * @param {number} deleteCount - The `deleteCount` parameter in the `splice` method represents the\n * number of elements to remove from the array starting at the specified `start` index. If\n * `deleteCount` is not provided, it defaults to the number of elements from the `start` index to the\n * end of the array (`\n * @param {E[]} items - The `items` parameter in the `splice` method represents the elements that\n * will be inserted into the deque at the specified `start` index. These elements will be inserted in\n * place of the elements that are removed based on the `start` and `deleteCount` parameters.\n * @returns The `splice` method is returning the array `deletedElements` which contains the elements\n * that were removed from the Deque during the splice operation.\n */\n override splice(start: number, deleteCount: number = this._length - start, ...items: E[]): this {\n // Check whether the starting position is legal\n rangeCheck(start, 0, this._length);\n\n // Adjust the value of deleteCount\n if (deleteCount < 0) deleteCount = 0;\n if (start + deleteCount > this._length) deleteCount = this._length - start;\n\n // Save deleted elements\n const deletedElements = this._createInstance();\n\n // Add removed elements to the result\n for (let i = 0; i < deleteCount; i++) {\n deletedElements.push(this.at(start + i));\n }\n\n // Calculate the range that needs to be deleted\n const elementsAfter = [];\n for (let i = start + deleteCount; i < this._length; i++) {\n elementsAfter.push(this.at(i));\n }\n\n // Adjust the length of the current Deque\n this.cut(start - 1, true);\n\n for (const item of items) {\n this.push(item);\n }\n\n // Insert subsequent elements back\n for (const element of elementsAfter) {\n this.push(element);\n }\n\n return deletedElements;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1) or O(n)\n *\n * The `cutRest` function cuts the elements from a specified position in a deque and returns a new\n * deque with the cut elements.\n * @param {number} pos - The `pos` parameter represents the position from which to cut the Deque. It\n * is a number that indicates the index of the element in the Deque where the cut should start.\n * @param [isCutSelf=false] - isCutSelf is a boolean parameter that determines whether the original\n * Deque should be modified or a new Deque should be created. If isCutSelf is true, the original\n * Deque will be modified by cutting off elements starting from the specified position. If isCutSelf\n * is false, a new De\n * @returns The function `cutRest` returns either the modified original deque (`this`) or a new deque\n * (`newDeque`) depending on the value of the `isCutSelf` parameter.\n */\n cutRest(pos: number, isCutSelf = false): Deque<E> {\n if (isCutSelf) {\n if (pos < 0) {\n return this;\n }\n const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);\n this._bucketFirst = bucketIndex;\n this._firstInBucket = indexInBucket;\n this._length = this._length - pos;\n return this;\n } else {\n const newDeque = this._createInstance({\n bucketSize: this._bucketSize,\n toElementFn: this._toElementFn,\n maxLen: this._maxLen\n });\n if (pos < 0) pos = 0;\n for (let i = pos; i < this._length; i++) {\n newDeque.push(this.at(i));\n }\n\n return newDeque;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1) or O(n)\n *\n * The `deleteAt` function removes an element at a specified position in an array-like data\n * structure.\n * @param {number} pos - The `pos` parameter in the `deleteAt` function represents the position at\n * which an element needs to be deleted from the data structure. It is of type `number` and indicates\n * the index of the element to be deleted.\n * @returns The size of the data structure after the deletion operation is performed.\n */\n deleteAt(pos: number): E | undefined {\n rangeCheck(pos, 0, this._length - 1);\n\n let deleted: E | undefined;\n if (pos === 0) {\n //If it is the first element, use shift() directly\n return this.shift();\n } else if (pos === this._length - 1) {\n // If it is the last element, just use pop()\n deleted = this.last;\n this.pop();\n return deleted;\n } else {\n // Delete the middle element\n const length = this._length - 1;\n const { bucketIndex: targetBucket, indexInBucket: targetPointer } = this._getBucketAndPosition(pos);\n deleted = this._buckets[targetBucket][targetPointer];\n\n for (let i = pos; i < length; i++) {\n const { bucketIndex: curBucket, indexInBucket: curPointer } = this._getBucketAndPosition(i);\n const { bucketIndex: nextBucket, indexInBucket: nextPointer } = this._getBucketAndPosition(i + 1);\n this._buckets[curBucket][curPointer] = this._buckets[nextBucket][nextPointer];\n }\n\n // Remove last duplicate element\n this.pop();\n return deleted;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `delete` function removes all occurrences of a specified element from an array-like data\n * structure.\n * @param {E} element - The `element` parameter represents the element that you want to delete from\n * the data structure.\n * @returns The size of the data structure after the element has been deleted.\n */\n delete(element: E): boolean {\n const size = this._length;\n if (size === 0) return false;\n let i = 0;\n let index = 0;\n while (i < size) {\n const oldElement = this.at(i);\n if (oldElement !== element) {\n this.setAt(index, oldElement!);\n index += 1;\n }\n i += 1;\n }\n this.cut(index - 1, true);\n return true;\n }\n\n // /**\n // * Time Complexity: O(n)\n // * Space Complexity: O(1)\n // *\n // * This function overrides the indexOf method to search for an element within a custom data\n // * structure.\n // * @param {E} searchElement - The `searchElement` parameter is the element that you are searching for\n // * within the data structure. The `indexOf` method will return the index of the first occurrence of\n // * this element within the data structure.\n // * @param {number} [fromIndex=0] - The `fromIndex` parameter in the `indexOf` method specifies the\n // * index at which to start searching for the `searchElement` within the data structure. If provided,\n // * the search will begin at this index instead of the beginning of the data structure.\n // * @returns The indexOf method is returning the index of the searchElement if it is found in the data\n // * structure, or -1 if the searchElement is not found.\n // */\n // override indexOf(searchElement: E, fromIndex: number = 0): number {\n // let index = fromIndex;\n // let bucketIndex = this._bucketFirst;\n // let indexInBucket = this._firstInBucket + fromIndex;\n //\n // for (let i = 0; i < this._length; i++) {\n // if (this._buckets[bucketIndex][indexInBucket] === searchElement) {\n // return index;\n // }\n // index++;\n // indexInBucket++;\n // if (indexInBucket >= this._bucketSize) {\n // bucketIndex++;\n // indexInBucket = 0;\n // }\n // if (bucketIndex >= this._bucketCount) {\n // bucketIndex = 0;\n // }\n // }\n // return -1;\n // }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The reverse() function reverses the order of the buckets and the elements within each bucket in a\n * data structure.\n * @returns The reverse() method is returning the object itself (this) after performing the reverse\n * operation on the buckets and updating the relevant properties.\n */\n reverse(): this {\n this._buckets.reverse().forEach(function (bucket) {\n bucket.reverse();\n });\n const { _bucketFirst, _bucketLast, _firstInBucket, _lastInBucket } = this;\n this._bucketFirst = this._bucketCount - _bucketLast - 1;\n this._bucketLast = this._bucketCount - _bucketFirst - 1;\n this._firstInBucket = this._bucketSize - _lastInBucket - 1;\n this._lastInBucket = this._bucketSize - _firstInBucket - 1;\n return this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `unique()` function removes duplicate elements from an array-like data structure and returns\n * the number of unique elements.\n * @returns The size of the modified array is being returned.\n */\n unique(): this {\n if (this._length <= 1) {\n return this;\n }\n let index = 1;\n let prev = this.at(0);\n for (let i = 1; i < this._length; ++i) {\n const cur = this.at(i);\n if (cur !== prev) {\n prev = cur;\n this.setAt(index++, cur);\n }\n }\n this.cut(index - 1, true);\n return this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `shrinkToFit` function reorganizes the elements in an array-like data structure to minimize\n * memory usage.\n * @returns Nothing is being returned. The function is using the `return` statement to exit early if\n * `this._length` is 0, but it does not return any value.\n */\n shrinkToFit(): void {\n if (this._length === 0) return;\n const newBuckets = [];\n if (this._bucketFirst === this._bucketLast) return;\n else if (this._bucketFirst < this._bucketLast) {\n for (let i = this._bucketFirst; i <= this._bucketLast; ++i) {\n newBuckets.push(this._buckets[i]);\n }\n } else {\n for (let i = this._bucketFirst; i < this._bucketCount; ++i) {\n newBuckets.push(this._buckets[i]);\n }\n for (let i = 0; i <= this._bucketLast; ++i) {\n newBuckets.push(this._buckets[i]);\n }\n }\n this._bucketFirst = 0;\n this._bucketLast = newBuckets.length - 1;\n this._buckets = newBuckets;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `clone()` function returns a new instance of the `Deque` class with the same elements and\n * bucket size as the original instance.\n * @returns The `clone()` method is returning a new instance of the `Deque` class with the same\n * elements as the original deque (`this`) and the same bucket size.\n */\n clone(): this {\n return new Deque<E, R>(this, {\n bucketSize: this.bucketSize,\n toElementFn: this.toElementFn,\n maxLen: this._maxLen\n }) as this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new deque containing elements from the original deque that satisfy\n * a given predicate function.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * the current element being iterated over, the index of the current element, and the deque itself.\n * It should return a boolean value indicating whether the element should be included in the filtered\n * deque or not.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `predicate` function. If `thisArg` is\n * @returns The `filter` method is returning a new `Deque` object that contains the elements that\n * satisfy the given predicate function.\n */\n filter(predicate: ElementCallback<E, R, boolean>, thisArg?: any): Deque<E, R> {\n const newDeque = this._createInstance({\n bucketSize: this._bucketSize,\n toElementFn: this.toElementFn,\n maxLen: this._maxLen\n });\n let index = 0;\n for (const el of this) {\n if (predicate.call(thisArg, el, index, this)) {\n newDeque.push(el);\n }\n index++;\n }\n return newDeque;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function takes a callback function and applies it to each element in the deque,\n * returning a new deque with the results.\n * @param callback - The callback parameter is a function that will be called for each element in the\n * deque. It takes three arguments: the current element, the index of the element, and the deque\n * itself. It should return a value of type EM.\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to\n * transform the raw element (`RM`) into a new element (`EM`) before adding it to the new deque. If\n * provided, this function will be called for each raw element in the original deque.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new Deque object with elements of type EM and raw elements of type RM.\n */\n map<EM, RM>(callback: ElementCallback<E, R, EM>, toElementFn?: (rawElement: RM) => EM, thisArg?: any): Deque<EM, RM> {\n const newDeque = new Deque<EM, RM>([], { bucketSize: this._bucketSize, toElementFn, maxLen: this._maxLen });\n let index = 0;\n for (const el of this) {\n newDeque.push(callback.call(thisArg, el, index, this));\n index++;\n }\n return newDeque;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The above function is an implementation of the iterator protocol in TypeScript, allowing the\n * object to be iterated over using a for...of loop.\n */\n protected *_getIterator(): IterableIterator<E> {\n for (let i = 0; i < this._length; ++i) {\n yield this.at(i);\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `_reallocate` function reallocates the buckets in an array, adding new buckets if needed.\n * @param {number} [needBucketNum] - The `needBucketNum` parameter is an optional number that\n * specifies the number of new buckets needed. If not provided, it will default to half of the\n * current bucket count (`this._bucketCount >> 1`) or 1 if the current bucket count is less than 2.\n */\n protected _reallocate(needBucketNum?: number) {\n const newBuckets = [];\n const addBucketNum = needBucketNum || this._bucketCount >> 1 || 1;\n for (let i = 0; i < addBucketNum; ++i) {\n newBuckets[i] = new Array(this._bucketSize);\n }\n for (let i = this._bucketFirst; i < this._bucketCount; ++i) {\n newBuckets[newBuckets.length] = this._buckets[i];\n }\n for (let i = 0; i < this._bucketLast; ++i) {\n newBuckets[newBuckets.length] = this._buckets[i];\n }\n newBuckets[newBuckets.length] = [...this._buckets[this._bucketLast]];\n this._bucketFirst = addBucketNum;\n this._bucketLast = newBuckets.length - 1;\n for (let i = 0; i < addBucketNum; ++i) {\n newBuckets[newBuckets.length] = new Array(this._bucketSize);\n }\n this._buckets = newBuckets;\n this._bucketCount = newBuckets.length;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function calculates the bucket index and index within the bucket based on the given position.\n * @param {number} pos - The `pos` parameter represents the position within the data structure. It is\n * a number that indicates the index or position of an element within the structure.\n * @returns an object with two properties: \"bucketIndex\" and \"indexInBucket\".\n */\n protected _getBucketAndPosition(pos: number) {\n let bucketIndex: number;\n let indexInBucket: number;\n\n const overallIndex = this._firstInBucket + pos;\n bucketIndex = this._bucketFirst + Math.floor(overallIndex / this._bucketSize);\n\n if (bucketIndex >= this._bucketCount) {\n bucketIndex -= this._bucketCount;\n }\n\n indexInBucket = ((overallIndex + 1) % this._bucketSize) - 1;\n if (indexInBucket < 0) {\n indexInBucket = this._bucketSize - 1;\n }\n\n return { bucketIndex, indexInBucket };\n }\n\n /**\n * The function `_createInstance` returns a new instance of the `Deque` class with the specified\n * options.\n * @param [options] - The `options` parameter in the `_createInstance` method is of type\n * `DequeOptions<E, R>`, which is an optional parameter that allows you to pass additional\n * configuration options when creating a new instance of the `Deque` class.\n * @returns An instance of the `Deque` class with an empty array and the provided options, casted as\n * `this`.\n */\n protected override _createInstance(options?: DequeOptions<E, R>): this {\n return new Deque<E, R>([], options) as this;\n }\n\n /**\n * This function returns an iterator that iterates over elements in reverse order.\n */\n protected *_getReverseIterator(): IterableIterator<E> {\n for (let i = this._length - 1; i > -1; i--) {\n yield this.at(i);\n }\n }\n}\n","/**\n * data-structure-typed\n * @author Kirk Qi\n * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>\n * @license MIT License\n */\n\nimport type { Comparator, DFSOrderPattern, ElementCallback, HeapOptions } from '../../types';\nimport { IterableElementBase } from '../base';\n\n/**\n * 1. Complete Binary Tree: Heaps are typically complete binary trees, meaning every level is fully filled except possibly for the last level, which has nodes as far left as possible.\n * 2. Heap Properties: Each node in a heap follows a specific order property, which varies depending on the type of heap:\n * Max Heap: The value of each parent node is greater than or equal to the value of its children.\n * Min Heap: The value of each parent node is less than or equal to the value of its children.\n * 3. Root Node Access: In a heap, the largest element (in a max heap) or the smallest element (in a min heap) is always at the root of the tree.\n * 4. Efficient Insertion and Deletion: Due to its structure, a heap allows for insertion and deletion operations in logarithmic time (O(log n)).\n * 5. Managing Dynamic Data Sets: Heaps effectively manage dynamic data sets, especially when frequent access to the largest or smallest elements is required.\n * 6. Non-linear Search: While a heap allows rapid access to its largest or smallest element, it is less efficient for other operations, such as searching for a specific element, as it is not designed for these tasks.\n * 7. Efficient Sorting Algorithms: For example, heap sort. Heap sort uses the properties of a heap to sort elements.\n * 8. Graph Algorithms: Such as Dijkstra's shortest path algorithm and Prime's minimum-spanning tree algorithm, which use heaps to improve performance.\n * @example\n * // Use Heap to sort an array\n * function heapSort(arr: number[]): number[] {\n * const heap = new Heap<number>(arr, { comparator: (a, b) => a - b });\n * const sorted: number[] = [];\n * while (!heap.isEmpty()) {\n * sorted.push(heap.poll()!); // Poll minimum element\n * }\n * return sorted;\n * }\n *\n * const array = [5, 3, 8, 4, 1, 2];\n * console.log(heapSort(array)); // [1, 2, 3, 4, 5, 8]\n * @example\n * // Use Heap to solve top k problems\n * function topKElements(arr: number[], k: number): number[] {\n * const heap = new Heap<number>([], { comparator: (a, b) => b - a }); // Max heap\n * arr.forEach(num => {\n * heap.add(num);\n * if (heap.size > k) heap.poll(); // Keep the heap size at K\n * });\n * return heap.toArray();\n * }\n *\n * const numbers = [10, 30, 20, 5, 15, 25];\n * console.log(topKElements(numbers, 3)); // [15, 10, 5]\n * @example\n * // Use Heap to merge sorted sequences\n * function mergeSortedSequences(sequences: number[][]): number[] {\n * const heap = new Heap<{ value: number; seqIndex: number; itemIndex: number }>([], {\n * comparator: (a, b) => a.value - b.value // Min heap\n * });\n *\n * // Initialize heap\n * sequences.forEach((seq, seqIndex) => {\n * if (seq.length) {\n * heap.add({ value: seq[0], seqIndex, itemIndex: 0 });\n * }\n * });\n *\n * const merged: number[] = [];\n * while (!heap.isEmpty()) {\n * const { value, seqIndex, itemIndex } = heap.poll()!;\n * merged.push(value);\n *\n * if (itemIndex + 1 < sequences[seqIndex].length) {\n * heap.add({\n * value: sequences[seqIndex][itemIndex + 1],\n * seqIndex,\n * itemIndex: itemIndex + 1\n * });\n * }\n * }\n *\n * return merged;\n * }\n *\n * const sequences = [\n * [1, 4, 7],\n * [2, 5, 8],\n * [3, 6, 9]\n * ];\n * console.log(mergeSortedSequences(sequences)); // [1, 2, 3, 4, 5, 6, 7, 8, 9]\n * @example\n * // Use Heap to dynamically maintain the median\n * class MedianFinder {\n * private low: MaxHeap<number>; // Max heap, stores the smaller half\n * private high: MinHeap<number>; // Min heap, stores the larger half\n *\n * constructor() {\n * this.low = new MaxHeap<number>([]);\n * this.high = new MinHeap<number>([]);\n * }\n *\n * addNum(num: number): void {\n * if (this.low.isEmpty() || num <= this.low.peek()!) this.low.add(num);\n * else this.high.add(num);\n *\n * // Balance heaps\n * if (this.low.size > this.high.size + 1) this.high.add(this.low.poll()!);\n * else if (this.high.size > this.low.size) this.low.add(this.high.poll()!);\n * }\n *\n * findMedian(): number {\n * if (this.low.size === this.high.size) return (this.low.peek()! + this.high.peek()!) / 2;\n * return this.low.peek()!;\n * }\n * }\n *\n * const medianFinder = new MedianFinder();\n * medianFinder.addNum(10);\n * console.log(medianFinder.findMedian()); // 10\n * medianFinder.addNum(20);\n * console.log(medianFinder.findMedian()); // 15\n * medianFinder.addNum(30);\n * console.log(medianFinder.findMedian()); // 20\n * medianFinder.addNum(40);\n * console.log(medianFinder.findMedian()); // 25\n * medianFinder.addNum(50);\n * console.log(medianFinder.findMedian()); // 30\n * @example\n * // Use Heap for load balancing\n * function loadBalance(requests: number[], servers: number): number[] {\n * const serverHeap = new Heap<{ id: number; load: number }>([], { comparator: (a, b) => a.load - b.load }); // min heap\n * const serverLoads = new Array(servers).fill(0);\n *\n * for (let i = 0; i < servers; i++) {\n * serverHeap.add({ id: i, load: 0 });\n * }\n *\n * requests.forEach(req => {\n * const server = serverHeap.poll()!;\n * serverLoads[server.id] += req;\n * server.load += req;\n * serverHeap.add(server); // The server after updating the load is re-entered into the heap\n * });\n *\n * return serverLoads;\n * }\n *\n * const requests = [5, 2, 8, 3, 7];\n * console.log(loadBalance(requests, 3)); // [12, 8, 5]\n * @example\n * // Use Heap to schedule tasks\n * type Task = [string, number];\n *\n * function scheduleTasks(tasks: Task[], machines: number): Map<number, Task[]> {\n * const machineHeap = new Heap<{ id: number; load: number }>([], { comparator: (a, b) => a.load - b.load }); // Min heap\n * const allocation = new Map<number, Task[]>();\n *\n * // Initialize the load on each machine\n * for (let i = 0; i < machines; i++) {\n * machineHeap.add({ id: i, load: 0 });\n * allocation.set(i, []);\n * }\n *\n * // Assign tasks\n * tasks.forEach(([task, load]) => {\n * const machine = machineHeap.poll()!;\n * allocation.get(machine.id)!.push([task, load]);\n * machine.load += load;\n * machineHeap.add(machine); // The machine after updating the load is re-entered into the heap\n * });\n *\n * return allocation;\n * }\n *\n * const tasks: Task[] = [\n * ['Task1', 3],\n * ['Task2', 1],\n * ['Task3', 2],\n * ['Task4', 5],\n * ['Task5', 4]\n * ];\n * const expectedMap = new Map<number, Task[]>();\n * expectedMap.set(0, [\n * ['Task1', 3],\n * ['Task4', 5]\n * ]);\n * expectedMap.set(1, [\n * ['Task2', 1],\n * ['Task3', 2],\n * ['Task5', 4]\n * ]);\n * console.log(scheduleTasks(tasks, 2)); // expectedMap\n */\nexport class Heap<E = any, R = any> extends IterableElementBase<E, R> {\n /**\n * The constructor initializes a heap data structure with optional elements and options.\n * @param elements - The `elements` parameter is an iterable object that contains the initial\n * elements to be added to the heap.\n * It is an optional parameter, and if not provided, the heap will\n * be initialized as empty.\n * @param [options] - The `options` parameter is an optional object that can contain additional\n * configuration options for the heap.\n * In this case, it is used to specify a custom comparator\n * function for comparing elements in the heap.\n * The comparator function is used to determine the\n * order of elements in the heap.\n */\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: HeapOptions<E, R>) {\n super(options);\n\n if (options) {\n const { comparator } = options;\n if (comparator) this._comparator = comparator;\n }\n\n this.addMany(elements);\n }\n\n protected _elements: E[] = [];\n\n /**\n * The function returns an array of elements.\n * @returns The element array is being returned.\n */\n get elements(): E[] {\n return this._elements;\n }\n\n /**\n * Get the size (number of elements) of the heap.\n */\n get size(): number {\n return this.elements.length;\n }\n\n /**\n * Get the last element in the heap, which is not necessarily a leaf node.\n * @returns The last element or undefined if the heap is empty.\n */\n get leaf(): E | undefined {\n return this.elements[this.size - 1] ?? undefined;\n }\n\n /**\n * Static method that creates a binary heap from an array of elements and a comparison function.\n * @returns A new Heap instance.\n * @param elements\n * @param options\n */\n static heapify<E = any, R = any>(elements: Iterable<E>, options: HeapOptions<E, R>): Heap<E> {\n return new Heap<E>(elements, options);\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The add function pushes an element into an array and then triggers a bubble-up operation.\n * @param {E} element - The `element` parameter represents the element that you want to add to the\n * data structure.\n * @returns The `add` method is returning a boolean value, which is the result of calling the\n * `_bubbleUp` method with the index `this.elements.length - 1` as an argument.\n */\n add(element: E): boolean {\n this._elements.push(element as E);\n return this._bubbleUp(this.elements.length - 1);\n }\n\n /**\n * Time Complexity: O(k log n)\n * Space Complexity: O(1)\n *\n * The `addMany` function iterates over elements and adds them to a collection, returning an array of\n * boolean values indicating success or failure.\n * @param {Iterable<E> | Iterable<R>} elements - The `elements` parameter in the `addMany` method is\n * an iterable containing elements of type `E` or `R`. The method iterates over each element in the\n * iterable and adds them to the data structure. If a transformation function `_toElementFn` is\n * provided, it transforms the element\n * @returns The `addMany` method returns an array of boolean values indicating whether each element\n * in the input iterable was successfully added to the data structure.\n */\n addMany(elements: Iterable<E> | Iterable<R>): boolean[] {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this._toElementFn) {\n ans.push(this.add(this._toElementFn(el as R)));\n continue;\n }\n ans.push(this.add(el as E));\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Remove and return the top element (the smallest or largest element) from the heap.\n * @returns The top element or undefined if the heap is empty.\n */\n poll(): E | undefined {\n if (this.elements.length === 0) return;\n const value = this.elements[0];\n const last = this.elements.pop()!;\n if (this.elements.length) {\n this.elements[0] = last;\n this._sinkDown(0, this.elements.length >> 1);\n }\n return value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Peek at the top element of the heap without removing it.\n * @returns The top element or undefined if the heap is empty.\n */\n peek(): E | undefined {\n return this.elements[0];\n }\n\n /**\n * Check if the heap is empty.\n * @returns True if the heap is empty, otherwise false.\n */\n isEmpty(): boolean {\n return this.size === 0;\n }\n\n /**\n * Reset the elements of the heap. Make the elements empty.\n */\n clear(): void {\n this._elements = [];\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * Clear and add elements of the heap\n * @param elements\n */\n refill(elements: E[]): boolean[] {\n this._elements = elements;\n return this.fix();\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * Use a comparison function to check whether a binary heap contains a specific element.\n * @param element - the element to check.\n * @returns Returns true if the specified element is contained; otherwise, returns false.\n */\n override has(element: E): boolean {\n return this.elements.includes(element);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `delete` function removes an element from an array-like data structure, maintaining the order\n * and structure of the remaining elements.\n * @param {E} element - The `element` parameter represents the element that you want to delete from\n * the array `this.elements`.\n * @returns The `delete` function is returning a boolean value. It returns `true` if the element was\n * successfully deleted from the array, and `false` if the element was not found in the array.\n */\n delete(element: E): boolean {\n const index = this.elements.indexOf(element);\n if (index < 0) return false;\n if (index === 0) {\n this.poll();\n } else if (index === this.elements.length - 1) {\n this.elements.pop();\n } else {\n this.elements.splice(index, 1, this.elements.pop()!);\n this._bubbleUp(index);\n this._sinkDown(index, this.elements.length >> 1);\n }\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * Depth-first search (DFS) method, different traversal orders can be selected。\n * @param order - Traverse order parameter: 'IN' (in-order), 'PRE' (pre-order) or 'POST' (post-order).\n * @returns An array containing elements traversed in the specified order.\n */\n dfs(order: DFSOrderPattern = 'PRE'): E[] {\n const result: E[] = [];\n\n // Auxiliary recursive function, traverses the binary heap according to the traversal order\n const _dfs = (index: number) => {\n const left = 2 * index + 1,\n right = left + 1;\n if (index < this.size) {\n if (order === 'IN') {\n _dfs(left);\n result.push(this.elements[index]);\n _dfs(right);\n } else if (order === 'PRE') {\n result.push(this.elements[index]);\n _dfs(left);\n _dfs(right);\n } else if (order === 'POST') {\n _dfs(left);\n _dfs(right);\n result.push(this.elements[index]);\n }\n }\n };\n\n _dfs(0); // Traverse starting from the root node\n\n return result;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * Clone the heap, creating a new heap with the same elements.\n * @returns A new Heap instance containing the same elements.\n */\n clone(): Heap<E, R> {\n return new Heap<E, R>(this, { comparator: this.comparator, toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * Sort the elements in the heap and return them as an array.\n * @returns An array containing the elements sorted in ascending order.\n */\n sort(): E[] {\n const visitedNode: E[] = [];\n const cloned = new Heap<E, R>(this, { comparator: this.comparator });\n while (cloned.size !== 0) {\n const top = cloned.poll();\n if (top !== undefined) visitedNode.push(top);\n }\n return visitedNode;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * Fix the entire heap to maintain heap properties.\n */\n fix(): boolean[] {\n const results: boolean[] = [];\n for (let i = Math.floor(this.size / 2); i >= 0; i--) results.push(this._sinkDown(i, this.elements.length >> 1));\n return results;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new Heap object containing elements that pass a given callback\n * function.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: the current element, the index of the current element, and the\n * heap itself. The callback function should return a boolean value indicating whether the current\n * element should be included in the filtered list\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `Heap` object that contains the elements that pass\n * the filter condition specified by the `callback` function.\n */\n filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): Heap<E, R> {\n const filteredList = new Heap<E, R>([], { toElementFn: this.toElementFn, comparator: this.comparator });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredList.add(current);\n }\n index++;\n }\n return filteredList;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function creates a new heap by applying a callback function to each element of the\n * original heap.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: `el` (the current element), `index` (the index of the current\n * element), and `this` (the heap itself). The callback function should return a value of\n * @param comparator - The `comparator` parameter is a function that defines the order of the\n * elements in the heap. It takes two elements `a` and `b` as arguments and returns a negative number\n * if `a` should be placed before `b`, a positive number if `a` should be placed after\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that converts the raw\n * element `RR` to the desired type `T`. It takes a single argument `rawElement` of type `RR` and\n * returns a value of type `T`. This function is used to transform the elements of the original\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `Heap` class with the mapped elements.\n */\n map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n comparator: Comparator<EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): Heap<EM, RM> {\n const mappedHeap: Heap<EM, RM> = new Heap<EM, RM>([], { comparator, toElementFn });\n let index = 0;\n for (const el of this) {\n mappedHeap.add(callback.call(thisArg, el, index, this));\n index++;\n }\n return mappedHeap;\n }\n\n protected _DEFAULT_COMPARATOR = (a: E, b: E): number => {\n if (typeof a === 'object' || typeof b === 'object') {\n throw TypeError(\n `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`\n );\n }\n if (a > b) return 1;\n if (a < b) return -1;\n return 0;\n };\n\n protected _comparator: Comparator<E> = this._DEFAULT_COMPARATOR;\n\n /**\n * The function returns the value of the _comparator property.\n * @returns The `_comparator` property is being returned.\n */\n get comparator() {\n return this._comparator;\n }\n\n /**\n * The function `_getIterator` returns an iterable iterator for the elements in the class.\n */\n protected *_getIterator(): IterableIterator<E> {\n for (const element of this.elements) {\n yield element;\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Float operation to maintain heap properties after adding an element.\n * @param index - The index of the newly added element.\n */\n protected _bubbleUp(index: number): boolean {\n const element = this.elements[index];\n while (index > 0) {\n const parent = (index - 1) >> 1;\n const parentItem = this.elements[parent];\n if (this.comparator(parentItem, element) <= 0) break;\n this.elements[index] = parentItem;\n index = parent;\n }\n this.elements[index] = element;\n return true;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Sinking operation to maintain heap properties after removing the top element.\n * @param index - The index from which to start sinking.\n * @param halfLength\n */\n protected _sinkDown(index: number, halfLength: number): boolean {\n const element = this.elements[index];\n while (index < halfLength) {\n let left = (index << 1) | 1;\n const right = left + 1;\n let minItem = this.elements[left];\n if (right < this.elements.length && this.comparator(minItem, this.elements[right]) > 0) {\n left = right;\n minItem = this.elements[right];\n }\n if (this.comparator(minItem, element) >= 0) break;\n this.elements[index] = minItem;\n index = left;\n }\n this.elements[index] = element;\n return true;\n }\n}\n\nexport class FibonacciHeapNode<E> {\n element: E;\n degree: number;\n left?: FibonacciHeapNode<E>;\n right?: FibonacciHeapNode<E>;\n child?: FibonacciHeapNode<E>;\n parent?: FibonacciHeapNode<E>;\n marked: boolean;\n\n /**\n * The constructor function initializes an object with an element and a degree, and sets the marked\n * property to false.\n * @param {E} element - The \"element\" parameter represents the value or data that will be stored in\n * the node of a data structure. It can be any type of data, such as a number, string, object, or\n * even another data structure.\n * @param [degree=0] - The degree parameter represents the degree of the element in a data structure\n * called a Fibonacci heap. The degree of a node is the number of children it has. By default, the\n * degree is set to 0 when a new node is created.\n */\n constructor(element: E, degree = 0) {\n this.element = element;\n this.degree = degree;\n this.marked = false;\n }\n}\n\nexport class FibonacciHeap<E> {\n /**\n * The constructor function initializes a FibonacciHeap object with an optional comparator function.\n * @param [comparator] - The `comparator` parameter is an optional argument that represents a\n * function used to compare elements in the FibonacciHeap. If a comparator function is provided, it\n * will be used to determine the order of elements in the heap. If no comparator function is\n * provided, a default comparator function will be used.\n */\n constructor(comparator?: Comparator<E>) {\n this.clear();\n this._comparator = comparator || this._defaultComparator;\n\n if (typeof this.comparator !== 'function') {\n throw new Error('FibonacciHeap constructor: given comparator should be a function.');\n }\n }\n\n protected _root?: FibonacciHeapNode<E>;\n\n /**\n * The function returns the root node of a Fibonacci heap.\n * @returns The method is returning either a FibonacciHeapNode object or undefined.\n */\n get root(): FibonacciHeapNode<E> | undefined {\n return this._root;\n }\n\n protected _size = 0;\n\n /**\n * The function returns the size of an object.\n * @returns The size of the object, which is a number.\n */\n get size(): number {\n return this._size;\n }\n\n protected _min?: FibonacciHeapNode<E>;\n\n /**\n * The function returns the minimum node in a Fibonacci heap.\n * @returns The method is returning the minimum node of the Fibonacci heap, which is of type\n * `FibonacciHeapNode<E>`. If there is no minimum node, it will return `undefined`.\n */\n get min(): FibonacciHeapNode<E> | undefined {\n return this._min;\n }\n\n protected _comparator: Comparator<E>;\n\n /**\n * The function returns the comparator used for comparing elements.\n * @returns The `_comparator` property of the object.\n */\n get comparator(): Comparator<E> {\n return this._comparator;\n }\n\n /**\n * Get the size (number of elements) of the heap.\n * @returns {number} The size of the heap. Returns 0 if the heap is empty. Returns -1 if the heap is invalid.\n */\n clear(): void {\n this._root = undefined;\n this._min = undefined;\n this._size = 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Insert an element into the heap and maintain the heap properties.\n * @param element\n * @returns {FibonacciHeap<E>} FibonacciHeap<E> - The heap itself.\n */\n add(element: E): FibonacciHeap<E> {\n return this.push(element);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Insert an element into the heap and maintain the heap properties.\n * @param element\n * @returns {FibonacciHeap<E>} FibonacciHeap<E> - The heap itself.\n */\n push(element: E): FibonacciHeap<E> {\n const node = this.createNode(element);\n node.left = node;\n node.right = node;\n this.mergeWithRoot(node);\n\n if (!this.min || this.comparator(node.element, this.min.element) <= 0) {\n this._min = node;\n }\n\n this._size++;\n return this;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Peek at the top element of the heap without removing it.\n * @returns The top element or undefined if the heap is empty.\n * @protected\n */\n peek(): E | undefined {\n return this.min ? this.min.element : undefined;\n }\n\n /**\n * Time Complexity: O(n), where n is the number of elements in the linked list.\n * Space Complexity: O(1)\n *\n * Get the size (number of elements) of the heap.\n * @param {FibonacciHeapNode<E>} head - The head of the linked list.\n * @protected\n * @returns FibonacciHeapNode<E>[] - An array containing the elements of the linked list.\n */\n consumeLinkedList(head?: FibonacciHeapNode<E>): FibonacciHeapNode<E>[] {\n const elements: FibonacciHeapNode<E>[] = [];\n if (!head) return elements;\n\n let node: FibonacciHeapNode<E> | undefined = head;\n let flag = false;\n\n while (true) {\n if (node === head && flag) break;\n else if (node === head) flag = true;\n\n if (node) {\n elements.push(node);\n node = node.right;\n }\n }\n\n return elements;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * @param parent\n * @param node\n */\n mergeWithChild(parent: FibonacciHeapNode<E>, node: FibonacciHeapNode<E>): void {\n if (!parent.child) {\n parent.child = node;\n } else {\n node.right = parent.child.right;\n node.left = parent.child;\n parent.child.right!.left = node;\n parent.child.right = node;\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Remove and return the top element (the smallest or largest element) from the heap.\n * @returns The top element or undefined if the heap is empty.\n */\n poll(): E | undefined {\n return this.pop();\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Remove and return the top element (the smallest or largest element) from the heap.\n * @returns The top element or undefined if the heap is empty.\n */\n pop(): E | undefined {\n if (this._size === 0) return undefined;\n\n const z = this.min!;\n if (z.child) {\n const elements = this.consumeLinkedList(z.child);\n for (const node of elements) {\n this.mergeWithRoot(node);\n node.parent = undefined;\n }\n }\n\n this.removeFromRoot(z);\n\n if (z === z.right) {\n this._min = undefined;\n this._root = undefined;\n } else {\n this._min = z.right;\n this._consolidate();\n }\n\n this._size--;\n\n return z.element;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * merge two heaps. The heap that is merged will be cleared. The heap that is merged into will remain.\n * @param heapToMerge\n */\n merge(heapToMerge: FibonacciHeap<E>): void {\n if (heapToMerge.size === 0) {\n return; // Nothing to merge\n }\n\n // Merge the root lists of the two heaps\n if (this.root && heapToMerge.root) {\n const thisRoot = this.root;\n const otherRoot = heapToMerge.root;\n\n const thisRootRight = thisRoot.right!;\n const otherRootLeft = otherRoot.left!;\n\n thisRoot.right = otherRoot;\n otherRoot.left = thisRoot;\n\n thisRootRight.left = otherRootLeft;\n otherRootLeft.right = thisRootRight;\n }\n\n // Update the minimum node\n if (!this.min || (heapToMerge.min && this.comparator(heapToMerge.min.element, this.min.element) < 0)) {\n this._min = heapToMerge.min;\n }\n\n // Update the size\n this._size += heapToMerge.size;\n\n // Clear the heap that was merged\n heapToMerge.clear();\n }\n\n /**\n * Create a new node.\n * @param element\n * @protected\n */\n createNode(element: E): FibonacciHeapNode<E> {\n return new FibonacciHeapNode<E>(element);\n }\n\n /**\n * Default comparator function used by the heap.\n * @param {E} a\n * @param {E} b\n * @protected\n */\n protected _defaultComparator(a: E, b: E): number {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Merge the given node with the root list.\n * @param node - The node to be merged.\n */\n protected mergeWithRoot(node: FibonacciHeapNode<E>): void {\n if (!this.root) {\n this._root = node;\n } else {\n node.right = this.root.right;\n node.left = this.root;\n this.root.right!.left = node;\n this.root.right = node;\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Remove and return the top element (the smallest or largest element) from the heap.\n * @param node - The node to be removed.\n * @protected\n */\n protected removeFromRoot(node: FibonacciHeapNode<E>): void {\n if (this.root === node) this._root = node.right;\n if (node.left) node.left.right = node.right;\n if (node.right) node.right.left = node.left;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Remove and return the top element (the smallest or largest element) from the heap.\n * @param y\n * @param x\n * @protected\n */\n protected _link(y: FibonacciHeapNode<E>, x: FibonacciHeapNode<E>): void {\n this.removeFromRoot(y);\n y.left = y;\n y.right = y;\n this.mergeWithChild(x, y);\n x.degree++;\n y.parent = x;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * Remove and return the top element (the smallest or largest element) from the heap.\n * @protected\n */\n protected _consolidate(): void {\n const A: (FibonacciHeapNode<E> | undefined)[] = new Array(this._size);\n const elements = this.consumeLinkedList(this.root);\n let x: FibonacciHeapNode<E> | undefined,\n y: FibonacciHeapNode<E> | undefined,\n d: number,\n t: FibonacciHeapNode<E> | undefined;\n\n for (const node of elements) {\n x = node;\n d = x.degree;\n\n while (A[d]) {\n y = A[d] as FibonacciHeapNode<E>;\n\n if (this.comparator(x.element, y.element) > 0) {\n t = x;\n x = y;\n y = t;\n }\n\n this._link(y, x);\n A[d] = undefined;\n d++;\n }\n\n A[d] = x;\n }\n\n for (let i = 0; i < this._size; i++) {\n if (A[i] && this.comparator(A[i]!.element, this.min!.element) <= 0) {\n this._min = A[i]!;\n }\n }\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Kirk Qi\n * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>\n * @license MIT License\n */\nimport type { Comparator, ElementCallback, HeapOptions } from '../../types';\nimport { Heap } from './heap';\n\n/**\n * 1. Complete Binary Tree: Heaps are typically complete binary trees, meaning every level is fully filled except possibly for the last level, which has nodes as far left as possible.\n * 2. Heap Properties: The value of each parent node is greater than or equal to the value of its children.\n * 3. Root Node Access: In a heap, the largest element (in a max heap) or the smallest element (in a min heap) is always at the root of the tree.\n * 4. Efficient Insertion and Deletion: Due to its structure, a heap allows for insertion and deletion operations in logarithmic time (O(log n)).\n * 5. Managing Dynamic Data Sets: Heaps effectively manage dynamic data sets, especially when frequent access to the largest or smallest elements is required.\n * 6. Non-linear Search: While a heap allows rapid access to its largest or smallest element, it is less efficient for other operations, such as searching for a specific element, as it is not designed for these tasks.\n * 7. Efficient Sorting Algorithms: For example, heap sort. Heap sort uses the properties of a heap to sort elements.\n * 8. Graph Algorithms: Such as Dijkstra's shortest path algorithm and Prim's minimum-spanning tree algorithm, which use heaps to improve performance.\n */\nexport class MaxHeap<E = any, R = any> extends Heap<E, R> {\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: HeapOptions<E, R>) {\n super(elements, {\n comparator: (a: E, b: E): number => {\n if (typeof a === 'object' || typeof b === 'object') {\n throw TypeError(\n `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`\n );\n }\n if (a < b) return 1;\n if (a > b) return -1;\n return 0;\n },\n ...options\n });\n }\n\n /**\n * The `clone` function returns a new instance of the `MaxHeap` class with the same properties as the\n * current instance.\n * @returns The `clone()` method is returning a new instance of the `MaxHeap` class with the same\n * properties as the current instance.\n */\n override clone(): MaxHeap<E, R> {\n return new MaxHeap<E, R>(this, { comparator: this.comparator, toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new MaxHeap object containing elements that pass a given callback\n * function.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: the current element, the index of the current element, and the\n * heap itself. The callback function should return a boolean value indicating whether the current\n * element should be included in the filtered list\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `MaxHeap` object that contains the elements that pass\n * the filter condition specified by the `callback` function.\n */\n override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): MaxHeap<E, R> {\n const filteredList = new MaxHeap<E, R>([], { toElementFn: this.toElementFn, comparator: this.comparator });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredList.add(current);\n }\n index++;\n }\n return filteredList;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * The `map` function creates a new heap by applying a callback function to each element of the\n * original heap.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: `el` (the current element), `index` (the index of the current\n * element), and `this` (the heap itself). The callback function should return a value of\n * @param comparator - The `comparator` parameter is a function that defines the order of the\n * elements in the heap. It takes two elements `a` and `b` as arguments and returns a negative number\n * if `a` should be placed before `b`, a positive number if `a` should be placed after\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that converts the raw\n * element `RR` to the desired type `T`. It takes a single argument `rawElement` of type `RR` and\n * returns a value of type `T`. This function is used to transform the elements of the original\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `MaxHeap` class with the mapped elements.\n */\n override map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n comparator: Comparator<EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): MaxHeap<EM, RM> {\n const mappedHeap: MaxHeap<EM, RM> = new MaxHeap<EM, RM>([], { comparator, toElementFn });\n let index = 0;\n for (const el of this) {\n mappedHeap.add(callback.call(thisArg, el, index, this));\n index++;\n }\n return mappedHeap;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Kirk Qi\n * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>\n * @license MIT License\n */\nimport type { Comparator, ElementCallback, HeapOptions } from '../../types';\nimport { Heap } from './heap';\n\n/**\n * 1. Complete Binary Tree: Heaps are typically complete binary trees, meaning every level is fully filled except possibly for the last level, which has nodes as far left as possible.\n * 2. MinHeap Properties: The value of each parent node is less than or equal to the value of its children.\n * 3. Root Node Access: In a heap, the largest element (in a max heap) or the smallest element (in a min heap) is always at the root of the tree.\n * 4. Efficient Insertion and Deletion: Due to its structure, a heap allows for insertion and deletion operations in logarithmic time (O(log n)).\n * 5. Managing Dynamic Data Sets: Heaps effectively manage dynamic data sets, especially when frequent access to the largest or smallest elements is required.\n * 6. Non-linear Search: While a heap allows rapid access to its largest or smallest element, it is less efficient for other operations, such as searching for a specific element, as it is not designed for these tasks.\n * 7. Efficient Sorting Algorithms: For example, heap sort. MinHeap sort uses the properties of a heap to sort elements.\n * 8. Graph Algorithms: Such as Dijkstra's shortest path algorithm and Prim's minimum spanning tree algorithm, which use heaps to improve performance.\n */\nexport class MinHeap<E = any, R = any> extends Heap<E, R> {\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: HeapOptions<E, R>) {\n super(elements, options);\n }\n\n /**\n * The `clone` function returns a new instance of the `MinHeap` class with the same comparator and\n * toElementFn as the original instance.\n * @returns The `clone()` method is returning a new instance of the `MinHeap` class with the same\n * properties as the current instance.\n */\n override clone(): MinHeap<E, R> {\n return new MinHeap<E, R>(this, { comparator: this.comparator, toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new MinHeap object containing elements that pass a given callback\n * function.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: the current element, the index of the current element, and the\n * heap itself. The callback function should return a boolean value indicating whether the current\n * element should be included in the filtered list\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `MinHeap` object that contains the elements that pass\n * the filter condition specified by the `callback` function.\n */\n override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): MinHeap<E, R> {\n const filteredList = new MinHeap<E, R>([], { toElementFn: this.toElementFn, comparator: this.comparator });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredList.add(current);\n }\n index++;\n }\n return filteredList;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * The `map` function creates a new heap by applying a callback function to each element of the\n * original heap.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: `el` (the current element), `index` (the index of the current\n * element), and `this` (the heap itself). The callback function should return a value of\n * @param comparator - The `comparator` parameter is a function that defines the order of the\n * elements in the heap. It takes two elements `a` and `b` as arguments and returns a negative number\n * if `a` should be placed before `b`, a positive number if `a` should be placed after\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that converts the raw\n * element `RR` to the desired type `T`. It takes a single argument `rawElement` of type `RR` and\n * returns a value of type `T`. This function is used to transform the elements of the original\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `MinHeap` class with the mapped elements.\n */\n override map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n comparator: Comparator<EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): MinHeap<EM, RM> {\n const mappedHeap: MinHeap<EM, RM> = new MinHeap<EM, RM>([], { comparator, toElementFn });\n let index = 0;\n for (const el of this) {\n mappedHeap.add(callback.call(thisArg, el, index, this));\n index++;\n }\n return mappedHeap;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { DijkstraResult, EntryCallback, VertexKey } from '../../types';\nimport { uuidV4 } from '../../utils';\nimport { IterableEntryBase } from '../base';\nimport { IGraph } from '../../interfaces';\nimport { Heap } from '../heap';\nimport { Queue } from '../queue';\n\nexport abstract class AbstractVertex<V = any> {\n key: VertexKey;\n value: V | undefined;\n\n /**\n * The function is a protected constructor that takes an key and an optional value as parameters.\n * @param {VertexKey} key - The `key` parameter is of type `VertexKey` and represents the identifier of the vertex. It is\n * used to uniquely identify the vertex object.\n * @param {V} [value] - The parameter \"value\" is an optional parameter of type V. It is used to assign a value to the\n * vertex. If no value is provided, it will be set to undefined.\n */\n protected constructor(key: VertexKey, value?: V) {\n this.key = key;\n this.value = value;\n }\n}\n\nexport abstract class AbstractEdge<E = any> {\n value: E | undefined;\n weight: number;\n\n /**\n * The above function is a protected constructor that initializes the weight, value, and hash code properties of an\n * object.\n * @param {number} [weight] - The `weight` parameter is an optional number that represents the weight of the object. If\n * a value is provided, it will be assigned to the `_weight` property. If no value is provided, the default value of 1\n * will be assigned.\n * @param {VO} [value] - The `value` parameter is of type `VO`, which means it can be any type. It is an optional parameter,\n * meaning it can be omitted when creating an instance of the class.\n */\n protected constructor(weight?: number, value?: E) {\n this.weight = weight !== undefined ? weight : 1;\n this.value = value;\n this._hashCode = uuidV4();\n }\n\n protected _hashCode: string;\n\n get hashCode(): string {\n return this._hashCode;\n }\n\n /**\n * In TypeScript, a subclass inherits the interface implementation of its parent class, without needing to implement the same interface again in the subclass. This behavior differs from Java's approach. In Java, if a parent class implements an interface, the subclass needs to explicitly implement the same interface, even if the parent class has already implemented it.\n * This means that using abstract methods in the parent class cannot constrain the grandchild classes. Defining methods within an interface also cannot constrain the descendant classes. When inheriting from this class, developers need to be aware that this method needs to be overridden.\n */\n}\n\nexport abstract class AbstractGraph<\n V = any,\n E = any,\n VO extends AbstractVertex<V> = AbstractVertex<V>,\n EO extends AbstractEdge<E> = AbstractEdge<E>\n >\n extends IterableEntryBase<VertexKey, V | undefined>\n implements IGraph<V, E, VO, EO>\n{\n constructor() {\n super();\n }\n\n protected _vertexMap: Map<VertexKey, VO> = new Map<VertexKey, VO>();\n\n get vertexMap(): Map<VertexKey, VO> {\n return this._vertexMap;\n }\n\n set vertexMap(v: Map<VertexKey, VO>) {\n this._vertexMap = v;\n }\n\n get size(): number {\n return this._vertexMap.size;\n }\n\n /**\n * In TypeScript, a subclass inherits the interface implementation of its parent class, without needing to implement the same interface again in the subclass. This behavior differs from Java's approach. In Java, if a parent class implements an interface, the subclass needs to explicitly implement the same interface, even if the parent class has already implemented it.\n * This means that using abstract methods in the parent class cannot constrain the grandchild classes. Defining methods within an interface also cannot constrain the descendant classes. When inheriting from this class, developers need to be aware that this method needs to be overridden.\n * @param key\n * @param value\n */\n abstract createVertex(key: VertexKey, value?: V): VO;\n\n /**\n * In TypeScript, a subclass inherits the interface implementation of its parent class, without needing to implement the same interface again in the subclass. This behavior differs from Java's approach. In Java, if a parent class implements an interface, the subclass needs to explicitly implement the same interface, even if the parent class has already implemented it.\n * This means that using abstract methods in the parent class cannot constrain the grandchild classes. Defining methods within an interface also cannot constrain the descendant classes. When inheriting from this class, developers need to be aware that this method needs to be overridden.\n * @param srcOrV1\n * @param destOrV2\n * @param weight\n * @param value\n */\n abstract createEdge(srcOrV1: VertexKey, destOrV2: VertexKey, weight?: number, value?: E): EO;\n\n abstract deleteEdge(edge: EO): EO | undefined;\n\n abstract getEdge(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | undefined;\n\n abstract degreeOf(vertexOrKey: VO | VertexKey): number;\n\n abstract edgeSet(): EO[];\n\n abstract edgesOf(vertexOrKey: VO | VertexKey): EO[];\n\n abstract getNeighbors(vertexOrKey: VO | VertexKey): VO[];\n\n abstract getEndsOfEdge(edge: EO): [VO, VO] | undefined;\n\n /**\n * Time Complexity: O(1) - Constant time for Map lookup.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n *\n * The function \"getVertex\" returns the vertex with the specified ID or undefined if it doesn't exist.\n * @param {VertexKey} vertexKey - The `vertexKey` parameter is the identifier of the vertex that you want to retrieve from\n * the `_vertexMap` map.\n * @returns The method `getVertex` returns the vertex with the specified `vertexKey` if it exists in the `_vertexMap`\n * map. If the vertex does not exist, it returns `undefined`.\n */\n getVertex(vertexKey: VertexKey): VO | undefined {\n return this._vertexMap.get(vertexKey) || undefined;\n }\n\n /**\n * Time Complexity: O(1) - Constant time for Map lookup.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n *\n * The function checks if a vertex exists in a graph.\n * @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can be either a vertex object (`VO`) or a vertex ID\n * (`VertexKey`).\n * @returns a boolean value.\n */\n hasVertex(vertexOrKey: VO | VertexKey): boolean {\n return this._vertexMap.has(this._getVertexKey(vertexOrKey));\n }\n\n addVertex(vertex: VO): boolean;\n\n addVertex(key: VertexKey, value?: V): boolean;\n\n /**\n * Time Complexity: O(1) - Constant time for Map operations.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n */\n\n addVertex(keyOrVertex: VertexKey | VO, value?: V): boolean {\n if (keyOrVertex instanceof AbstractVertex) {\n return this._addVertex(keyOrVertex);\n } else {\n const newVertex = this.createVertex(keyOrVertex, value);\n return this._addVertex(newVertex);\n }\n }\n\n isVertexKey(potentialKey: any): potentialKey is VertexKey {\n const potentialKeyType = typeof potentialKey;\n return potentialKeyType === 'string' || potentialKeyType === 'number';\n }\n\n /**\n * Time Complexity: O(1) - Constant time for Map operations.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n */\n\n abstract deleteVertex(vertexOrKey: VO | VertexKey): boolean;\n\n /**\n * Time Complexity: O(K), where K is the number of vertexMap to be removed.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n *\n * The function removes all vertexMap from a graph and returns a boolean indicating if any vertexMap were removed.\n * @param {VO[] | VertexKey[]} vertexMap - The `vertexMap` parameter can be either an array of vertexMap (`VO[]`) or an array\n * of vertex IDs (`VertexKey[]`).\n * @returns a boolean value. It returns true if at least one vertex was successfully removed, and false if no vertexMap\n * were removed.\n */\n removeManyVertices(vertexMap: VO[] | VertexKey[]): boolean {\n const removed: boolean[] = [];\n for (const v of vertexMap) {\n removed.push(this.deleteVertex(v));\n }\n return removed.length > 0;\n }\n\n /**\n * Time Complexity: O(1) - Depends on the implementation in the concrete class.\n * Space Complexity: O(1) - Depends on the implementation in the concrete class.\n *\n * The function checks if there is an edge between two vertexMap and returns a boolean value indicating the result.\n * @param {VertexKey | VO} v1 - The parameter v1 can be either a VertexKey or a VO. A VertexKey represents the unique\n * identifier of a vertex in a graph, while VO represents the type of the vertex object itself.\n * @param {VertexKey | VO} v2 - The parameter `v2` represents the second vertex in the edge. It can be either a\n * `VertexKey` or a `VO` type, which represents the type of the vertex.\n * @returns A boolean value is being returned.\n */\n hasEdge(v1: VertexKey | VO, v2: VertexKey | VO): boolean {\n const edge = this.getEdge(v1, v2);\n return !!edge;\n }\n\n addEdge(edge: EO): boolean;\n\n addEdge(src: VO | VertexKey, dest: VO | VertexKey, weight?: number, value?: E): boolean;\n\n /**\n * Time Complexity: O(1) - Depends on the implementation in the concrete class.\n * Space Complexity: O(1) - Depends on the implementation in the concrete class.\n */\n\n addEdge(srcOrEdge: VO | VertexKey | EO, dest?: VO | VertexKey, weight?: number, value?: E): boolean {\n if (srcOrEdge instanceof AbstractEdge) {\n return this._addEdge(srcOrEdge);\n } else {\n if (dest instanceof AbstractVertex || typeof dest === 'string' || typeof dest === 'number') {\n if (!(this.hasVertex(srcOrEdge) && this.hasVertex(dest))) return false;\n if (srcOrEdge instanceof AbstractVertex) srcOrEdge = srcOrEdge.key;\n if (dest instanceof AbstractVertex) dest = dest.key;\n const newEdge = this.createEdge(srcOrEdge, dest, weight, value);\n return this._addEdge(newEdge);\n } else {\n throw new Error('dest must be a Vertex or vertex key while srcOrEdge is an Edge');\n }\n }\n }\n\n /**\n * Time Complexity: O(1) - Constant time for Map and Edge operations.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n *\n * The function sets the weight of an edge between two vertexMap in a graph.\n * @param {VertexKey | VO} srcOrKey - The `srcOrKey` parameter can be either a `VertexKey` or a `VO` object. It represents\n * the source vertex of the edge.\n * @param {VertexKey | VO} destOrKey - The `destOrKey` parameter represents the destination vertex of the edge. It can be\n * either a `VertexKey` or a vertex object `VO`.\n * @param {number} weight - The weight parameter represents the weight of the edge between the source vertex (srcOrKey)\n * and the destination vertex (destOrKey).\n * @returns a boolean value. If the edge exists between the source and destination vertexMap, the function will update\n * the weight of the edge and return true. If the edge does not exist, the function will return false.\n */\n setEdgeWeight(srcOrKey: VertexKey | VO, destOrKey: VertexKey | VO, weight: number): boolean {\n const edge = this.getEdge(srcOrKey, destOrKey);\n if (edge) {\n edge.weight = weight;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Time Complexity: O(P), where P is the number of paths found (in the worst case, exploring all paths).\n * Space Complexity: O(P) - Linear space, where P is the number of paths found.\n *\n * The function `getAllPathsBetween` finds all paths between two vertexMap in a graph using depth-first search.\n * @param {VO | VertexKey} v1 - The parameter `v1` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).\n * It is the starting vertex for finding paths.\n * @param {VO | VertexKey} v2 - The parameter `v2` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).\n * @param limit - The count of limitation of result array.\n * @returns The function `getAllPathsBetween` returns an array of arrays of vertexMap (`VO[][]`).\n */\n getAllPathsBetween(v1: VO | VertexKey, v2: VO | VertexKey, limit = 1000): VO[][] {\n const paths: VO[][] = [];\n const vertex1 = this._getVertex(v1);\n const vertex2 = this._getVertex(v2);\n\n if (!(vertex1 && vertex2)) {\n return [];\n }\n\n const stack: { vertex: VO; path: VO[] }[] = [];\n stack.push({ vertex: vertex1, path: [vertex1] });\n\n while (stack.length > 0) {\n const { vertex, path } = stack.pop()!;\n\n if (vertex === vertex2) {\n paths.push(path);\n if (paths.length >= limit) return paths;\n }\n\n const neighbors = this.getNeighbors(vertex);\n for (const neighbor of neighbors) {\n if (!path.includes(neighbor)) {\n const newPath = [...path, neighbor];\n stack.push({ vertex: neighbor, path: newPath });\n }\n }\n }\n return paths;\n }\n\n /**\n * Time Complexity: O(L), where L is the length of the path.\n * Space Complexity: O(1) - Constant space.\n *\n * The function calculates the sum of weights along a given path.\n * @param {VO[]} path - An array of vertexMap (VO) representing a path in a graph.\n * @returns The function `getPathSumWeight` returns the sum of the weights of the edgeMap in the given path.\n */\n getPathSumWeight(path: VO[]): number {\n let sum = 0;\n for (let i = 0; i < path.length; i++) {\n sum += this.getEdge(path[i], path[i + 1])?.weight || 0;\n }\n return sum;\n }\n\n /**\n * Time Complexity: O(V + E) - Depends on the implementation (Dijkstra's algorithm).\n * Space Complexity: O(V + E) - Depends on the implementation (Dijkstra's algorithm).\n *\n * The function `getMinCostBetween` calculates the minimum cost between two vertexMap in a graph, either based on edge\n * weights or using a breadth-first search algorithm.\n * @param {VO | VertexKey} v1 - The parameter `v1` represents the starting vertex or its ID.\n * @param {VO | VertexKey} v2 - The parameter `v2` represents the destination vertex or its ID. It is the vertex to which\n * you want to find the minimum cost or weight from the source vertex `v1`.\n * @param {boolean} [isWeight] - isWeight is an optional parameter that indicates whether the graph edgeMap have weights.\n * If isWeight is set to true, the function will calculate the minimum cost between v1 and v2 based on the weights of\n * the edgeMap. If isWeight is set to false or not provided, the function will calculate the\n * @returns The function `getMinCostBetween` returns a number representing the minimum cost between two vertexMap (`v1`\n * and `v2`). If the `isWeight` parameter is `true`, it calculates the minimum weight among all paths between the\n * vertexMap. If `isWeight` is `false` or not provided, it uses a breadth-first search (BFS) algorithm to calculate the\n * minimum number of\n */\n getMinCostBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean): number | undefined {\n if (isWeight === undefined) isWeight = false;\n\n if (isWeight) {\n const allPaths = this.getAllPathsBetween(v1, v2);\n let min = Infinity;\n for (const path of allPaths) {\n min = Math.min(this.getPathSumWeight(path), min);\n }\n return min;\n } else {\n // BFS\n const vertex2 = this._getVertex(v2);\n const vertex1 = this._getVertex(v1);\n if (!(vertex1 && vertex2)) {\n return undefined;\n }\n\n const visited: Map<VO, boolean> = new Map();\n const queue = new Queue<VO>([vertex1]);\n visited.set(vertex1, true);\n let cost = 0;\n while (queue.length > 0) {\n for (let i = 0; i < queue.length; i++) {\n const cur = queue.shift();\n if (cur === vertex2) {\n return cost;\n }\n // TODO consider optimizing to AbstractGraph\n if (cur !== undefined) {\n const neighbors = this.getNeighbors(cur);\n for (const neighbor of neighbors) {\n if (!visited.has(neighbor)) {\n visited.set(neighbor, true);\n queue.push(neighbor);\n }\n }\n }\n }\n cost++;\n }\n return undefined;\n }\n }\n\n /**\n * Time Complexity: O(V + E) - Depends on the implementation (Dijkstra's algorithm or DFS).\n * Space Complexity: O(V + E) - Depends on the implementation (Dijkstra's algorithm or DFS).\n *\n * The function `getMinPathBetween` returns the minimum path between two vertexMap in a graph, either based on weight or\n * using a breadth-first search algorithm.\n * @param {VO | VertexKey} v1 - The parameter `v1` represents the starting vertex of the path. It can be either a vertex\n * object (`VO`) or a vertex ID (`VertexKey`).\n * @param {VO | VertexKey} v2 - VO | VertexKey - The second vertex or vertex ID between which we want to find the minimum\n * path.\n * @param {boolean} [isWeight] - A boolean flag indicating whether to consider the weight of edgeMap in finding the\n * minimum path. If set to true, the function will use Dijkstra's algorithm to find the minimum weighted path. If set\n * to false, the function will use breadth-first search (BFS) to find the minimum path.\n * @param isDFS - If set to true, it enforces the use of getAllPathsBetween to first obtain all possible paths,\n * followed by iterative computation of the shortest path. This approach may result in exponential time complexity,\n * so the default method is to use the Dijkstra algorithm to obtain the shortest weighted path.\n * @returns The function `getMinPathBetween` returns an array of vertexMap (`VO[]`) representing the minimum path between\n * two vertexMap (`v1` and `v2`). If there is no path between the vertexMap, it returns `undefined`.\n */\n getMinPathBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean, isDFS = false): VO[] | undefined {\n if (isWeight === undefined) isWeight = false;\n\n if (isWeight) {\n if (isDFS) {\n const allPaths = this.getAllPathsBetween(v1, v2, 10000);\n let min = Infinity;\n let minIndex = -1;\n let index = 0;\n for (const path of allPaths) {\n const pathSumWeight = this.getPathSumWeight(path);\n if (pathSumWeight < min) {\n min = pathSumWeight;\n minIndex = index;\n }\n index++;\n }\n return allPaths[minIndex] || undefined;\n } else {\n return this.dijkstra(v1, v2, true, true)?.minPath ?? [];\n }\n } else {\n // DFS\n let minPath: VO[] = [];\n const vertex1 = this._getVertex(v1);\n const vertex2 = this._getVertex(v2);\n if (!(vertex1 && vertex2)) return [];\n\n const dfs = (cur: VO, dest: VO, visiting: Set<VO>, path: VO[]) => {\n visiting.add(cur);\n if (cur === dest) {\n minPath = [vertex1, ...path];\n return;\n }\n\n const neighbors = this.getNeighbors(cur);\n for (const neighbor of neighbors) {\n if (!visiting.has(neighbor)) {\n path.push(neighbor);\n dfs(neighbor, dest, visiting, path);\n path.pop();\n }\n }\n\n visiting.delete(cur);\n };\n\n dfs(vertex1, vertex2, new Set<VO>(), []);\n return minPath;\n }\n }\n\n /**\n * Time Complexity: O(V^2 + E) - Quadratic time in the worst case (no heap optimization).\n * Space Complexity: O(V + E) - Depends on the implementation (Dijkstra's algorithm).\n *\n * The function `dijkstraWithoutHeap` implements Dijkstra's algorithm to find the shortest path between two vertexMap in\n * a graph without using a heap data structure.\n * @param {VO | VertexKey} src - The source vertex from which to start the Dijkstra's algorithm. It can be either a\n * vertex object or a vertex ID.\n * @param {VO | VertexKey | undefined} [dest] - The `dest` parameter in the `dijkstraWithoutHeap` function is an optional\n * parameter that specifies the destination vertex for the Dijkstra algorithm. It can be either a vertex object or its\n * identifier. If no destination is provided, the value is set to `undefined`.\n * @param {boolean} [getMinDist] - The `getMinDist` parameter is a boolean flag that determines whether the minimum\n * distance from the source vertex to the destination vertex should be calculated and returned in the result. If\n * `getMinDist` is set to `true`, the `minDist` property in the result will contain the minimum distance\n * @param {boolean} [genPaths] - The `genPaths` parameter is a boolean flag that determines whether or not to generate\n * paths in the Dijkstra algorithm. If `genPaths` is set to `true`, the algorithm will calculate and return the\n * shortest paths from the source vertex to all other vertexMap in the graph. If `genPaths\n * @returns The function `dijkstraWithoutHeap` returns an object of type `DijkstraResult<VO>`.\n */\n dijkstraWithoutHeap(\n src: VO | VertexKey,\n dest: VO | VertexKey | undefined = undefined,\n getMinDist: boolean = false,\n genPaths: boolean = false\n ): DijkstraResult<VO> {\n let minDist = Infinity;\n let minDest: VO | undefined = undefined;\n let minPath: VO[] = [];\n const paths: VO[][] = [];\n\n const vertexMap = this._vertexMap;\n const distMap: Map<VO, number> = new Map();\n const seen: Set<VO> = new Set();\n const preMap: Map<VO, VO | undefined> = new Map(); // predecessor\n const srcVertex = this._getVertex(src);\n\n const destVertex = dest ? this._getVertex(dest) : undefined;\n\n if (!srcVertex) {\n return undefined;\n }\n\n for (const vertex of vertexMap) {\n const vertexOrKey = vertex[1];\n if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Infinity);\n }\n distMap.set(srcVertex, 0);\n preMap.set(srcVertex, undefined);\n\n const getMinOfNoSeen = () => {\n let min = Infinity;\n let minV: VO | undefined = undefined;\n for (const [key, value] of distMap) {\n if (!seen.has(key)) {\n if (value < min) {\n min = value;\n minV = key;\n }\n }\n }\n return minV;\n };\n\n const getPaths = (minV: VO | undefined) => {\n for (const vertex of vertexMap) {\n const vertexOrKey = vertex[1];\n\n if (vertexOrKey instanceof AbstractVertex) {\n const path: VO[] = [vertexOrKey];\n let parent = preMap.get(vertexOrKey);\n while (parent) {\n path.push(parent);\n parent = preMap.get(parent);\n }\n const reversed = path.reverse();\n if (vertex[1] === minV) minPath = reversed;\n paths.push(reversed);\n }\n }\n };\n\n for (let i = 1; i < vertexMap.size; i++) {\n const cur = getMinOfNoSeen();\n if (cur) {\n seen.add(cur);\n if (destVertex && destVertex === cur) {\n if (getMinDist) {\n minDist = distMap.get(destVertex) || Infinity;\n }\n if (genPaths) {\n getPaths(destVertex);\n }\n return { distMap, preMap, seen, paths, minDist, minPath };\n }\n const neighbors = this.getNeighbors(cur);\n for (const neighbor of neighbors) {\n if (!seen.has(neighbor)) {\n const edge = this.getEdge(cur, neighbor);\n if (edge) {\n const curFromMap = distMap.get(cur);\n const neighborFromMap = distMap.get(neighbor);\n // TODO after no-non-undefined-assertion not ensure the logic\n if (curFromMap !== undefined && neighborFromMap !== undefined) {\n if (edge.weight + curFromMap < neighborFromMap) {\n distMap.set(neighbor, edge.weight + curFromMap);\n preMap.set(neighbor, cur);\n }\n }\n }\n }\n }\n }\n }\n\n if (getMinDist)\n distMap.forEach((d, v) => {\n if (v !== srcVertex) {\n if (d < minDist) {\n minDist = d;\n if (genPaths) minDest = v;\n }\n }\n });\n\n if (genPaths) getPaths(minDest);\n\n return { distMap, preMap, seen, paths, minDist, minPath };\n }\n\n /**\n * Time Complexity: O((V + E) * log(V)) - Depends on the implementation (using a binary heap).\n * Space Complexity: O(V + E) - Depends on the implementation (using a binary heap).\n *\n * Dijkstra's algorithm is used to find the shortest paths from a source node to all other nodes in a graph. Its basic idea is to repeatedly choose the node closest to the source node and update the distances of other nodes using this node as an intermediary. Dijkstra's algorithm requires that the edge weights in the graph are non-negative.\n * The `dijkstra` function implements Dijkstra's algorithm to find the shortest path between a source vertex and an\n * optional destination vertex, and optionally returns the minimum distance, the paths, and other information.\n * @param {VO | VertexKey} src - The `src` parameter represents the source vertex from which the Dijkstra algorithm will\n * start. It can be either a vertex object or a vertex ID.\n * @param {VO | VertexKey | undefined} [dest] - The `dest` parameter is the destination vertex or vertex ID. It specifies the\n * vertex to which the shortest path is calculated from the source vertex. If no destination is provided, the algorithm\n * will calculate the shortest paths to all other vertexMap from the source vertex.\n * @param {boolean} [getMinDist] - The `getMinDist` parameter is a boolean flag that determines whether the minimum\n * distance from the source vertex to the destination vertex should be calculated and returned in the result. If\n * `getMinDist` is set to `true`, the `minDist` property in the result will contain the minimum distance\n * @param {boolean} [genPaths] - The `genPaths` parameter is a boolean flag that determines whether or not to generate\n * paths in the Dijkstra algorithm. If `genPaths` is set to `true`, the algorithm will calculate and return the\n * shortest paths from the source vertex to all other vertexMap in the graph. If `genPaths\n * @returns The function `dijkstra` returns an object of type `DijkstraResult<VO>`.\n */\n dijkstra(\n src: VO | VertexKey,\n dest: VO | VertexKey | undefined = undefined,\n getMinDist: boolean = false,\n genPaths: boolean = false\n ): DijkstraResult<VO> {\n let minDist = Infinity;\n let minDest: VO | undefined = undefined;\n let minPath: VO[] = [];\n const paths: VO[][] = [];\n const vertexMap = this._vertexMap;\n const distMap: Map<VO, number> = new Map();\n const seen: Set<VO> = new Set();\n const preMap: Map<VO, VO | undefined> = new Map(); // predecessor\n\n const srcVertex = this._getVertex(src);\n const destVertex = dest ? this._getVertex(dest) : undefined;\n\n if (!srcVertex) return undefined;\n\n for (const vertex of vertexMap) {\n const vertexOrKey = vertex[1];\n if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Infinity);\n }\n\n const heap = new Heap<{ key: number; value: VO }>([], { comparator: (a, b) => a.key - b.key });\n heap.add({ key: 0, value: srcVertex });\n\n distMap.set(srcVertex, 0);\n preMap.set(srcVertex, undefined);\n\n /**\n * The function `getPaths` retrieves all paths from vertexMap to a specified minimum vertex.\n * @param {VO | undefined} minV - The parameter `minV` is of type `VO | undefined`. It represents the minimum vertex value or\n * undefined.\n */\n const getPaths = (minV: VO | undefined) => {\n for (const vertex of vertexMap) {\n const vertexOrKey = vertex[1];\n if (vertexOrKey instanceof AbstractVertex) {\n const path: VO[] = [vertexOrKey];\n let parent = preMap.get(vertexOrKey);\n while (parent) {\n path.push(parent);\n parent = preMap.get(parent);\n }\n const reversed = path.reverse();\n if (vertex[1] === minV) minPath = reversed;\n paths.push(reversed);\n }\n }\n };\n\n while (heap.size > 0) {\n const curHeapNode = heap.poll();\n const dist = curHeapNode?.key;\n const cur = curHeapNode?.value;\n if (dist !== undefined) {\n if (cur) {\n seen.add(cur);\n if (destVertex && destVertex === cur) {\n if (getMinDist) {\n minDist = distMap.get(destVertex) || Infinity;\n }\n if (genPaths) {\n getPaths(destVertex);\n }\n return { distMap, preMap, seen, paths, minDist, minPath };\n }\n const neighbors = this.getNeighbors(cur);\n for (const neighbor of neighbors) {\n if (!seen.has(neighbor)) {\n const weight = this.getEdge(cur, neighbor)?.weight;\n if (typeof weight === 'number') {\n const distSrcToNeighbor = distMap.get(neighbor);\n if (distSrcToNeighbor) {\n if (dist + weight < distSrcToNeighbor) {\n heap.add({ key: dist + weight, value: neighbor });\n preMap.set(neighbor, cur);\n distMap.set(neighbor, dist + weight);\n }\n }\n }\n }\n }\n }\n }\n }\n\n if (getMinDist) {\n distMap.forEach((d, v) => {\n if (v !== srcVertex) {\n if (d < minDist) {\n minDist = d;\n if (genPaths) minDest = v;\n }\n }\n });\n }\n\n if (genPaths) {\n getPaths(minDest);\n }\n\n return { distMap, preMap, seen, paths, minDist, minPath };\n }\n\n /**\n * Time Complexity: O(V * E) - Quadratic time in the worst case (Bellman-Ford algorithm).\n * Space Complexity: O(V + E) - Depends on the implementation (Bellman-Ford algorithm).\n *\n * one to rest pairs\n * The Bellman-Ford algorithm is also used to find the shortest paths from a source node to all other nodes in a graph. Unlike Dijkstra's algorithm, it can handle edge weights that are negative. Its basic idea involves iterative relaxation of all edgeMap for several rounds to gradually approximate the shortest paths. Due to its ability to handle negative-weight edgeMap, the Bellman-Ford algorithm is more flexible in some scenarios.\n * The `bellmanFord` function implements the Bellman-Ford algorithm to find the shortest path from a source vertex to\n * all other vertexMap in a graph, and optionally detects negative cycles and generates the minimum path.\n * @param {VO | VertexKey} src - The `src` parameter is the source vertex from which the Bellman-Ford algorithm will\n * start calculating the shortest paths. It can be either a vertex object or a vertex ID.\n * @param {boolean} [scanNegativeCycle] - A boolean flag indicating whether to scan for negative cycles in the graph.\n * @param {boolean} [getMin] - The `getMin` parameter is a boolean flag that determines whether the algorithm should\n * calculate the minimum distance from the source vertex to all other vertexMap in the graph. If `getMin` is set to\n * `true`, the algorithm will find the minimum distance and update the `min` variable with the minimum\n * @param {boolean} [genPath] - A boolean flag indicating whether to generate paths for all vertexMap from the source\n * vertex.\n * @returns The function `bellmanFord` returns an object with the following properties:\n */\n bellmanFord(src: VO | VertexKey, scanNegativeCycle?: boolean, getMin?: boolean, genPath?: boolean) {\n if (getMin === undefined) getMin = false;\n if (genPath === undefined) genPath = false;\n\n const srcVertex = this._getVertex(src);\n const paths: VO[][] = [];\n const distMap: Map<VO, number> = new Map();\n const preMap: Map<VO, VO> = new Map(); // predecessor\n let min = Infinity;\n let minPath: VO[] = [];\n // TODO\n let hasNegativeCycle: boolean | undefined;\n if (scanNegativeCycle) hasNegativeCycle = false;\n if (!srcVertex) return { hasNegativeCycle, distMap, preMap, paths, min, minPath };\n\n const vertexMap = this._vertexMap;\n const numOfVertices = vertexMap.size;\n const edgeMap = this.edgeSet();\n const numOfEdges = edgeMap.length;\n\n this._vertexMap.forEach(vertex => {\n distMap.set(vertex, Infinity);\n });\n\n distMap.set(srcVertex, 0);\n\n for (let i = 1; i < numOfVertices; ++i) {\n for (let j = 0; j < numOfEdges; ++j) {\n const ends = this.getEndsOfEdge(edgeMap[j]);\n if (ends) {\n const [s, d] = ends;\n const weight = edgeMap[j].weight;\n const sWeight = distMap.get(s);\n const dWeight = distMap.get(d);\n if (sWeight !== undefined && dWeight !== undefined) {\n if (distMap.get(s) !== Infinity && sWeight + weight < dWeight) {\n distMap.set(d, sWeight + weight);\n if (genPath) preMap.set(d, s);\n }\n }\n }\n }\n }\n\n let minDest: VO | undefined = undefined;\n if (getMin) {\n distMap.forEach((d, v) => {\n if (v !== srcVertex) {\n if (d < min) {\n min = d;\n if (genPath) minDest = v;\n }\n }\n });\n }\n\n if (genPath) {\n for (const vertex of vertexMap) {\n const vertexOrKey = vertex[1];\n if (vertexOrKey instanceof AbstractVertex) {\n const path: VO[] = [vertexOrKey];\n let parent = preMap.get(vertexOrKey);\n while (parent !== undefined) {\n path.push(parent);\n parent = preMap.get(parent);\n }\n const reversed = path.reverse();\n if (vertex[1] === minDest) minPath = reversed;\n paths.push(reversed);\n }\n }\n }\n\n for (let j = 0; j < numOfEdges; ++j) {\n const ends = this.getEndsOfEdge(edgeMap[j]);\n if (ends) {\n const [s] = ends;\n const weight = edgeMap[j].weight;\n const sWeight = distMap.get(s);\n if (sWeight) {\n if (sWeight !== Infinity && sWeight + weight < sWeight) hasNegativeCycle = true;\n }\n }\n }\n\n return { hasNegativeCycle, distMap, preMap, paths, min, minPath };\n }\n\n /**\n * Dijkstra algorithm time: O(logVE) space: O(VO + EO)\n */\n\n /**\n * Dijkstra algorithm time: O(logVE) space: O(VO + EO)\n * Dijkstra's algorithm is used to find the shortest paths from a source node to all other nodes in a graph. Its basic idea is to repeatedly choose the node closest to the source node and update the distances of other nodes using this node as an intermediary. Dijkstra's algorithm requires that the edge weights in the graph are non-negative.\n */\n\n /**\n * BellmanFord time:O(VE) space:O(VO)\n * one to rest pairs\n * The Bellman-Ford algorithm is also used to find the shortest paths from a source node to all other nodes in a graph. Unlike Dijkstra's algorithm, it can handle edge weights that are negative. Its basic idea involves iterative relaxation of all edgeMap for several rounds to gradually approximate the shortest paths. Due to its ability to handle negative-weight edgeMap, the Bellman-Ford algorithm is more flexible in some scenarios.\n * The `bellmanFord` function implements the Bellman-Ford algorithm to find the shortest path from a source vertex to\n */\n\n /**\n * Time Complexity: O(V^3) - Cubic time (Floyd-Warshall algorithm).\n * Space Complexity: O(V^2) - Quadratic space (Floyd-Warshall algorithm).\n *\n * Not support graph with negative weight cycle\n * all pairs\n * The Floyd-Warshall algorithm is used to find the shortest paths between all pairs of nodes in a graph. It employs dynamic programming to compute the shortest paths from any node to any other node. The Floyd-Warshall algorithm's advantage lies in its ability to handle graphs with negative-weight edgeMap, and it can simultaneously compute shortest paths between any two nodes.\n * The function implements the Floyd-Warshall algorithm to find the shortest path between all pairs of vertexMap in a\n * graph.\n * @returns The function `floydWarshall()` returns an object with two properties: `costs` and `predecessor`. The `costs`\n * property is a 2D array of numbers representing the shortest path costs between vertexMap in a graph. The\n * `predecessor` property is a 2D array of vertexMap (or `undefined`) representing the predecessor vertexMap in the shortest\n * path between vertexMap in the\n */\n floydWarshall(): { costs: number[][]; predecessor: (VO | undefined)[][] } {\n const idAndVertices = [...this._vertexMap];\n const n = idAndVertices.length;\n\n const costs: number[][] = [];\n const predecessor: (VO | undefined)[][] = [];\n // successors\n\n for (let i = 0; i < n; i++) {\n costs[i] = [];\n predecessor[i] = [];\n for (let j = 0; j < n; j++) {\n predecessor[i][j] = undefined;\n }\n }\n\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n costs[i][j] = this.getEdge(idAndVertices[i][1], idAndVertices[j][1])?.weight || Infinity;\n }\n }\n\n for (let k = 0; k < n; k++) {\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n if (costs[i][j] > costs[i][k] + costs[k][j]) {\n costs[i][j] = costs[i][k] + costs[k][j];\n predecessor[i][j] = idAndVertices[k][1];\n }\n }\n }\n }\n return { costs, predecessor };\n }\n\n /**\n * O(V+E+C)\n * O(V+C)\n */\n getCycles(isInclude2Cycle: boolean = false): VertexKey[][] {\n const cycles: VertexKey[][] = [];\n const visited: Set<VO> = new Set();\n\n const dfs = (vertex: VO, currentPath: VertexKey[], visited: Set<VO>) => {\n if (visited.has(vertex)) {\n if (\n ((!isInclude2Cycle && currentPath.length > 2) || (isInclude2Cycle && currentPath.length >= 2)) &&\n currentPath[0] === vertex.key\n ) {\n cycles.push([...currentPath]);\n }\n return;\n }\n\n visited.add(vertex);\n currentPath.push(vertex.key);\n\n for (const neighbor of this.getNeighbors(vertex)) {\n if (neighbor) dfs(neighbor, currentPath, visited);\n }\n\n visited.delete(vertex);\n currentPath.pop();\n };\n\n for (const vertex of this.vertexMap.values()) {\n dfs(vertex, [], visited);\n }\n\n // Use a set to eliminate duplicate cycles\n const uniqueCycles = new Map<string, VertexKey[]>();\n\n for (const cycle of cycles) {\n const sorted = [...cycle].sort().toString();\n\n if (uniqueCycles.has(sorted)) continue;\n else {\n uniqueCycles.set(sorted, cycle);\n }\n }\n\n // Convert the unique cycles back to an array\n return [...uniqueCycles].map(cycleString => cycleString[1]);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function iterates over key-value pairs in a data structure and returns an array of\n * pairs that satisfy a given predicate.\n * @param predicate - The `predicate` parameter is a callback function that takes four arguments:\n * `value`, `key`, `index`, and `this`. It is used to determine whether an element should be included\n * in the filtered array. The callback function should return `true` if the element should be\n * included, and `\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the `predicate` function. It is used when you want to bind a\n * specific object as the context for the `predicate` function. If `thisArg` is provided, it will be\n * @returns The `filter` method returns an array of key-value pairs `[VertexKey, V | undefined][]`\n * that satisfy the given predicate function.\n */\n filter(predicate: EntryCallback<VertexKey, V | undefined, boolean>, thisArg?: any): [VertexKey, V | undefined][] {\n const filtered: [VertexKey, V | undefined][] = [];\n let index = 0;\n for (const [key, value] of this) {\n if (predicate.call(thisArg, key, value, index, this)) {\n filtered.push([key, value]);\n }\n index++;\n }\n return filtered;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function iterates over the elements of a collection and applies a callback function to\n * each element, returning an array of the results.\n * @param callback - The callback parameter is a function that will be called for each element in the\n * map. It takes four arguments:\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. If `thisArg` is provided, it will be\n * used as the `this` value when calling the callback function. If `thisArg` is not provided, `\n * @returns The `map` function is returning an array of type `T[]`.\n */\n map<T>(callback: EntryCallback<VertexKey, V | undefined, T>, thisArg?: any): T[] {\n const mapped: T[] = [];\n let index = 0;\n for (const [key, value] of this) {\n mapped.push(callback.call(thisArg, key, value, index, this));\n index++;\n }\n return mapped;\n }\n\n protected *_getIterator(): IterableIterator<[VertexKey, V | undefined]> {\n for (const vertex of this._vertexMap.values()) {\n yield [vertex.key, vertex.value];\n }\n }\n\n protected abstract _addEdge(edge: EO): boolean;\n\n protected _addVertex(newVertex: VO): boolean {\n if (this.hasVertex(newVertex)) {\n return false;\n // throw (new Error('Duplicated vertex key is not allowed'));\n }\n this._vertexMap.set(newVertex.key, newVertex);\n return true;\n }\n\n protected _getVertex(vertexOrKey: VertexKey | VO): VO | undefined {\n const vertexKey = this._getVertexKey(vertexOrKey);\n return this._vertexMap.get(vertexKey) || undefined;\n }\n\n protected _getVertexKey(vertexOrKey: VO | VertexKey): VertexKey {\n return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { TopologicalStatus, VertexKey } from '../../types';\nimport { AbstractEdge, AbstractGraph, AbstractVertex } from './abstract-graph';\nimport { IGraph } from '../../interfaces';\nimport { arrayRemove } from '../../utils';\n\nexport class DirectedVertex<V = any> extends AbstractVertex<V> {\n /**\n * The constructor function initializes a vertex with an optional value.\n * @param {VertexKey} key - The `key` parameter is of type `VertexKey` and represents the identifier of the vertex. It is\n * used to uniquely identify the vertex within a graph or data structure.\n * @param {V} [value] - The \"value\" parameter is an optional parameter of type V. It is used to initialize the value of the\n * vertex. If no value is provided, the vertex will be initialized with a default value.\n */\n constructor(key: VertexKey, value?: V) {\n super(key, value);\n }\n}\n\nexport class DirectedEdge<E = any> extends AbstractEdge<E> {\n src: VertexKey;\n dest: VertexKey;\n\n /**\n * The constructor function initializes the source and destination vertexMap of an edge, along with an optional weight\n * and value.\n * @param {VertexKey} src - The `src` parameter is the source vertex ID. It represents the starting point of an edge in\n * a graph.\n * @param {VertexKey} dest - The `dest` parameter represents the destination vertex of an edge. It is of type\n * `VertexKey`, which is likely a unique identifier for a vertex in a graph.\n * @param {number} [weight] - The weight parameter is an optional number that represents the weight of the edge.\n * @param {E} [value] - The `value` parameter is an optional parameter of type `E`. It represents the value associated with\n * the edge.\n */\n constructor(src: VertexKey, dest: VertexKey, weight?: number, value?: E) {\n super(weight, value);\n this.src = src;\n this.dest = dest;\n }\n}\n\n/**\n *\n */\nexport class DirectedGraph<\n V = any,\n E = any,\n VO extends DirectedVertex<V> = DirectedVertex<V>,\n EO extends DirectedEdge<E> = DirectedEdge<E>\n >\n extends AbstractGraph<V, E, VO, EO>\n implements IGraph<V, E, VO, EO>\n{\n /**\n * The constructor function initializes an instance of a class.\n */\n constructor() {\n super();\n }\n\n protected _outEdgeMap: Map<VO, EO[]> = new Map<VO, EO[]>();\n\n get outEdgeMap(): Map<VO, EO[]> {\n return this._outEdgeMap;\n }\n\n set outEdgeMap(v: Map<VO, EO[]>) {\n this._outEdgeMap = v;\n }\n\n protected _inEdgeMap: Map<VO, EO[]> = new Map<VO, EO[]>();\n\n get inEdgeMap(): Map<VO, EO[]> {\n return this._inEdgeMap;\n }\n\n set inEdgeMap(v: Map<VO, EO[]>) {\n this._inEdgeMap = v;\n }\n\n /**\n * The function creates a new vertex with an optional value and returns it.\n * @param {VertexKey} key - The `key` parameter is the unique identifier for the vertex. It is of type `VertexKey`, which\n * could be a number or a string depending on how you want to identify your vertexMap.\n * @param [value] - The 'value' parameter is an optional value that can be assigned to the vertex. If a value is provided,\n * it will be assigned to the 'value' property of the vertex. If no value is provided, the 'value' property will be\n * assigned the same value as the 'key' parameter\n * @returns a new instance of a DirectedVertex object, casted as type VO.\n */\n createVertex(key: VertexKey, value?: V): VO {\n return new DirectedVertex(key, value) as VO;\n }\n\n /**\n * The function creates a directed edge between two vertexMap with an optional weight and value.\n * @param {VertexKey} src - The source vertex ID of the edge. It represents the starting point of the edge.\n * @param {VertexKey} dest - The `dest` parameter is the identifier of the destination vertex for the edge.\n * @param {number} [weight] - The weight parameter is an optional number that represents the weight of the edge. If no\n * weight is provided, it defaults to 1.\n * @param [value] - The 'value' parameter is an optional value that can be assigned to the edge. It can be of any type and\n * is used to store additional information or data associated with the edge.\n * @returns a new instance of a DirectedEdge object, casted as type EO.\n */\n createEdge(src: VertexKey, dest: VertexKey, weight?: number, value?: E): EO {\n return new DirectedEdge(src, dest, weight ?? 1, value) as EO;\n }\n\n /**\n * Time Complexity: O(|V|) where |V| is the number of vertexMap\n * Space Complexity: O(1)\n *\n * The `getEdge` function retrieves an edge between two vertexMap based on their source and destination IDs.\n * @param {VO | VertexKey | undefined} srcOrKey - The source vertex or its ID. It can be either a vertex object or a vertex ID.\n * @param {VO | VertexKey | undefined} destOrKey - The `destOrKey` parameter in the `getEdge` function represents the\n * destination vertex of the edge. It can be either a vertex object (`VO`), a vertex ID (`VertexKey`), or `undefined` if the\n * destination is not specified.\n * @returns the first edge found between the source and destination vertexMap, or undefined if no such edge is found.\n */\n getEdge(srcOrKey: VO | VertexKey | undefined, destOrKey: VO | VertexKey | undefined): EO | undefined {\n let edgeMap: EO[] = [];\n\n if (srcOrKey !== undefined && destOrKey !== undefined) {\n const src: VO | undefined = this._getVertex(srcOrKey);\n const dest: VO | undefined = this._getVertex(destOrKey);\n\n if (src && dest) {\n const srcOutEdges = this._outEdgeMap.get(src);\n if (srcOutEdges) {\n edgeMap = srcOutEdges.filter(edge => edge.dest === dest.key);\n }\n }\n }\n\n return edgeMap[0] || undefined;\n }\n\n /**\n * Time Complexity: O(|E|) where |E| is the number of edgeMap\n * Space Complexity: O(1)\n *\n * The function removes an edge between two vertexMap in a graph and returns the removed edge.\n * @param {VO | VertexKey} srcOrKey - The source vertex or its ID.\n * @param {VO | VertexKey} destOrKey - The `destOrKey` parameter represents the destination vertex or its ID.\n * @returns the removed edge (EO) if it exists, or undefined if either the source or destination vertex does not exist.\n */\n deleteEdgeSrcToDest(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | undefined {\n const src: VO | undefined = this._getVertex(srcOrKey);\n const dest: VO | undefined = this._getVertex(destOrKey);\n let removed: EO | undefined = undefined;\n if (!src || !dest) {\n return undefined;\n }\n\n const srcOutEdges = this._outEdgeMap.get(src);\n if (srcOutEdges) {\n arrayRemove<EO>(srcOutEdges, (edge: EO) => edge.dest === dest.key);\n }\n\n const destInEdges = this._inEdgeMap.get(dest);\n if (destInEdges) {\n removed = arrayRemove<EO>(destInEdges, (edge: EO) => edge.src === src.key)[0] || undefined;\n }\n return removed;\n }\n\n /**\n * Time Complexity: O(E) where E is the number of edgeMap\n * Space Complexity: O(1)\n *\n * The `deleteEdge` function removes an edge from a graph and returns the removed edge.\n * @param {EO | VertexKey} edgeOrSrcVertexKey - The `edge` parameter can be either an `EO` object (edge object) or\n * a `VertexKey` (key of a vertex).\n * @param {VertexKey} [destVertexKey] - The `destVertexKey` parameter is an optional parameter that\n * represents the key of the destination vertex of the edge. It is used to specify the destination\n * vertex when the `edge` parameter is a vertex key. If `destVertexKey` is not provided, the function\n * assumes that the `edge`\n * @returns the removed edge (EO) or undefined if no edge was removed.\n */\n deleteEdge(edgeOrSrcVertexKey: EO | VertexKey, destVertexKey?: VertexKey): EO | undefined {\n let removed: EO | undefined = undefined;\n let src: VO | undefined, dest: VO | undefined;\n if (this.isVertexKey(edgeOrSrcVertexKey)) {\n if (this.isVertexKey(destVertexKey)) {\n src = this._getVertex(edgeOrSrcVertexKey);\n dest = this._getVertex(destVertexKey);\n } else {\n return;\n }\n } else {\n src = this._getVertex(edgeOrSrcVertexKey.src);\n dest = this._getVertex(edgeOrSrcVertexKey.dest);\n }\n\n if (src && dest) {\n const srcOutEdges = this._outEdgeMap.get(src);\n if (srcOutEdges && srcOutEdges.length > 0) {\n arrayRemove(srcOutEdges, (edge: EO) => edge.src === src!.key && edge.dest === dest?.key);\n }\n\n const destInEdges = this._inEdgeMap.get(dest);\n if (destInEdges && destInEdges.length > 0) {\n removed = arrayRemove(destInEdges, (edge: EO) => edge.src === src!.key && edge.dest === dest!.key)[0];\n }\n }\n\n return removed;\n }\n\n /**\n * Time Complexity: O(1) - Constant time for Map operations.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n *\n * The `deleteVertex` function removes a vertex from a graph by its ID or by the vertex object itself.\n * @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can be either a vertex object (`VO`) or a vertex ID\n * (`VertexKey`).\n * @returns The method is returning a boolean value.\n */\n deleteVertex(vertexOrKey: VO | VertexKey): boolean {\n let vertexKey: VertexKey;\n let vertex: VO | undefined;\n if (this.isVertexKey(vertexOrKey)) {\n vertex = this.getVertex(vertexOrKey);\n vertexKey = vertexOrKey;\n } else {\n vertex = vertexOrKey;\n vertexKey = this._getVertexKey(vertexOrKey);\n }\n\n if (vertex) {\n const neighbors = this.getNeighbors(vertex);\n for (const neighbor of neighbors) {\n // this._inEdgeMap.delete(neighbor);\n this.deleteEdgeSrcToDest(vertex, neighbor);\n }\n this._outEdgeMap.delete(vertex);\n this._inEdgeMap.delete(vertex);\n }\n\n return this._vertexMap.delete(vertexKey);\n }\n\n /**\n * Time Complexity: O(|E|) where |E| is the number of edgeMap\n * Space Complexity: O(1)\n *\n * The function removes edgeMap between two vertexMap and returns the removed edgeMap.\n * @param {VertexKey | VO} v1 - The parameter `v1` can be either a `VertexKey` or a `VO`. A `VertexKey` represents the\n * unique identifier of a vertex in a graph, while `VO` represents the actual vertex object.\n * @param {VertexKey | VO} v2 - The parameter `v2` represents either a `VertexKey` or a `VO` object. It is used to specify\n * the second vertex in the edge that needs to be removed.\n * @returns an array of removed edgeMap (EO[]).\n */\n deleteEdgesBetween(v1: VertexKey | VO, v2: VertexKey | VO): EO[] {\n const removed: EO[] = [];\n\n if (v1 && v2) {\n const v1ToV2 = this.deleteEdgeSrcToDest(v1, v2);\n const v2ToV1 = this.deleteEdgeSrcToDest(v2, v1);\n\n if (v1ToV2) removed.push(v1ToV2);\n if (v2ToV1) removed.push(v2ToV1);\n }\n\n return removed;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `incomingEdgesOf` returns an array of incoming edgeMap for a given vertex or vertex ID.\n * @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can be either a vertex object (`VO`) or a vertex ID\n * (`VertexKey`).\n * @returns The method `incomingEdgesOf` returns an array of edgeMap (`EO[]`).\n */\n incomingEdgesOf(vertexOrKey: VO | VertexKey): EO[] {\n const target = this._getVertex(vertexOrKey);\n if (target) {\n return this.inEdgeMap.get(target) || [];\n }\n return [];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `outgoingEdgesOf` returns an array of outgoing edgeMap from a given vertex or vertex ID.\n * @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can accept either a vertex object (`VO`) or a vertex ID\n * (`VertexKey`).\n * @returns The method `outgoingEdgesOf` returns an array of edgeMap (`EO[]`).\n */\n outgoingEdgesOf(vertexOrKey: VO | VertexKey): EO[] {\n const target = this._getVertex(vertexOrKey);\n if (target) {\n return this._outEdgeMap.get(target) || [];\n }\n return [];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"degreeOf\" returns the total degree of a vertex, which is the sum of its out-degree and in-degree.\n * @param {VertexKey | VO} vertexOrKey - The parameter `vertexOrKey` can be either a `VertexKey` or a `VO`.\n * @returns The sum of the out-degree and in-degree of the specified vertex or vertex ID.\n */\n degreeOf(vertexOrKey: VertexKey | VO): number {\n return this.outDegreeOf(vertexOrKey) + this.inDegreeOf(vertexOrKey);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"inDegreeOf\" returns the number of incoming edgeMap for a given vertex.\n * @param {VertexKey | VO} vertexOrKey - The parameter `vertexOrKey` can be either a `VertexKey` or a `VO`.\n * @returns The number of incoming edgeMap of the specified vertex or vertex ID.\n */\n inDegreeOf(vertexOrKey: VertexKey | VO): number {\n return this.incomingEdgesOf(vertexOrKey).length;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `outDegreeOf` returns the number of outgoing edgeMap from a given vertex.\n * @param {VertexKey | VO} vertexOrKey - The parameter `vertexOrKey` can be either a `VertexKey` or a `VO`.\n * @returns The number of outgoing edgeMap from the specified vertex or vertex ID.\n */\n outDegreeOf(vertexOrKey: VertexKey | VO): number {\n return this.outgoingEdgesOf(vertexOrKey).length;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"edgesOf\" returns an array of both outgoing and incoming edgeMap of a given vertex or vertex ID.\n * @param {VertexKey | VO} vertexOrKey - The parameter `vertexOrKey` can be either a `VertexKey` or a `VO`.\n * @returns The function `edgesOf` returns an array of edgeMap.\n */\n edgesOf(vertexOrKey: VertexKey | VO): EO[] {\n return [...this.outgoingEdgesOf(vertexOrKey), ...this.incomingEdgesOf(vertexOrKey)];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"getEdgeSrc\" returns the source vertex of an edge, or undefined if the edge does not exist.\n * @param {EO} e - The parameter \"e\" is of type EO, which represents an edge in a graph.\n * @returns either a vertex object (VO) or undefined.\n */\n getEdgeSrc(e: EO): VO | undefined {\n return this._getVertex(e.src);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"getEdgeDest\" returns the destination vertex of an edge.\n * @param {EO} e - The parameter \"e\" is of type \"EO\", which represents an edge in a graph.\n * @returns either a vertex object of type VO or undefined.\n */\n getEdgeDest(e: EO): VO | undefined {\n return this._getVertex(e.dest);\n }\n\n /**\n * Time Complexity: O(|E|) where |E| is the number of edgeMap\n * Space Complexity: O(1)\n *\n * The function `getDestinations` returns an array of destination vertexMap connected to a given vertex.\n * @param {VO | VertexKey | undefined} vertex - The `vertex` parameter represents the starting vertex from which we want to\n * find the destinations. It can be either a `VO` object, a `VertexKey` value, or `undefined`.\n * @returns an array of vertexMap (VO[]).\n */\n getDestinations(vertex: VO | VertexKey | undefined): VO[] {\n if (vertex === undefined) {\n return [];\n }\n const destinations: VO[] = [];\n const outgoingEdges = this.outgoingEdgesOf(vertex);\n for (const outEdge of outgoingEdges) {\n const child = this.getEdgeDest(outEdge);\n if (child) {\n destinations.push(child);\n }\n }\n return destinations;\n }\n\n /**\n * Time Complexity: O(|V| + |E|) where |V| is the number of vertexMap and |E| is the number of edgeMap\n * Space Complexity: O(|V|)\n *\n * The `topologicalSort` function performs a topological sort on a graph and returns an array of vertexMap or vertex IDs\n * in the sorted order, or undefined if the graph contains a cycle.\n * @param {'vertex' | 'key'} [propertyName] - The `propertyName` parameter is an optional parameter that specifies the\n * property to use for sorting the vertexMap. It can have two possible values: 'vertex' or 'key'. If 'vertex' is\n * specified, the vertexMap themselves will be used for sorting. If 'key' is specified, the ids of\n * @returns an array of vertexMap or vertex IDs in topological order. If there is a cycle in the graph, it returns undefined.\n */\n topologicalSort(propertyName?: 'vertex' | 'key'): Array<VO | VertexKey> | undefined {\n propertyName = propertyName ?? 'key';\n // When judging whether there is a cycle in the undirected graph, all nodes with degree of **<= 1** are enqueued\n // When judging whether there is a cycle in the directed graph, all nodes with **in degree = 0** are enqueued\n const statusMap: Map<VO | VertexKey, TopologicalStatus> = new Map<VO | VertexKey, TopologicalStatus>();\n for (const entry of this.vertexMap) {\n statusMap.set(entry[1], 0);\n }\n\n let sorted: (VO | VertexKey)[] = [];\n let hasCycle = false;\n const dfs = (cur: VO | VertexKey) => {\n statusMap.set(cur, 1);\n const children = this.getDestinations(cur);\n for (const child of children) {\n const childStatus = statusMap.get(child);\n if (childStatus === 0) {\n dfs(child);\n } else if (childStatus === 1) {\n hasCycle = true;\n }\n }\n statusMap.set(cur, 2);\n sorted.push(cur);\n };\n\n for (const entry of this.vertexMap) {\n if (statusMap.get(entry[1]) === 0) {\n dfs(entry[1]);\n }\n }\n\n if (hasCycle) return undefined;\n\n if (propertyName === 'key') sorted = sorted.map(vertex => (vertex instanceof DirectedVertex ? vertex.key : vertex));\n return sorted.reverse();\n }\n\n /**\n * Time Complexity: O(|E|) where |E| is the number of edgeMap\n * Space Complexity: O(|E|)\n *\n * The `edgeSet` function returns an array of all the edgeMap in the graph.\n * @returns The `edgeSet()` method returns an array of edgeMap (`EO[]`).\n */\n edgeSet(): EO[] {\n let edgeMap: EO[] = [];\n this._outEdgeMap.forEach(outEdges => {\n edgeMap = [...edgeMap, ...outEdges];\n });\n return edgeMap;\n }\n\n /**\n * Time Complexity: O(|E|) where |E| is the number of edgeMap\n * Space Complexity: O(1)\n *\n * The function `getNeighbors` returns an array of neighboring vertexMap of a given vertex or vertex ID in a graph.\n * @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can be either a vertex object (`VO`) or a vertex ID\n * (`VertexKey`).\n * @returns an array of vertexMap (VO[]).\n */\n getNeighbors(vertexOrKey: VO | VertexKey): VO[] {\n const neighbors: VO[] = [];\n const vertex = this._getVertex(vertexOrKey);\n if (vertex) {\n const outEdges = this.outgoingEdgesOf(vertex);\n for (const outEdge of outEdges) {\n const neighbor = this._getVertex(outEdge.dest);\n // TODO after no-non-undefined-assertion not ensure the logic\n if (neighbor) {\n neighbors.push(neighbor);\n }\n }\n }\n return neighbors;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"getEndsOfEdge\" returns the source and destination vertexMap of an edge if it exists in the graph,\n * otherwise it returns undefined.\n * @param {EO} edge - The parameter `edge` is of type `EO`, which represents an edge in a graph.\n * @returns The function `getEndsOfEdge` returns an array containing two vertexMap `[VO, VO]` if the edge exists in the\n * graph. If the edge does not exist, it returns `undefined`.\n */\n getEndsOfEdge(edge: EO): [VO, VO] | undefined {\n if (!this.hasEdge(edge.src, edge.dest)) {\n return undefined;\n }\n const v1 = this._getVertex(edge.src);\n const v2 = this._getVertex(edge.dest);\n if (v1 && v2) {\n return [v1, v2];\n } else {\n return undefined;\n }\n }\n\n /**\n * The isEmpty function checks if the graph is empty.\n *\n * @return A boolean value\n */\n isEmpty(): boolean {\n return this.vertexMap.size === 0 && this.inEdgeMap.size === 0 && this.outEdgeMap.size === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear function resets the vertex map, in-edge map, and out-edge map.\n */\n clear() {\n this._vertexMap = new Map<VertexKey, VO>();\n this._inEdgeMap = new Map<VO, EO[]>();\n this._outEdgeMap = new Map<VO, EO[]>();\n }\n\n /**\n * The clone function creates a new DirectedGraph object with the same vertices and edges as the original.\n *\n * @return A new instance of the directedgraph class\n */\n clone(): DirectedGraph<V, E, VO, EO> {\n const cloned = new DirectedGraph<V, E, VO, EO>();\n cloned.vertexMap = new Map<VertexKey, VO>(this.vertexMap);\n cloned.inEdgeMap = new Map<VO, EO[]>(this.inEdgeMap);\n cloned.outEdgeMap = new Map<VO, EO[]>(this.outEdgeMap);\n return cloned;\n }\n\n /**\n * Time Complexity: O(V + E)\n * Space Complexity: O(V)\n * Tarjan is an algorithm based on dfs,which is used to solve the connectivity problem of graphs.\n * Tarjan can find the SSC(strongly connected components), articulation points, and bridges of directed graphs.\n *\n * The function `tarjan` implements the Tarjan's algorithm to find strongly connected components in a\n * graph.\n * @returns The function `tarjan()` returns an object with three properties: `dfnMap`, `lowMap`, and\n * `SCCs`.\n */\n tarjan(): { dfnMap: Map<VO, number>; lowMap: Map<VO, number>; SCCs: Map<number, VO[]> } {\n const dfnMap = new Map<VO, number>();\n const lowMap = new Map<VO, number>();\n const SCCs = new Map<number, VO[]>();\n\n let time = 0;\n\n const stack: VO[] = [];\n const inStack: Set<VO> = new Set();\n\n const dfs = (vertex: VO) => {\n dfnMap.set(vertex, time);\n lowMap.set(vertex, time);\n time++;\n\n stack.push(vertex);\n inStack.add(vertex);\n\n const neighbors = this.getNeighbors(vertex);\n for (const neighbor of neighbors) {\n if (!dfnMap.has(neighbor)) {\n dfs(neighbor);\n lowMap.set(vertex, Math.min(lowMap.get(vertex)!, lowMap.get(neighbor)!));\n } else if (inStack.has(neighbor)) {\n lowMap.set(vertex, Math.min(lowMap.get(vertex)!, dfnMap.get(neighbor)!));\n }\n }\n\n if (dfnMap.get(vertex) === lowMap.get(vertex)) {\n const SCC: VO[] = [];\n let poppedVertex: VO | undefined;\n\n do {\n poppedVertex = stack.pop();\n inStack.delete(poppedVertex!);\n SCC.push(poppedVertex!);\n } while (poppedVertex !== vertex);\n\n SCCs.set(SCCs.size, SCC);\n }\n };\n\n for (const vertex of this.vertexMap.values()) {\n if (!dfnMap.has(vertex)) {\n dfs(vertex);\n }\n }\n\n return { dfnMap, lowMap, SCCs };\n }\n\n /**\n * Time Complexity: O(V + E) - Depends on the implementation (Tarjan's algorithm).\n * Space Complexity: O(V) - Depends on the implementation (Tarjan's algorithm).\n *\n * The function returns a map that associates each vertex object with its corresponding depth-first\n * number.\n * @returns A Map object with keys of type VO and values of type number.\n */\n getDFNMap(): Map<VO, number> {\n return this.tarjan().dfnMap;\n }\n\n /**\n * The function returns a Map object that contains the low values of each vertex in a Tarjan\n * algorithm.\n * @returns The method `getLowMap()` is returning a `Map` object with keys of type `VO` and values of\n * type `number`.\n */\n getLowMap(): Map<VO, number> {\n return this.tarjan().lowMap;\n }\n\n /**\n * The function \"getSCCs\" returns a map of strongly connected components (SCCs) using the Tarjan\n * algorithm.\n * @returns a map where the keys are numbers and the values are arrays of VO objects.\n */\n getSCCs(): Map<number, VO[]> {\n return this.tarjan().SCCs;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_addEdge` adds an edge to a graph if the source and destination vertexMap exist.\n * @param {EO} edge - The parameter `edge` is of type `EO`, which represents an edge in a graph. It is the edge that\n * needs to be added to the graph.\n * @returns a boolean value. It returns true if the edge was successfully added to the graph, and false if either the\n * source or destination vertex does not exist in the graph.\n */\n protected _addEdge(edge: EO): boolean {\n if (!(this.hasVertex(edge.src) && this.hasVertex(edge.dest))) {\n return false;\n }\n\n const srcVertex = this._getVertex(edge.src);\n const destVertex = this._getVertex(edge.dest);\n\n // TODO after no-non-undefined-assertion not ensure the logic\n if (srcVertex && destVertex) {\n const srcOutEdges = this._outEdgeMap.get(srcVertex);\n if (srcOutEdges) {\n srcOutEdges.push(edge);\n } else {\n this._outEdgeMap.set(srcVertex, [edge]);\n }\n\n const destInEdges = this._inEdgeMap.get(destVertex);\n if (destInEdges) {\n destInEdges.push(edge);\n } else {\n this._inEdgeMap.set(destVertex, [edge]);\n }\n return true;\n } else {\n return false;\n }\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { VertexKey } from '../../types';\nimport { IGraph } from '../../interfaces';\nimport { AbstractEdge, AbstractGraph, AbstractVertex } from './abstract-graph';\nimport { arrayRemove } from '../../utils';\n\nexport class UndirectedVertex<V = any> extends AbstractVertex<V> {\n /**\n * The constructor function initializes a vertex with an optional value.\n * @param {VertexKey} key - The `key` parameter is of type `VertexKey` and represents the identifier of the vertex. It is\n * used to uniquely identify the vertex within a graph or network.\n * @param {V} [value] - The \"value\" parameter is an optional parameter of type V. It is used to initialize the value of the\n * vertex. If no value is provided, the vertex will be initialized with a default value.\n */\n constructor(key: VertexKey, value?: V) {\n super(key, value);\n }\n}\n\nexport class UndirectedEdge<E = number> extends AbstractEdge<E> {\n endpoints: [VertexKey, VertexKey];\n\n /**\n * The constructor function creates an instance of a class with two vertex IDs, an optional weight, and an optional\n * value.\n * @param {VertexKey} v1 - The first vertex ID of the edge.\n * @param {VertexKey} v2 - The parameter `v2` is a `VertexKey`, which represents the identifier of the second vertex in a\n * graph edge.\n * @param {number} [weight] - The weight parameter is an optional number that represents the weight of the edge.\n * @param {E} [value] - The \"value\" parameter is an optional parameter of type E. It is used to store a value associated\n * with the edge.\n */\n constructor(v1: VertexKey, v2: VertexKey, weight?: number, value?: E) {\n super(weight, value);\n this.endpoints = [v1, v2];\n }\n}\n\n/**\n *\n */\nexport class UndirectedGraph<\n V = any,\n E = any,\n VO extends UndirectedVertex<V> = UndirectedVertex<V>,\n EO extends UndirectedEdge<E> = UndirectedEdge<E>\n >\n extends AbstractGraph<V, E, VO, EO>\n implements IGraph<V, E, VO, EO>\n{\n /**\n * The constructor initializes a new Map object to store edgeMap.\n */\n constructor() {\n super();\n this._edgeMap = new Map<VO, EO[]>();\n }\n\n protected _edgeMap: Map<VO, EO[]>;\n\n get edgeMap(): Map<VO, EO[]> {\n return this._edgeMap;\n }\n\n set edgeMap(v: Map<VO, EO[]>) {\n this._edgeMap = v;\n }\n\n /**\n * The function creates a new vertex with an optional value and returns it.\n * @param {VertexKey} key - The `key` parameter is the unique identifier for the vertex. It is used to distinguish one\n * vertex from another in the graph.\n * @param [value] - The `value` parameter is an optional value that can be assigned to the vertex. If a value is provided,\n * it will be used as the value of the vertex. If no value is provided, the `key` parameter will be used as the value of\n * the vertex.\n * @returns The method is returning a new instance of the `UndirectedVertex` class, casted as type `VO`.\n */\n override createVertex(key: VertexKey, value?: VO['value']): VO {\n return new UndirectedVertex(key, value ?? key) as VO;\n }\n\n /**\n * The function creates an undirected edge between two vertexMap with an optional weight and value.\n * @param {VertexKey} v1 - The parameter `v1` represents the first vertex of the edge.\n * @param {VertexKey} v2 - The parameter `v2` represents the second vertex of the edge.\n * @param {number} [weight] - The `weight` parameter is an optional number that represents the weight of the edge. If\n * no weight is provided, it defaults to 1.\n * @param [value] - The `value` parameter is an optional value that can be assigned to the edge. It can be of any type and\n * is used to store additional information or data associated with the edge.\n * @returns a new instance of the `UndirectedEdge` class, which is casted as type `EO`.\n */\n override createEdge(v1: VertexKey, v2: VertexKey, weight?: number, value?: EO['value']): EO {\n return new UndirectedEdge(v1, v2, weight ?? 1, value) as EO;\n }\n\n /**\n * Time Complexity: O(|E|), where |E| is the number of edgeMap incident to the given vertex.\n * Space Complexity: O(1)\n *\n * The function `getEdge` returns the first edge that connects two endpoints, or undefined if no such edge exists.\n * @param {VO | VertexKey | undefined} v1 - The parameter `v1` represents a vertex or vertex ID. It can be of type `VO` (vertex\n * object), `undefined`, or `VertexKey` (a string or number representing the ID of a vertex).\n * @param {VO | VertexKey | undefined} v2 - The parameter `v2` represents a vertex or vertex ID. It can be of type `VO` (vertex\n * object), `undefined`, or `VertexKey` (vertex ID).\n * @returns an edge (EO) or undefined.\n */\n getEdge(v1: VO | VertexKey | undefined, v2: VO | VertexKey | undefined): EO | undefined {\n let edgeMap: EO[] | undefined = [];\n\n if (v1 !== undefined && v2 !== undefined) {\n const vertex1: VO | undefined = this._getVertex(v1);\n const vertex2: VO | undefined = this._getVertex(v2);\n\n if (vertex1 && vertex2) {\n edgeMap = this._edgeMap.get(vertex1)?.filter(e => e.endpoints.includes(vertex2.key));\n }\n }\n\n return edgeMap ? edgeMap[0] || undefined : undefined;\n }\n\n /**\n * Time Complexity: O(|E|), where |E| is the number of edgeMap incident to the given vertex.\n * Space Complexity: O(1)\n *\n * The function removes an edge between two vertexMap in a graph and returns the removed edge.\n * @param {VO | VertexKey} v1 - The parameter `v1` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).\n * @param {VO | VertexKey} v2 - VO | VertexKey - This parameter can be either a vertex object (VO) or a vertex ID\n * (VertexKey). It represents the second vertex of the edge that needs to be removed.\n * @returns the removed edge (EO) if it exists, or undefined if either of the endpoints (VO) does not exist.\n */\n deleteEdgeBetween(v1: VO | VertexKey, v2: VO | VertexKey): EO | undefined {\n const vertex1: VO | undefined = this._getVertex(v1);\n const vertex2: VO | undefined = this._getVertex(v2);\n\n if (!vertex1 || !vertex2) {\n return undefined;\n }\n\n const v1Edges = this._edgeMap.get(vertex1);\n let removed: EO | undefined = undefined;\n if (v1Edges) {\n removed = arrayRemove<EO>(v1Edges, (e: EO) => e.endpoints.includes(vertex2.key))[0] || undefined;\n }\n const v2Edges = this._edgeMap.get(vertex2);\n if (v2Edges) {\n arrayRemove<EO>(v2Edges, (e: EO) => e.endpoints.includes(vertex1.key));\n }\n return removed;\n }\n\n /**\n * Time Complexity: O(E), where E is the number of edgeMap incident to the given vertex.\n * Space Complexity: O(1)\n *\n * The function `deleteEdge` deletes an edge between two endpoints in a graph.\n * @param {EO | VertexKey} edgeOrOneSideVertexKey - The parameter `edgeOrOneSideVertexKey` can be\n * either an edge object or a vertex key.\n * @param {VertexKey} [otherSideVertexKey] - The parameter `otherSideVertexKey` is an optional\n * parameter that represents the key of the vertex on the other side of the edge. It is used when the\n * `edgeOrOneSideVertexKey` parameter is a vertex key, and it specifies the key of the vertex on the\n * other side of the\n * @returns The `deleteEdge` function returns either the deleted edge object (EO) or `undefined`.\n */\n deleteEdge(edgeOrOneSideVertexKey: EO | VertexKey, otherSideVertexKey?: VertexKey): EO | undefined {\n let oneSide: VO | undefined, otherSide: VO | undefined;\n if (this.isVertexKey(edgeOrOneSideVertexKey)) {\n if (this.isVertexKey(otherSideVertexKey)) {\n oneSide = this._getVertex(edgeOrOneSideVertexKey);\n otherSide = this._getVertex(otherSideVertexKey);\n } else {\n return;\n }\n } else {\n oneSide = this._getVertex(edgeOrOneSideVertexKey.endpoints[0]);\n otherSide = this._getVertex(edgeOrOneSideVertexKey.endpoints[1]);\n }\n\n if (oneSide && otherSide) {\n return this.deleteEdgeBetween(oneSide, otherSide);\n } else {\n return;\n }\n }\n\n /**\n * Time Complexity: O(1) - Constant time for Map operations.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n *\n * The `deleteVertex` function removes a vertex from a graph by its ID or by the vertex object itself.\n * @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can be either a vertex object (`VO`) or a vertex ID\n * (`VertexKey`).\n * @returns The method is returning a boolean value.\n */\n deleteVertex(vertexOrKey: VO | VertexKey): boolean {\n let vertexKey: VertexKey;\n let vertex: VO | undefined;\n if (this.isVertexKey(vertexOrKey)) {\n vertex = this.getVertex(vertexOrKey);\n vertexKey = vertexOrKey;\n } else {\n vertex = vertexOrKey;\n vertexKey = this._getVertexKey(vertexOrKey);\n }\n\n const neighbors = this.getNeighbors(vertexOrKey);\n\n if (vertex) {\n neighbors.forEach(neighbor => {\n const neighborEdges = this._edgeMap.get(neighbor);\n if (neighborEdges) {\n const restEdges = neighborEdges.filter(edge => {\n return !edge.endpoints.includes(vertexKey);\n });\n this._edgeMap.set(neighbor, restEdges);\n }\n });\n this._edgeMap.delete(vertex);\n }\n\n return this._vertexMap.delete(vertexKey);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `degreeOf` returns the degree of a vertex in a graph, which is the number of edgeMap connected to that\n * vertex.\n * @param {VertexKey | VO} vertexOrKey - The parameter `vertexOrKey` can be either a `VertexKey` or a `VO`.\n * @returns The function `degreeOf` returns the degree of a vertex in a graph. The degree of a vertex is the number of\n * edgeMap connected to that vertex.\n */\n degreeOf(vertexOrKey: VertexKey | VO): number {\n const vertex = this._getVertex(vertexOrKey);\n if (vertex) {\n return this._edgeMap.get(vertex)?.length || 0;\n } else {\n return 0;\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function returns the edgeMap of a given vertex or vertex ID.\n * @param {VertexKey | VO} vertexOrKey - The parameter `vertexOrKey` can be either a `VertexKey` or a `VO`. A `VertexKey` is a\n * unique identifier for a vertex in a graph, while `VO` represents the type of the vertex.\n * @returns an array of edgeMap.\n */\n edgesOf(vertexOrKey: VertexKey | VO): EO[] {\n const vertex = this._getVertex(vertexOrKey);\n if (vertex) {\n return this._edgeMap.get(vertex) || [];\n } else {\n return [];\n }\n }\n\n /**\n * Time Complexity: O(|V| + |E|), where |V| is the number of vertexMap and |E| is the number of edgeMap.\n * Space Complexity: O(|E|)\n *\n * The function \"edgeSet\" returns an array of unique edgeMap from a set of edgeMap.\n * @returns The method `edgeSet()` returns an array of type `EO[]`.\n */\n edgeSet(): EO[] {\n const edgeSet: Set<EO> = new Set();\n this._edgeMap.forEach(edgeMap => {\n edgeMap.forEach(edge => {\n edgeSet.add(edge);\n });\n });\n return [...edgeSet];\n }\n\n /**\n * Time Complexity: O(|V| + |E|), where |V| is the number of vertexMap and |E| is the number of edgeMap.\n * Space Complexity: O(|E|)\n *\n * The function \"getNeighbors\" returns an array of neighboring endpoints for a given vertex or vertex ID.\n * @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can be either a vertex object (`VO`) or a vertex ID\n * (`VertexKey`).\n * @returns an array of vertexMap (VO[]).\n */\n getNeighbors(vertexOrKey: VO | VertexKey): VO[] {\n const neighbors: VO[] = [];\n const vertex = this._getVertex(vertexOrKey);\n if (vertex) {\n const neighborEdges = this.edgesOf(vertex);\n for (const edge of neighborEdges) {\n const neighbor = this._getVertex(edge.endpoints.filter(e => e !== vertex.key)[0]);\n if (neighbor) {\n neighbors.push(neighbor);\n }\n }\n }\n return neighbors;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"getEndsOfEdge\" returns the endpoints at the ends of an edge if the edge exists in the graph, otherwise\n * it returns undefined.\n * @param {EO} edge - The parameter \"edge\" is of type EO, which represents an edge in a graph.\n * @returns The function `getEndsOfEdge` returns an array containing two endpoints `[VO, VO]` if the edge exists in the\n * graph. If the edge does not exist, it returns `undefined`.\n */\n getEndsOfEdge(edge: EO): [VO, VO] | undefined {\n if (!this.hasEdge(edge.endpoints[0], edge.endpoints[1])) {\n return undefined;\n }\n const v1 = this._getVertex(edge.endpoints[0]);\n const v2 = this._getVertex(edge.endpoints[1]);\n if (v1 && v2) {\n return [v1, v2];\n } else {\n return undefined;\n }\n }\n\n /**\n * The isEmpty function checks if the graph is empty.\n * @return True if the graph is empty and false otherwise\n */\n isEmpty(): boolean {\n return this.vertexMap.size === 0 && this.edgeMap.size === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear function resets the vertex and edge maps to empty maps.\n */\n clear() {\n this._vertexMap = new Map<VertexKey, VO>();\n this._edgeMap = new Map<VO, EO[]>();\n }\n\n /**\n * The clone function creates a new UndirectedGraph object and copies the\n * vertexMap and edgeMap from this graph to the new one. This is done by\n * assigning each of these properties to their respective counterparts in the\n * cloned graph. The clone function returns a reference to this newly created,\n * cloned UndirectedGraph object.\n *\n * @return A new instance of the undirectedgraph class\n */\n clone(): UndirectedGraph<V, E, VO, EO> {\n const cloned = new UndirectedGraph<V, E, VO, EO>();\n cloned.vertexMap = new Map<VertexKey, VO>(this.vertexMap);\n cloned.edgeMap = new Map<VO, EO[]>(this.edgeMap);\n return cloned;\n }\n\n /**\n * Time Complexity: O(V + E)\n * Space Complexity: O(V)\n * Tarjan is an algorithm based on dfs,which is used to solve the connectivity problem of graphs.\n * 1. Tarjan can find the articulation points and bridges(critical edgeMap) of undirected graphs in linear time\n *\n * The function `tarjan` implements the Tarjan's algorithm to find bridges and cut vertices in a\n * graph.\n * @returns The function `tarjan()` returns an object with the following properties:\n */\n tarjan(): { dfnMap: Map<VO, number>; lowMap: Map<VO, number>; bridges: EO[]; cutVertices: VO[] } {\n const dfnMap = new Map<VO, number>();\n const lowMap = new Map<VO, number>();\n const bridges: EO[] = [];\n const cutVertices: VO[] = [];\n\n let time = 0;\n\n const dfs = (vertex: VO, parent: VO | undefined) => {\n dfnMap.set(vertex, time);\n lowMap.set(vertex, time);\n time++;\n\n const neighbors = this.getNeighbors(vertex);\n let childCount = 0;\n\n for (const neighbor of neighbors) {\n if (!dfnMap.has(neighbor)) {\n childCount++;\n dfs(neighbor, vertex);\n lowMap.set(vertex, Math.min(lowMap.get(vertex)!, lowMap.get(neighbor)!));\n\n if (lowMap.get(neighbor)! > dfnMap.get(vertex)!) {\n // Found a bridge\n const edge = this.getEdge(vertex, neighbor);\n if (edge) {\n bridges.push(edge);\n }\n }\n\n if (parent !== undefined && lowMap.get(neighbor)! >= dfnMap.get(vertex)!) {\n // Found an articulation point\n cutVertices.push(vertex);\n }\n } else if (neighbor !== parent) {\n lowMap.set(vertex, Math.min(lowMap.get(vertex)!, dfnMap.get(neighbor)!));\n }\n }\n\n if (parent === undefined && childCount > 1) {\n // Special case for root in DFS tree\n cutVertices.push(vertex);\n }\n };\n\n for (const vertex of this.vertexMap.values()) {\n if (!dfnMap.has(vertex)) {\n dfs(vertex, undefined);\n }\n }\n\n return {\n dfnMap,\n lowMap,\n bridges,\n cutVertices\n };\n }\n\n /**\n * The function \"getBridges\" returns an array of bridges in a graph using the Tarjan's algorithm.\n * @returns The function `getBridges()` is returning the bridges found using the Tarjan's algorithm.\n */\n getBridges() {\n return this.tarjan().bridges;\n }\n\n /**\n * The function \"getCutVertices\" returns an array of cut vertices using the Tarjan's algorithm.\n * @returns the cut vertices found using the Tarjan's algorithm.\n */\n getCutVertices() {\n return this.tarjan().cutVertices;\n }\n\n /**\n * The function returns the dfnMap property of the result of the tarjan() function.\n * @returns the `dfnMap` property of the result of calling the `tarjan()` function.\n */\n getDFNMap() {\n return this.tarjan().dfnMap;\n }\n\n /**\n * The function returns the lowMap property of the result of the tarjan() function.\n * @returns the lowMap property of the result of calling the tarjan() function.\n */\n getLowMap() {\n return this.tarjan().lowMap;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function adds an edge to the graph by updating the adjacency list with the vertexMap of the edge.\n * @param {EO} edge - The parameter \"edge\" is of type EO, which represents an edge in a graph.\n * @returns a boolean value.\n */\n protected _addEdge(edge: EO): boolean {\n for (const end of edge.endpoints) {\n const endVertex = this._getVertex(end);\n if (endVertex === undefined) return false;\n if (endVertex) {\n const edgeMap = this._edgeMap.get(endVertex);\n if (edgeMap) {\n edgeMap.push(edge);\n } else {\n this._edgeMap.set(endVertex, [edge]);\n }\n }\n }\n return true;\n }\n}\n","import type { MapGraphCoordinate, VertexKey } from '../../types';\nimport { DirectedEdge, DirectedGraph, DirectedVertex } from './directed-graph';\n\nexport class MapVertex<V = any> extends DirectedVertex<V> {\n lat: number;\n long: number;\n\n /**\n * The constructor function initializes an object with an key, latitude, longitude, and an optional value.\n * @param {VertexKey} key - The `key` parameter is of type `VertexKey` and represents the identifier of the vertex.\n * @param {number} lat - The \"lat\" parameter represents the latitude of a vertex. Latitude is a geographic coordinate\n * that specifies the north-south position of a point on the Earth's surface. It is measured in degrees, with positive\n * values representing points north of the equator and negative values representing points south of the equator.\n * @param {number} long - The \"long\" parameter represents the longitude of a location. Longitude is a geographic\n * coordinate that specifies the east-west position of a point on the Earth's surface. It is measured in degrees, with\n * values ranging from -180 to 180.\n * @param {V} [value] - The \"value\" parameter is an optional value of type V. It is not required to be provided when\n * creating an instance of the class.\n */\n constructor(key: VertexKey, value: V, lat: number, long: number) {\n super(key, value);\n this.lat = lat;\n this.long = long;\n }\n}\n\nexport class MapEdge<E = any> extends DirectedEdge<E> {\n /**\n * The constructor function initializes a new instance of a class with the given source, destination, weight, and\n * value.\n * @param {VertexKey} src - The `src` parameter is the source vertex ID. It represents the starting point of an edge in\n * a graph.\n * @param {VertexKey} dest - The `dest` parameter is the identifier of the destination vertex for an edge.\n * @param {number} [weight] - The weight parameter is an optional number that represents the weight of the edge.\n * @param {E} [value] - The \"value\" parameter is an optional parameter of type E. It is used to store additional\n * information or data associated with the edge.\n */\n constructor(src: VertexKey, dest: VertexKey, weight?: number, value?: E) {\n super(src, dest, weight, value);\n }\n}\n\n/**\n *\n */\nexport class MapGraph<\n V = any,\n E = any,\n VO extends MapVertex<V> = MapVertex<V>,\n EO extends MapEdge<E> = MapEdge<E>\n> extends DirectedGraph<V, E, VO, EO> {\n /**\n * The constructor function initializes the originCoord and bottomRight properties of a MapGraphCoordinate object.\n * @param {MapGraphCoordinate} originCoord - The `originCoord` parameter is a `MapGraphCoordinate` object that represents the\n * starting point or reference point of the map graph. It defines the coordinates of the top-left corner of the map\n * graph.\n * @param {MapGraphCoordinate} [bottomRight] - The `bottomRight` parameter is an optional parameter of type\n * `MapGraphCoordinate`. It represents the bottom right coordinate of a map graph. If this parameter is not provided,\n * it will default to `undefined`.\n */\n constructor(originCoord: MapGraphCoordinate, bottomRight?: MapGraphCoordinate) {\n super();\n this._originCoord = originCoord;\n this._bottomRight = bottomRight;\n }\n\n protected _originCoord: MapGraphCoordinate = [0, 0];\n\n get originCoord(): MapGraphCoordinate {\n return this._originCoord;\n }\n\n protected _bottomRight: MapGraphCoordinate | undefined;\n\n get bottomRight(): MapGraphCoordinate | undefined {\n return this._bottomRight;\n }\n\n /**\n * The function creates a new vertex with the given key, value, latitude, and longitude.\n * @param {VertexKey} key - The key parameter is the unique identifier for the vertex. It is of type VertexKey, which could\n * be a string or a number depending on how you define it in your code.\n * @param [value] - The `value` parameter is an optional value that can be assigned to the `value` property of the vertex. It\n * is of type `V`, which means it should be of the same type as the `value` property of the vertex class `VO`.\n * @param {number} lat - The `lat` parameter represents the latitude of the vertex. It is a number that specifies the\n * position of the vertex on the Earth's surface in the north-south direction.\n * @param {number} long - The `long` parameter represents the longitude coordinate of the vertex.\n * @returns The method is returning a new instance of the `MapVertex` class, casted as type `VO`.\n */\n override createVertex(\n key: VertexKey,\n value?: V,\n lat: number = this.originCoord[0],\n long: number = this.originCoord[1]\n ): VO {\n return new MapVertex(key, value, lat, long) as VO;\n }\n\n /**\n * The function creates a new instance of a MapEdge with the given source, destination, weight, and value.\n * @param {VertexKey} src - The source vertex ID of the edge. It represents the starting point of the edge.\n * @param {VertexKey} dest - The `dest` parameter is the identifier of the destination vertex for the edge being\n * created.\n * @param {number} [weight] - The `weight` parameter is an optional number that represents the weight of the edge. It\n * is used to assign a numerical value to the edge, which can be used in algorithms such as shortest path algorithms.\n * If the weight is not provided, it can be set to a default value or left undefined.\n * @param [value] - The `value` parameter is an optional value that can be assigned to the edge. It can be of any type,\n * depending on the specific implementation of the `MapEdge` class.\n * @returns a new instance of the `MapEdge` class, cast as type `EO`.\n */\n override createEdge(src: VertexKey, dest: VertexKey, weight?: number, value?: E): EO {\n return new MapEdge(src, dest, weight, value) as EO;\n }\n\n /**\n * The override function is used to override the default behavior of a function.\n * In this case, we are overriding the clone() function from Graph&lt;V, E&gt;.\n * The clone() function returns a new graph that is an exact copy of the original graph.\n *\n * @return A mapgraph&lt;v, e, vo, eo&gt;\n */\n override clone(): MapGraph<V, E, VO, EO> {\n const cloned = new MapGraph<V, E, VO, EO>(this.originCoord, this.bottomRight);\n cloned.vertexMap = new Map<VertexKey, VO>(this.vertexMap);\n cloned.inEdgeMap = new Map<VO, EO[]>(this.inEdgeMap);\n cloned.outEdgeMap = new Map<VO, EO[]>(this.outEdgeMap);\n return cloned;\n }\n}\n","import { isComparable } from '../utils';\n\nexport enum DFSOperation {\n VISIT = 0,\n PROCESS = 1\n}\n\nexport class Range<K> {\n constructor(\n public low: K,\n public high: K,\n public includeLow: boolean = true,\n public includeHigh: boolean = true\n ) {\n if (!(isComparable(low) && isComparable(high))) throw new RangeError('low or high is not comparable');\n if (low > high) throw new RangeError('low must be less than or equal to high');\n }\n\n // Determine whether a key is within the range\n isInRange(key: K, comparator: (a: K, b: K) => number): boolean {\n const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;\n const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;\n return lowCheck && highCheck;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n\nimport type {\n BinaryTreeDeleteResult,\n BinaryTreeOptions,\n BinaryTreePrintOptions,\n BTNEntry,\n DFSOrderPattern,\n DFSStackItem,\n EntryCallback,\n FamilyPosition,\n IterationType,\n NodeCallback,\n NodeDisplayLayout,\n NodePredicate,\n OptNodeOrNull,\n RBTNColor,\n ToEntryFn\n} from '../../types';\nimport { IBinaryTree } from '../../interfaces';\nimport { isComparable, trampoline } from '../../utils';\nimport { Queue } from '../queue';\nimport { IterableEntryBase } from '../base';\nimport { DFSOperation, Range } from '../../common';\n\n/**\n * Represents a node in a binary tree.\n * @template V - The type of data stored in the node.\n * @template BinaryTreeNode<K, V> - The type of the family relationship in the binary tree.\n */\nexport class BinaryTreeNode<K = any, V = any> {\n key: K;\n value?: V;\n parent?: BinaryTreeNode<K, V> = undefined;\n\n /**\n * The constructor function initializes an object with a key and an optional value in TypeScript.\n * @param {K} key - The `key` parameter in the constructor function is used to store the key value\n * for the key-value pair.\n * @param {V} [value] - The `value` parameter in the constructor is optional, meaning it does not\n * have to be provided when creating an instance of the class. If a `value` is not provided, it will\n * default to `undefined`.\n */\n constructor(key: K, value?: V) {\n this.key = key;\n this.value = value;\n }\n\n _left?: BinaryTreeNode<K, V> | null | undefined = undefined;\n\n get left(): BinaryTreeNode<K, V> | null | undefined {\n return this._left;\n }\n\n set left(v: BinaryTreeNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this as unknown as BinaryTreeNode<K, V>;\n }\n this._left = v;\n }\n\n _right?: BinaryTreeNode<K, V> | null | undefined = undefined;\n\n get right(): BinaryTreeNode<K, V> | null | undefined {\n return this._right;\n }\n\n set right(v: BinaryTreeNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n\n _height: number = 0;\n\n get height(): number {\n return this._height;\n }\n\n set height(value: number) {\n this._height = value;\n }\n\n _color: RBTNColor = 'BLACK';\n\n get color(): RBTNColor {\n return this._color;\n }\n\n set color(value: RBTNColor) {\n this._color = value;\n }\n\n _count: number = 1;\n\n get count(): number {\n return this._count;\n }\n\n set count(value: number) {\n this._count = value;\n }\n\n get familyPosition(): FamilyPosition {\n if (!this.parent) {\n return this.left || this.right ? 'ROOT' : 'ISOLATED';\n }\n\n if (this.parent.left === this) {\n return this.left || this.right ? 'ROOT_LEFT' : 'LEFT';\n } else if (this.parent.right === this) {\n return this.left || this.right ? 'ROOT_RIGHT' : 'RIGHT';\n }\n\n return 'MAL_NODE';\n }\n}\n\n/**\n * 1. Two Children Maximum: Each node has at most two children.\n * 2. Left and Right Children: Nodes have distinct left and right children.\n * 3. Depth and Height: Depth is the number of edges from the root to a node; height is the maximum depth in the tree.\n * 4. Subtrees: Each child of a node forms the root of a subtree.\n * 5. Leaf Nodes: Nodes without children are leaves.\n * @example\n * // determine loan approval using a decision tree\n * // Decision tree structure\n * const loanDecisionTree = new BinaryTree<string>(\n * ['stableIncome', 'goodCredit', 'Rejected', 'Approved', 'Rejected'],\n * { isDuplicate: true }\n * );\n *\n * function determineLoanApproval(\n * node?: BinaryTreeNode<string> | null,\n * conditions?: { [key: string]: boolean }\n * ): string {\n * if (!node) throw new Error('Invalid node');\n *\n * // If it's a leaf node, return the decision result\n * if (!node.left && !node.right) return node.key;\n *\n * // Check if a valid condition exists for the current node's key\n * return conditions?.[node.key]\n * ? determineLoanApproval(node.left, conditions)\n * : determineLoanApproval(node.right, conditions);\n * }\n *\n * // Test case 1: Stable income and good credit score\n * console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: true, goodCredit: true })); // 'Approved'\n *\n * // Test case 2: Stable income but poor credit score\n * console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: true, goodCredit: false })); // 'Rejected'\n *\n * // Test case 3: No stable income\n * console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: false, goodCredit: true })); // 'Rejected'\n *\n * // Test case 4: No stable income and poor credit score\n * console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: false, goodCredit: false })); // 'Rejected'\n * @example\n * // evaluate the arithmetic expression represented by the binary tree\n * const expressionTree = new BinaryTree<number | string>(['+', 3, '*', null, null, 5, '-', null, null, 2, 8]);\n *\n * function evaluate(node?: BinaryTreeNode<number | string> | null): number {\n * if (!node) return 0;\n *\n * if (typeof node.key === 'number') return node.key;\n *\n * const leftValue = evaluate(node.left); // Evaluate the left subtree\n * const rightValue = evaluate(node.right); // Evaluate the right subtree\n *\n * // Perform the operation based on the current node's operator\n * switch (node.key) {\n * case '+':\n * return leftValue + rightValue;\n * case '-':\n * return leftValue - rightValue;\n * case '*':\n * return leftValue * rightValue;\n * case '/':\n * return rightValue !== 0 ? leftValue / rightValue : 0; // Handle division by zero\n * default:\n * throw new Error(`Unsupported operator: ${node.key}`);\n * }\n * }\n *\n * console.log(evaluate(expressionTree.root)); // -27\n */\nexport class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends IterableEntryBase<K, V | undefined>\n implements IBinaryTree<K, V, R, MK, MV, MR>\n{\n iterationType: IterationType = 'ITERATIVE';\n\n /**\n * This TypeScript constructor function initializes a binary tree with optional options and adds\n * elements based on the provided input.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an\n * iterable that can contain either objects of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It\n * is used to initialize the binary tree with keys, nodes, entries, or raw data.\n * @param [options] - The `options` parameter in the constructor is an optional object that can\n * contain the following properties:\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n > = [],\n options?: BinaryTreeOptions<K, V, R>\n ) {\n super();\n if (options) {\n const { iterationType, toEntryFn, isMapMode, isDuplicate } = options;\n if (iterationType) this.iterationType = iterationType;\n if (isMapMode !== undefined) this._isMapMode = isMapMode;\n if (isDuplicate !== undefined) this._isDuplicate = isDuplicate;\n if (typeof toEntryFn === 'function') this._toEntryFn = toEntryFn;\n else if (toEntryFn) throw TypeError('toEntryFn must be a function type');\n }\n\n if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);\n }\n\n protected _isMapMode = true;\n\n get isMapMode() {\n return this._isMapMode;\n }\n\n protected _isDuplicate = false;\n\n get isDuplicate() {\n return this._isDuplicate;\n }\n\n protected _store = new Map<K, V | undefined>();\n\n get store() {\n return this._store;\n }\n\n protected _root?: BinaryTreeNode<K, V> | null | undefined;\n\n get root(): BinaryTreeNode<K, V> | null | undefined {\n return this._root;\n }\n\n protected _size: number = 0;\n\n get size(): number {\n return this._size;\n }\n\n protected _NIL: BinaryTreeNode<K, V> = new BinaryTreeNode<K, V>(NaN as K) as unknown as BinaryTreeNode<K, V>;\n\n get NIL(): BinaryTreeNode<K, V> {\n return this._NIL;\n }\n\n protected _toEntryFn?: ToEntryFn<K, V, R>;\n\n get toEntryFn() {\n return this._toEntryFn;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a new binary tree node with a specified key and optional value.\n * @param {K} key - The `key` parameter is the key of the node being created in the binary tree.\n * @param {V} [value] - The `value` parameter in the `createNode` function is optional, meaning it is\n * not required to be provided when calling the function. If a `value` is provided, it should be of\n * type `V`, which is the type of the value associated with the node.\n * @returns A new BinaryTreeNode instance with the provided key and value is being returned, casted\n * as BinaryTreeNode<K, V>.\n */\n createNode(key: K, value?: V): BinaryTreeNode<K, V> {\n return new BinaryTreeNode<K, V>(key, this._isMapMode ? undefined : value);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a binary tree with the specified options.\n * @param [options] - The `options` parameter in the `createTree` function is an optional parameter\n * that allows you to provide partial configuration options for creating a binary tree. It is of type\n * `Partial<BinaryTreeOptions<K, V, R>>`, which means you can pass in an object containing a subset\n * of properties\n * @returns A new instance of a binary tree with the specified options is being returned.\n */\n createTree(options?: BinaryTreeOptions<K, V, R>) {\n return new BinaryTree<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n isMapMode: this._isMapMode,\n toEntryFn: this._toEntryFn,\n ...options\n });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The function `ensureNode` in TypeScript checks if a given input is a node, entry, key, or raw\n * value and returns the corresponding node or null.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`\n * parameter in the `ensureNode` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It\n * is used to determine whether the input is a key, node, entry, or raw data. The\n * @param {IterationType} iterationType - The `iterationType` parameter in the `ensureNode` function\n * is used to specify the type of iteration to be performed. It has a default value of\n * `this.iterationType` if not explicitly provided.\n * @returns The `ensureNode` function returns either a node, `null`, or `undefined` based on the\n * conditions specified in the code snippet.\n */\n ensureNode(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType: IterationType = this.iterationType\n ): BinaryTreeNode<K, V> | null | undefined {\n if (keyNodeOrEntry === null) return null;\n if (keyNodeOrEntry === undefined) return;\n if (keyNodeOrEntry === this._NIL) return;\n\n if (this.isNode(keyNodeOrEntry)) return keyNodeOrEntry;\n\n if (this.isEntry(keyNodeOrEntry)) {\n const key = keyNodeOrEntry[0];\n if (key === null) return null;\n if (key === undefined) return;\n return this.getNode(key, this._root, iterationType);\n }\n\n return this.getNode(keyNodeOrEntry, this._root, iterationType);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function isNode checks if the input is an instance of BinaryTreeNode.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be either a key, a node, an entry, or raw data. The function is\n * checking if the input is an instance of a `BinaryTreeNode` and returning a boolean value\n * accordingly.\n * @returns The function `isNode` is checking if the input `keyNodeOrEntry` is an instance of\n * `BinaryTreeNode`. If it is, the function returns `true`, indicating that the input is a node. If\n * it is not an instance of `BinaryTreeNode`, the function returns `false`, indicating that the input\n * is not a node.\n */\n isNode(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is BinaryTreeNode<K, V> {\n return keyNodeOrEntry instanceof BinaryTreeNode;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `isRaw` checks if the input parameter is of type `R` by verifying if it is an object.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R} keyNodeEntryOrRaw - K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n * @returns The function `isRaw` is checking if the `keyNodeEntryOrRaw` parameter is of type `R` by\n * checking if it is an object. If the parameter is an object, the function will return `true`,\n * indicating that it is of type `R`.\n */\n isRaw(\n keyNodeEntryOrRaw: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n ): keyNodeEntryOrRaw is R {\n return this._toEntryFn !== undefined && typeof keyNodeEntryOrRaw === 'object';\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `isRealNode` checks if a given input is a valid node in a binary tree.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`\n * parameter in the `isRealNode` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`.\n * The function checks if the input parameter is a `BinaryTreeNode<K, V>` type by verifying if it is not equal\n * @returns The function `isRealNode` is checking if the input `keyNodeOrEntry` is a valid\n * node by comparing it to `this._NIL`, `null`, and `undefined`. If the input is not one of these\n * values, it then calls the `isNode` method to further determine if the input is a node. The\n * function will return a boolean value indicating whether the\n */\n isRealNode(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is BinaryTreeNode<K, V> {\n if (keyNodeOrEntry === this._NIL || keyNodeOrEntry === null || keyNodeOrEntry === undefined) return false;\n return this.isNode(keyNodeOrEntry);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if a given input is a valid node or null.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` in the `isRealNodeOrNull` function can be of type `BTNRep<K,\n * V, BinaryTreeNode<K, V>>` or `R`. It is a union type that can either be a key, a node, an entry, or\n * @returns The function `isRealNodeOrNull` is returning a boolean value. It checks if the input\n * `keyNodeOrEntry` is either `null` or a real node, and returns `true` if it is a node or\n * `null`, and `false` otherwise.\n */\n isRealNodeOrNull(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is BinaryTreeNode<K, V> | null {\n return keyNodeOrEntry === null || this.isRealNode(keyNodeOrEntry);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function isNIL checks if a given key, node, entry, or raw value is equal to the _NIL value.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - BTNRep<K, V,\n * BinaryTreeNode<K, V>>\n * @returns The function is checking if the `keyNodeOrEntry` parameter is equal to the `_NIL`\n * property of the current object and returning a boolean value based on that comparison.\n */\n isNIL(keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): boolean {\n return keyNodeOrEntry === this._NIL;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `isRange` checks if the input parameter is an instance of the `Range` class.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>> | Range<K>} keyNodeEntryOrPredicate\n * - The `keyNodeEntryOrPredicate` parameter in the `isRange` function can be\n * of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `, `NodePredicate<BinaryTreeNode<K, V>>`, or\n * `Range<K>`. The function checks if the `keyNodeEntry\n * @returns The `isRange` function is checking if the `keyNodeEntryOrPredicate` parameter is an\n * instance of the `Range` class. If it is an instance of `Range`, the function will return `true`,\n * indicating that the parameter is a `Range<K>`. If it is not an instance of `Range`, the function\n * will return `false`.\n */\n isRange(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V>>\n | Range<K>\n ): keyNodeEntryOrPredicate is Range<K> {\n return keyNodeEntryOrPredicate instanceof Range;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function determines whether a given key, node, entry, or raw data is a leaf node in a binary\n * tree.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It represents a\n * key, node, entry, or raw data in a binary tree structure. The function `isLeaf` checks whether the\n * provided\n * @returns The function `isLeaf` returns a boolean value indicating whether the input\n * `keyNodeOrEntry` is a leaf node in a binary tree.\n */\n isLeaf(keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): boolean {\n keyNodeOrEntry = this.ensureNode(keyNodeOrEntry);\n if (keyNodeOrEntry === undefined) return false;\n if (keyNodeOrEntry === null) return true;\n return !this.isRealNode(keyNodeOrEntry.left) && !this.isRealNode(keyNodeOrEntry.right);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `isEntry` checks if the input is a BTNEntry object by verifying if it is an array\n * with a length of 2.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`\n * parameter in the `isEntry` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or type `R`.\n * The function checks if the provided `keyNodeOrEntry` is of type `BTN\n * @returns The `isEntry` function is checking if the `keyNodeOrEntry` parameter is an array\n * with a length of 2. If it is, then it returns `true`, indicating that the parameter is of type\n * `BTNEntry<K, V>`. If the condition is not met, it returns `false`.\n */\n isEntry(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is BTNEntry<K, V> {\n return Array.isArray(keyNodeOrEntry) && keyNodeOrEntry.length === 2;\n }\n\n /**\n * Time Complexity O(1)\n * Space Complexity O(1)\n *\n * The function `isValidKey` checks if a given key is comparable.\n * @param {any} key - The `key` parameter is of type `any`, which means it can be any data type in\n * TypeScript.\n * @returns The function `isValidKey` is checking if the `key` parameter is `null` or if it is comparable.\n * If the `key` is `null`, the function returns `true`. Otherwise, it returns the result of the\n * `isComparable` function, which is not provided in the code snippet.\n */\n isValidKey(key: any): key is K {\n if (key === null) return true;\n return isComparable(key);\n }\n\n /**\n * Time Complexity O(n)\n * Space Complexity O(1)\n *\n * The `add` function in TypeScript adds a new node to a binary tree while handling duplicate keys\n * and finding the correct insertion position.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `add` method you provided\n * seems to be for adding a new node to a binary tree structure. The `keyNodeOrEntry`\n * parameter in the method can accept different types of values:\n * @param {V} [value] - The `value` parameter in the `add` method represents the value associated\n * with the key that you want to add to the binary tree. When adding a key-value pair to the binary\n * tree, you provide the key and its corresponding value. The `add` method then creates a new node\n * with this\n * @returns The `add` method returns a boolean value. It returns `true` if the insertion of the new\n * node was successful, and `false` if the insertion position could not be found or if a duplicate\n * key was found and the node was replaced instead of inserted.\n */\n add(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V\n ): boolean {\n const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);\n if (newNode === undefined) return false;\n\n // If the tree is empty, directly set the new node as the root node\n if (!this._root) {\n this._setRoot(newNode);\n if (this._isMapMode) this._setValue(newNode?.key, newValue);\n this._size = 1;\n return true;\n }\n\n const queue = new Queue<BinaryTreeNode<K, V>>([this._root]);\n let potentialParent: BinaryTreeNode<K, V> | undefined; // Record the parent node of the potential insertion location\n\n while (queue.length > 0) {\n const cur = queue.shift();\n\n if (!cur) continue;\n\n if (!this._isDuplicate) {\n // Check for duplicate keys when newNode is not null\n if (newNode !== null && cur.key === newNode.key) {\n this._replaceNode(cur, newNode);\n if (this._isMapMode) this._setValue(cur.key, newValue);\n return true; // If duplicate keys are found, no insertion is performed\n }\n }\n\n // Record the first possible insertion location found\n if (potentialParent === undefined && (cur.left === undefined || cur.right === undefined)) {\n potentialParent = cur;\n }\n\n // Continue traversing the left and right subtrees\n if (cur.left !== null) {\n if (cur.left) queue.push(cur.left);\n }\n if (cur.right !== null) {\n if (cur.right) queue.push(cur.right);\n }\n }\n\n // At the end of the traversal, if the insertion position is found, insert\n if (potentialParent) {\n if (potentialParent.left === undefined) {\n potentialParent.left = newNode;\n } else if (potentialParent.right === undefined) {\n potentialParent.right = newNode;\n }\n if (this._isMapMode) this._setValue(newNode?.key, newValue);\n this._size++;\n return true;\n }\n\n return false; // If the insertion position cannot be found, return undefined\n }\n\n /**\n * Time Complexity: O(k * n)\n * Space Complexity: O(k)\n *\n * The `addMany` function takes in multiple keys or nodes or entries or raw values along with\n * optional values, and adds them to a data structure while returning an array indicating whether\n * each insertion was successful.\n * @param keysNodesEntriesOrRaws - `keysNodesEntriesOrRaws` is an iterable that can contain a\n * mix of keys, nodes, entries, or raw values. Each element in this iterable can be of type\n * `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`.\n * @param [values] - The `values` parameter in the `addMany` function is an optional parameter that\n * accepts an iterable of values. These values correspond to the keys or nodes being added in the\n * `keysNodesEntriesOrRaws` parameter. If provided, the function will iterate over the values and\n * assign them\n * @returns The `addMany` method returns an array of boolean values indicating whether each key,\n * node, entry, or raw value was successfully added to the data structure. Each boolean value\n * corresponds to the success of adding the corresponding key or value in the input iterable.\n */\n addMany(\n keysNodesEntriesOrRaws: Iterable<\n K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n >,\n values?: Iterable<V | undefined>\n ): boolean[] {\n // TODO not sure addMany not be run multi times\n const inserted: boolean[] = [];\n\n let valuesIterator: Iterator<V | undefined> | undefined;\n if (values) {\n valuesIterator = values[Symbol.iterator]();\n }\n\n for (let keyNodeEntryOrRaw of keysNodesEntriesOrRaws) {\n let value: V | undefined | null = undefined;\n\n if (valuesIterator) {\n const valueResult = valuesIterator.next();\n if (!valueResult.done) {\n value = valueResult.value;\n }\n }\n if (this.isRaw(keyNodeEntryOrRaw)) keyNodeEntryOrRaw = this._toEntryFn!(keyNodeEntryOrRaw);\n inserted.push(this.add(keyNodeEntryOrRaw, value));\n }\n\n return inserted;\n }\n\n /**\n * Time Complexity: O(k * n)\n * Space Complexity: O(1)\n *\n * The `merge` function in TypeScript merges another binary tree into the current tree by adding all\n * elements from the other tree.\n * @param anotherTree - BinaryTree<K, V, R, MK, MV, MR>\n */\n merge(anotherTree: BinaryTree<K, V, R, MK, MV, MR>) {\n this.addMany(anotherTree, []);\n }\n\n /**\n * Time Complexity: O(k * n)\n * Space Complexity: O(1)\n *\n * The `refill` function clears the existing data structure and then adds new key-value pairs based\n * on the provided input.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the `refill`\n * method can accept an iterable containing a mix of `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` objects or `R`\n * objects.\n * @param [values] - The `values` parameter in the `refill` method is an optional parameter that\n * accepts an iterable of values of type `V` or `undefined`.\n */\n refill(\n keysNodesEntriesOrRaws: Iterable<\n K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n >,\n values?: Iterable<V | undefined>\n ): void {\n this.clear();\n this.addMany(keysNodesEntriesOrRaws, values);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `delete` in TypeScript implements the deletion of a node in a binary tree and returns\n * the deleted node along with information for tree balancing.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry\n * - The `delete` method you provided is used to delete a node from a binary tree based on the key,\n * node, entry or raw data. The method returns an array of\n * `BinaryTreeDeleteResult` objects containing information about the deleted node and whether\n * balancing is needed.\n * @returns The `delete` method returns an array of `BinaryTreeDeleteResult` objects. Each object in\n * the array contains information about the node that was deleted (`deleted`) and the node that may\n * need to be balanced (`needBalanced`).\n */\n delete(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] {\n const deletedResult: BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] = [];\n if (!this._root) return deletedResult;\n\n const curr = this.getNode(keyNodeOrEntry);\n if (!curr) return deletedResult;\n\n const parent: BinaryTreeNode<K, V> | undefined = curr?.parent;\n let needBalanced: BinaryTreeNode<K, V> | undefined;\n let orgCurrent: BinaryTreeNode<K, V> | undefined = curr;\n\n if (!curr.left && !curr.right && !parent) {\n this._setRoot(undefined);\n } else if (curr.left) {\n const leftSubTreeRightMost = this.getRightMost(node => node, curr.left);\n if (leftSubTreeRightMost) {\n const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;\n orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);\n if (parentOfLeftSubTreeMax) {\n if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)\n parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;\n else parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;\n needBalanced = parentOfLeftSubTreeMax;\n }\n }\n } else if (parent) {\n const { familyPosition: fp } = curr;\n if (fp === 'LEFT' || fp === 'ROOT_LEFT') {\n parent.left = curr.right;\n } else if (fp === 'RIGHT' || fp === 'ROOT_RIGHT') {\n parent.right = curr.right;\n }\n needBalanced = parent;\n } else {\n this._setRoot(curr.right);\n curr.right = undefined;\n }\n\n this._size = this._size - 1;\n\n deletedResult.push({ deleted: orgCurrent, needBalanced });\n if (this._isMapMode && orgCurrent) this._store.delete(orgCurrent.key);\n return deletedResult;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(k + log n)\n *\n * The `search` function in TypeScript performs a depth-first or breadth-first search on a tree\n * structure based on a given predicate or key, with options to return multiple results or just one.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The\n * `keyNodeEntryOrPredicate` parameter in the `search` function can accept three types of values:\n * @param [onlyOne=false] - The `onlyOne` parameter in the `search` function is a boolean flag that\n * determines whether the search should stop after finding the first matching node. If `onlyOne` is\n * set to `true`, the search will return as soon as a matching node is found. If `onlyOne` is\n * @param {C} callback - The `callback` parameter in the `search` function is a callback function\n * that will be called on each node that matches the search criteria. It is of type `C`, which\n * extends `NodeCallback<BinaryTreeNode<K, V> | null>`. The default value for `callback` is `this._DEFAULT_NODE_CALLBACK` if\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `search` function is\n * used to specify the node from which the search operation should begin. It represents the starting\n * point in the binary tree where the search will be performed. If no specific `startNode` is\n * provided, the search operation will start from the root\n * @param {IterationType} iterationType - The `iterationType` parameter in the `search` function\n * specifies the type of iteration to be used when searching for nodes in a binary tree. It can have\n * two possible values:\n * @returns The `search` function returns an array of values that match the provided criteria based\n * on the search algorithm implemented within the function.\n */\n search<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V> | null>,\n onlyOne = false,\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C>[] {\n if (keyNodeEntryOrPredicate === undefined) return [];\n if (keyNodeEntryOrPredicate === null) return [];\n startNode = this.ensureNode(startNode);\n if (!startNode) return [];\n const predicate = this._ensurePredicate(keyNodeEntryOrPredicate);\n\n const ans: ReturnType<C>[] = [];\n\n if (iterationType === 'RECURSIVE') {\n const dfs = (cur: BinaryTreeNode<K, V>) => {\n if (predicate(cur)) {\n ans.push(callback(cur));\n if (onlyOne) return;\n }\n if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;\n if (this.isRealNode(cur.left)) dfs(cur.left);\n if (this.isRealNode(cur.right)) dfs(cur.right);\n };\n\n dfs(startNode);\n } else {\n const stack = [startNode];\n while (stack.length > 0) {\n const cur = stack.pop();\n if (this.isRealNode(cur)) {\n if (predicate(cur)) {\n ans.push(callback(cur));\n if (onlyOne) return ans;\n }\n if (this.isRealNode(cur.left)) stack.push(cur.left);\n if (this.isRealNode(cur.right)) stack.push(cur.right);\n }\n }\n }\n\n return ans;\n }\n\n getNodes(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V>>,\n onlyOne?: boolean,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType\n ): BinaryTreeNode<K, V>[];\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(k + log n)\n *\n * The function `getNodes` retrieves nodes from a binary tree based on a key, node, entry, raw data,\n * or predicate, with options for recursive or iterative traversal.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate\n * - The `getNodes` function you provided takes several parameters:\n * @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` function is a boolean flag that\n * determines whether to return only the first node that matches the criteria specified by the\n * `keyNodeEntryOrPredicate` parameter. If `onlyOne` is set to `true`, the function will\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `getNodes` function is used to specify the starting point for traversing the binary tree. It\n * represents the root node of the binary tree or the node from which the traversal should begin. If\n * not provided, the default value is set to `this._root\n * @param {IterationType} iterationType - The `iterationType` parameter in the `getNodes` function\n * determines the type of iteration to be performed when traversing the nodes of a binary tree. It\n * can have two possible values:\n * @returns The `getNodes` function returns an array of nodes that satisfy the provided condition\n * based on the input parameters and the iteration type specified.\n */\n getNodes(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V> | null>,\n onlyOne = false,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): (BinaryTreeNode<K, V> | null)[] {\n return this.search(keyNodeEntryOrPredicate, onlyOne, node => node, startNode, iterationType);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The `getNode` function retrieves a node based on the provided key, node, entry, raw data, or\n * predicate.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate\n * - The `keyNodeEntryOrPredicate` parameter in the `getNode` function can accept a key,\n * node, entry, raw data, or a predicate function.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `getNode` function is used to specify the starting point for searching for a node in a binary\n * tree. If no specific starting point is provided, the default value is set to `this._root`, which\n * is typically the root node of the binary tree.\n * @param {IterationType} iterationType - The `iterationType` parameter in the `getNode` method is\n * used to specify the type of iteration to be performed when searching for a node. It has a default\n * value of `this.iterationType`, which means it will use the iteration type defined in the current\n * context if no specific value is provided\n * @returns The `getNode` function is returning the first node that matches the specified criteria,\n * or `null` if no matching node is found.\n */\n getNode(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V> | null>,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): BinaryTreeNode<K, V> | null | undefined {\n return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType)[0];\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * This function overrides the `get` method to retrieve the value associated with a specified key,\n * node, entry, raw data, or predicate in a data structure.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate\n * - The `keyNodeEntryOrPredicate` parameter in the `get` method can accept one of the\n * following types:\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `get`\n * method is used to specify the starting point for searching for a key or node in the binary tree.\n * If no specific starting point is provided, the default starting point is the root of the binary\n * tree (`this._root`).\n * @param {IterationType} iterationType - The `iterationType` parameter in the `get` method is used\n * to specify the type of iteration to be performed when searching for a key in the binary tree. It\n * is an optional parameter with a default value of `this.iterationType`, which means it will use the\n * iteration type defined in the\n * @returns The `get` method is returning the value associated with the specified key, node, entry,\n * raw data, or predicate in the binary tree map. If the specified key or node is found in the tree,\n * the method returns the corresponding value. If the key or node is not found, it returns\n * `undefined`.\n */\n override get(\n keyNodeEntryOrPredicate: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): V | undefined {\n if (this._isMapMode) {\n const key = this._extractKey(keyNodeEntryOrPredicate);\n if (key === null || key === undefined) return;\n return this._store.get(key);\n }\n return this.getNode(keyNodeEntryOrPredicate, startNode, iterationType)?.value;\n }\n\n override has(\n keyNodeEntryOrPredicate?:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V>>,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType\n ): boolean;\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The `has` function in TypeScript checks if a specified key, node, entry, raw data, or predicate\n * exists in the data structure.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate\n * - The `keyNodeEntryOrPredicate` parameter in the `override has` method can accept one of\n * the following types:\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `override` method is used to specify the starting point for the search operation within the data\n * structure. It defaults to `this._root` if not provided explicitly.\n * @param {IterationType} iterationType - The `iterationType` parameter in the `override has` method\n * is used to specify the type of iteration to be performed. It has a default value of\n * `this.iterationType`, which means it will use the iteration type defined in the current context if\n * no value is provided when calling the method.\n * @returns The `override has` method is returning a boolean value. It checks if there are any nodes\n * that match the provided key, node, entry, raw data, or predicate in the tree structure. If there\n * are matching nodes, it returns `true`, indicating that the tree contains the specified element.\n * Otherwise, it returns `false`.\n */\n override has(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V> | null>,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): boolean {\n return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType).length > 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear function removes nodes and values in map mode.\n */\n clear() {\n this._clearNodes();\n if (this._isMapMode) this._clearValues();\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `isEmpty` function in TypeScript checks if a data structure has no elements and returns a\n * boolean value.\n * @returns The `isEmpty()` method is returning a boolean value, specifically `true` if the `_size`\n * property is equal to 0, indicating that the data structure is empty, and `false` otherwise.\n */\n isEmpty(): boolean {\n return this._size === 0;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The function checks if a binary tree is perfectly balanced by comparing its minimum height with\n * its height.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting\n * point for checking if the binary tree is perfectly balanced. It represents the root node of the\n * binary tree or a specific node from which the balance check should begin.\n * @returns The method `isPerfectlyBalanced` is returning a boolean value, which indicates whether\n * the tree starting from the `startNode` node is perfectly balanced or not. The return value is\n * determined by comparing the minimum height of the tree with the height of the tree. If the minimum\n * height plus 1 is greater than or equal to the height of the tree, then it is considered perfectly\n * balanced and\n */\n isPerfectlyBalanced(\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root\n ): boolean {\n return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The function `isBST` in TypeScript checks if a binary search tree is valid using either recursive\n * or iterative methods.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `isBST`\n * function represents the starting point for checking whether a binary search tree (BST) is valid.\n * It can be a node in the BST or a reference to the root of the BST. If no specific node is\n * provided, the function will default to\n * @param {IterationType} iterationType - The `iterationType` parameter in the `isBST` function\n * determines whether the function should use a recursive approach or an iterative approach to check\n * if the binary search tree (BST) is valid.\n * @returns The `isBST` method is returning a boolean value, which indicates whether the binary\n * search tree (BST) represented by the given root node is a valid BST or not. The method checks if\n * the tree satisfies the BST property, where for every node, all nodes in its left subtree have keys\n * less than the node's key, and all nodes in its right subtree have keys greater than the node's\n */\n isBST(\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): boolean {\n // TODO there is a bug\n startNode = this.ensureNode(startNode);\n if (!startNode) return true;\n\n if (iterationType === 'RECURSIVE') {\n const dfs = (cur: BinaryTreeNode<K, V> | null | undefined, min: number, max: number): boolean => {\n if (!this.isRealNode(cur)) return true;\n const numKey = Number(cur.key);\n if (numKey <= min || numKey >= max) return false;\n return dfs(cur.left, min, numKey) && dfs(cur.right, numKey, max);\n };\n\n const isStandardBST = dfs(startNode, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);\n const isInverseBST = dfs(startNode, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);\n return isStandardBST || isInverseBST;\n } else {\n const checkBST = (checkMax = false) => {\n const stack = [];\n let prev = checkMax ? Number.MAX_SAFE_INTEGER : Number.MIN_SAFE_INTEGER;\n // @ts-ignore\n let curr: BinaryTreeNode<K, V> | null | undefined = startNode;\n while (this.isRealNode(curr) || stack.length > 0) {\n while (this.isRealNode(curr)) {\n stack.push(curr);\n curr = curr.left;\n }\n curr = stack.pop()!;\n const numKey = Number(curr.key);\n if (!this.isRealNode(curr) || (!checkMax && prev >= numKey) || (checkMax && prev <= numKey)) return false;\n prev = numKey;\n curr = curr.right;\n }\n return true;\n };\n const isStandardBST = checkBST(false),\n isInverseBST = checkBST(true);\n return isStandardBST || isInverseBST;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The `getDepth` function calculates the depth between two nodes in a binary tree.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } dist - The `dist` parameter in the `getDepth`\n * function represents the node or entry in a binary tree map, or a reference to a node in the tree.\n * It is the target node for which you want to calculate the depth from the `startNode` node.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `getDepth` function represents the starting point from which you want to calculate the depth of a\n * given node or entry in a binary tree. If no specific starting point is provided, the default value\n * for `startNode` is set to the root of the binary\n * @returns The `getDepth` method returns the depth of a given node `dist` relative to the\n * `startNode` node in a binary tree. If the `dist` node is not found in the path to the `startNode`\n * node, it returns the depth of the `dist` node from the root of the tree.\n */\n getDepth(\n dist: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root\n ): number {\n let distEnsured = this.ensureNode(dist);\n const beginRootEnsured = this.ensureNode(startNode);\n let depth = 0;\n while (distEnsured?.parent) {\n if (distEnsured === beginRootEnsured) {\n return depth;\n }\n depth++;\n distEnsured = distEnsured.parent;\n }\n return depth;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The `getHeight` function calculates the maximum height of a binary tree using either a recursive\n * or iterative approach in TypeScript.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting\n * point from which the height of the binary tree will be calculated. It can be a node in the binary\n * tree or a reference to the root of the tree. If not provided, it defaults to the root of the\n * binary tree data structure.\n * @param {IterationType} iterationType - The `iterationType` parameter is used to determine the type\n * of iteration to be performed while calculating the height of the binary tree. It can have two\n * possible values:\n * @returns The `getHeight` method returns the height of the binary tree starting from the specified\n * root node. The height is calculated based on the maximum depth of the tree, considering either a\n * recursive approach or an iterative approach depending on the `iterationType` parameter.\n */\n getHeight(\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): number {\n startNode = this.ensureNode(startNode);\n if (!this.isRealNode(startNode)) return -1;\n\n if (iterationType === 'RECURSIVE') {\n const _getMaxHeight = (cur: BinaryTreeNode<K, V> | null | undefined): number => {\n if (!this.isRealNode(cur)) return -1;\n const leftHeight = _getMaxHeight(cur.left);\n const rightHeight = _getMaxHeight(cur.right);\n return Math.max(leftHeight, rightHeight) + 1;\n };\n\n return _getMaxHeight(startNode);\n } else {\n const stack: { node: BinaryTreeNode<K, V>; depth: number }[] = [{ node: startNode, depth: 0 }];\n let maxHeight = 0;\n\n while (stack.length > 0) {\n const { node, depth } = stack.pop()!;\n\n if (this.isRealNode(node.left)) stack.push({ node: node.left, depth: depth + 1 });\n if (this.isRealNode(node.right)) stack.push({ node: node.right, depth: depth + 1 });\n\n maxHeight = Math.max(maxHeight, depth);\n }\n\n return maxHeight;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The `getMinHeight` function calculates the minimum height of a binary tree using either a\n * recursive or iterative approach in TypeScript.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `getMinHeight` function represents the starting node from which the minimum height of the binary\n * tree will be calculated. It is either a node in the binary tree or a reference to the root of the\n * tree. If not provided, the default value is the root\n * @param {IterationType} iterationType - The `iterationType` parameter in the `getMinHeight` method\n * specifies the type of iteration to use when calculating the minimum height of a binary tree. It\n * can have two possible values:\n * @returns The `getMinHeight` method returns the minimum height of the binary tree starting from the\n * specified root node. The height is calculated based on the shortest path from the root node to a\n * leaf node in the tree. The method uses either a recursive approach or an iterative approach (using\n * a stack) based on the `iterationType` parameter.\n */\n getMinHeight(\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): number {\n startNode = this.ensureNode(startNode);\n if (!startNode) return -1;\n\n if (iterationType === 'RECURSIVE') {\n const _getMinHeight = (cur: BinaryTreeNode<K, V> | null | undefined): number => {\n if (!this.isRealNode(cur)) return 0;\n if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return 0;\n const leftMinHeight = _getMinHeight(cur.left);\n const rightMinHeight = _getMinHeight(cur.right);\n return Math.min(leftMinHeight, rightMinHeight) + 1;\n };\n\n return _getMinHeight(startNode);\n } else {\n const stack: BinaryTreeNode<K, V>[] = [];\n let node: BinaryTreeNode<K, V> | null | undefined = startNode,\n last: BinaryTreeNode<K, V> | null | undefined = null;\n const depths: Map<BinaryTreeNode<K, V>, number> = new Map();\n\n while (stack.length > 0 || node) {\n if (this.isRealNode(node)) {\n stack.push(node);\n node = node.left;\n } else {\n node = stack[stack.length - 1];\n if (!this.isRealNode(node.right) || last === node.right) {\n node = stack.pop();\n if (this.isRealNode(node)) {\n const leftMinHeight = this.isRealNode(node.left) ? depths.get(node.left)! : -1;\n const rightMinHeight = this.isRealNode(node.right) ? depths.get(node.right)! : -1;\n depths.set(node, 1 + Math.min(leftMinHeight, rightMinHeight));\n last = node;\n node = null;\n }\n } else node = node.right;\n }\n }\n\n return depths.get(startNode)!;\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `getPathToRoot` in TypeScript retrieves the path from a given node to the root of a\n * tree structure, applying a specified callback function along the way.\n * @param {C} callback - The `callback` parameter is a function that is used to process each node in\n * the path to the root. It is expected to be a function that takes a node as an argument and returns\n * a value based on that node. The return type of the callback function is determined by the generic\n * type `C\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } beginNode - The `beginNode` parameter in the\n * `getPathToRoot` function can be either a key, a node, an entry, or any other value of type `R`.\n * @param [isReverse=true] - The `isReverse` parameter in the `getPathToRoot` function determines\n * whether the resulting path from the given `beginNode` to the root should be in reverse order or\n * not. If `isReverse` is set to `true`, the path will be reversed before being returned. If `is\n * @returns The function `getPathToRoot` returns an array of the return values of the callback\n * function `callback` applied to each node in the path from the `beginNode` to the root node. The\n * array is either in reverse order or in the original order based on the value of the `isReverse`\n * parameter.\n */\n getPathToRoot<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(\n beginNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n isReverse = false\n ): ReturnType<C>[] {\n const result: ReturnType<C>[] = [];\n let beginNodeEnsured = this.ensureNode(beginNode);\n\n if (!beginNodeEnsured) return result;\n\n while (beginNodeEnsured.parent) {\n // Array.push + Array.reverse is more efficient than Array.unshift\n result.push(callback(beginNodeEnsured));\n beginNodeEnsured = beginNodeEnsured.parent;\n }\n result.push(callback(beginNodeEnsured));\n return isReverse ? result.reverse() : result;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `getLeftMost` retrieves the leftmost node in a binary tree using either recursive or\n * tail-recursive iteration.\n * @param {C} callback - The `callback` parameter is a function that will be called with the leftmost\n * node of a binary tree or with `undefined` if the tree is empty. It is provided with a default\n * value of `_DEFAULT_NODE_CALLBACK` if not specified.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `getLeftMost` function represents the starting point for finding the leftmost node in a binary\n * tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific\n * starting point is provided, the function will default\n * @param {IterationType} iterationType - The `iterationType` parameter in the `getLeftMost` function\n * specifies the type of iteration to be used when traversing the binary tree nodes. It can have two\n * possible values:\n * @returns The `getLeftMost` function returns the result of the callback function `C` applied to the\n * leftmost node in the binary tree starting from the `startNode` node. If the `startNode` node is\n * `NIL`, it returns the result of the callback function applied to `undefined`. If the `startNode`\n * node is not a real node, it returns the result of the callback\n */\n getLeftMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C> {\n if (this.isNIL(startNode)) return callback(undefined);\n startNode = this.ensureNode(startNode);\n\n if (!this.isRealNode(startNode)) return callback(startNode);\n\n if (iterationType === 'RECURSIVE') {\n const dfs = (cur: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> => {\n if (!this.isRealNode(cur.left)) return cur;\n return dfs(cur.left);\n };\n\n return callback(dfs(startNode));\n } else {\n // Indirect implementation of iteration using tail recursion optimization\n const dfs = trampoline((cur: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> => {\n if (!this.isRealNode(cur.left)) return cur;\n return dfs.cont(cur.left);\n });\n\n return callback(dfs(startNode));\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `getRightMost` retrieves the rightmost node in a binary tree using either recursive\n * or iterative traversal methods.\n * @param {C} callback - The `callback` parameter is a function that will be called with the result\n * of finding the rightmost node in a binary tree. It is of type `NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>`,\n * which means it is a callback function that can accept either an optional binary tree node or null\n * as\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `getRightMost` function represents the starting point for finding the rightmost node in a binary\n * tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific\n * starting point is provided, the function will default\n * @param {IterationType} iterationType - The `iterationType` parameter in the `getRightMost`\n * function specifies the type of iteration to be used when traversing the binary tree nodes. It can\n * have two possible values:\n * @returns The `getRightMost` function returns the result of the callback function `C`, which is\n * passed as a parameter to the function. The callback function is called with the rightmost node in\n * the binary tree structure, determined based on the specified iteration type ('RECURSIVE' or\n * other).\n */\n getRightMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C> {\n if (this.isNIL(startNode)) return callback(undefined);\n startNode = this.ensureNode(startNode);\n if (!startNode) return callback(startNode);\n\n if (iterationType === 'RECURSIVE') {\n const dfs = (cur: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> => {\n if (!this.isRealNode(cur.right)) return cur;\n return dfs(cur.right);\n };\n\n return callback(dfs(startNode));\n } else {\n // Indirect implementation of iteration using tail recursion optimization\n const dfs = trampoline((cur: BinaryTreeNode<K, V>) => {\n if (!this.isRealNode(cur.right)) return cur;\n return dfs.cont(cur.right);\n });\n\n return callback(dfs(startNode));\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `getPredecessor` in TypeScript returns the predecessor node of a given node in a\n * binary tree.\n * @param {BinaryTreeNode<K, V>} node - The `getPredecessor` function you provided seems to be attempting to find the\n * predecessor of a given node in a binary tree. However, there seems to be a logical issue in the\n * while loop condition that might cause an infinite loop.\n * @returns The `getPredecessor` function returns the predecessor node of the input `BinaryTreeNode<K, V>` parameter.\n * If the left child of the input node exists, it traverses to the rightmost node of the left subtree\n * to find the predecessor. If the left child does not exist, it returns the input node itself.\n */\n getPredecessor(node: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> {\n if (this.isRealNode(node.left)) {\n let predecessor: BinaryTreeNode<K, V> | null | undefined = node.left;\n while (!this.isRealNode(predecessor) || (this.isRealNode(predecessor.right) && predecessor.right !== node)) {\n if (this.isRealNode(predecessor)) {\n predecessor = predecessor.right;\n }\n }\n return predecessor;\n } else {\n return node;\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `getSuccessor` in TypeScript returns the next node in an in-order traversal of a\n * binary tree.\n * @param {K | BinaryTreeNode<K, V> | null} [x] - The `getSuccessor` function takes a parameter `x`, which can be of\n * type `K`, `BinaryTreeNode<K, V>`, or `null`.\n * @returns The `getSuccessor` function returns the successor node of the input node `x`. If `x` has\n * a right child, the function returns the leftmost node in the right subtree of `x`. If `x` does not\n * have a right child, the function traverses up the parent nodes until it finds a node that is not\n * the right child of its parent, and returns that node\n */\n getSuccessor(x?: K | BinaryTreeNode<K, V> | null): BinaryTreeNode<K, V> | null | undefined {\n x = this.ensureNode(x);\n if (!this.isRealNode(x)) return undefined;\n\n if (this.isRealNode(x.right)) {\n return this.getLeftMost(node => node, x.right);\n }\n\n let y: BinaryTreeNode<K, V> | null | undefined = x.parent;\n while (this.isRealNode(y) && x === y.right) {\n x = y;\n y = y.parent;\n }\n return y;\n }\n\n dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(\n callback?: C,\n pattern?: DFSOrderPattern,\n onlyOne?: boolean,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType\n ): ReturnType<C>[];\n\n dfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback?: C,\n pattern?: DFSOrderPattern,\n onlyOne?: boolean,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType,\n includeNull?: boolean\n ): ReturnType<C>[];\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The function performs a depth-first search on a binary tree structure based on the specified\n * parameters.\n * @param {C} callback - The `callback` parameter is a function that will be called for each node\n * visited during the depth-first search. It should accept a `BinaryTreeNode` as an argument and\n * return an optional node or null. The default value for this parameter is `_DEFAULT_NODE_CALLBACK`.\n * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `dfs` function specifies\n * the order in which the nodes are visited during a depth-first search traversal. The possible\n * values for the `pattern` parameter are:\n * @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `dfs` function is a boolean flag\n * that determines whether the depth-first search should stop after finding the first matching node\n * or continue searching for all matching nodes. If `onlyOne` is set to `true`, the search will stop\n * after finding the first matching node\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined}\n * startNode - The `startNode` parameter in the `dfs` function can be one of the following types:\n * @param {IterationType} iterationType - The `iterationType` parameter in the `dfs` function\n * specifies the type of iteration to be performed during the Depth-First Search traversal. It is\n * used to determine the order in which nodes are visited during the traversal. The possible values\n * for `iterationType` are typically defined as an enum or a\n * @param [includeNull=false] - The `includeNull` parameter in the `dfs` function determines whether\n * null nodes should be included in the depth-first search traversal. If `includeNull` is set to\n * `true`, null nodes will be included in the traversal process. If it is set to `false`, null nodes\n * will be skipped\n * @returns The `dfs` method is returning an array of the return type of the callback function `C`.\n */\n dfs<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n pattern: DFSOrderPattern = 'IN',\n onlyOne: boolean = false,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType,\n includeNull = false\n ): ReturnType<C>[] {\n startNode = this.ensureNode(startNode);\n if (!startNode) return [];\n return this._dfs(callback, pattern, onlyOne, startNode, iterationType, includeNull);\n }\n\n bfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(\n callback?: C,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType,\n includeNull?: false\n ): ReturnType<C>[];\n\n bfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback?: C,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType,\n includeNull?: true\n ): ReturnType<C>[];\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `bfs` function performs a breadth-first search traversal on a binary tree or binary search\n * tree, executing a specified callback function on each node visited.\n * @param {C} callback - The `callback` parameter in the `bfs` function is a function that will be\n * called on each node visited during the breadth-first search traversal. It is a generic type `C`\n * that extends the `NodeCallback` type, which takes a parameter of type `BinaryTreeNode<K, V>` or `null`.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `bfs`\n * function represents the starting point for the breadth-first search traversal in a binary tree. It\n * can be specified as a key, node, or entry in the binary tree structure. If not provided, the\n * default value is the root node of the binary\n * @param {IterationType} iterationType - The `iterationType` parameter in the `bfs` function\n * determines the type of iteration to be performed on the binary tree nodes. It can have two\n * possible values:\n * @param [includeNull=false] - The `includeNull` parameter in the `bfs` function determines whether\n * to include `null` values in the breadth-first search traversal of a binary tree. If `includeNull`\n * is set to `true`, the traversal will include `null` values for nodes that do not have children\n * (left\n * @returns The `bfs` function returns an array of values that are the result of applying the\n * provided callback function to each node in the binary tree in a breadth-first search manner.\n */\n bfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType,\n includeNull = false\n ): ReturnType<C>[] {\n startNode = this.ensureNode(startNode);\n if (!startNode) return [];\n\n const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];\n\n if (iterationType === 'RECURSIVE') {\n const queue: Queue<OptNodeOrNull<BinaryTreeNode<K, V>>> = new Queue<OptNodeOrNull<BinaryTreeNode<K, V>>>([\n startNode\n ]);\n\n const dfs = (level: number) => {\n if (queue.length === 0) return;\n\n const current = queue.shift()!;\n ans.push(callback(current));\n\n if (includeNull) {\n if (current && this.isRealNodeOrNull(current.left)) queue.push(current.left);\n if (current && this.isRealNodeOrNull(current.right)) queue.push(current.right);\n } else {\n if (this.isRealNode(current.left)) queue.push(current.left);\n if (this.isRealNode(current.right)) queue.push(current.right);\n }\n\n dfs(level + 1);\n };\n\n dfs(0);\n } else {\n const queue = new Queue<OptNodeOrNull<BinaryTreeNode<K, V>>>([startNode]);\n while (queue.length > 0) {\n const levelSize = queue.length;\n\n for (let i = 0; i < levelSize; i++) {\n const current = queue.shift()!;\n ans.push(callback(current));\n\n if (includeNull) {\n if (current && this.isRealNodeOrNull(current.left)) queue.push(current.left);\n if (current && this.isRealNodeOrNull(current.right)) queue.push(current.right);\n } else {\n if (this.isRealNode(current.left)) queue.push(current.left);\n if (this.isRealNode(current.right)) queue.push(current.right);\n }\n }\n }\n }\n return ans;\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `leaves` function in TypeScript returns an array of values from leaf nodes in a binary tree\n * structure based on a specified callback and iteration type.\n * @param {C} callback - The `callback` parameter is a function that will be called on each leaf node\n * in the binary tree. It is optional and defaults to a default callback function if not provided.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `leaves`\n * method is used to specify the starting point for finding and processing the leaves of a binary\n * tree. It can be provided as either a key, a node, or an entry in the binary tree structure. If not\n * explicitly provided, the default value\n * @param {IterationType} iterationType - The `iterationType` parameter in the `leaves` method\n * specifies the type of iteration to be performed when collecting the leaves of a binary tree. It\n * can have two possible values:\n * @returns The `leaves` method returns an array of values that are the result of applying the\n * provided callback function to each leaf node in the binary tree.\n */\n leaves<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C>[] {\n startNode = this.ensureNode(startNode);\n const leaves: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];\n if (!this.isRealNode(startNode)) return [];\n\n if (iterationType === 'RECURSIVE') {\n const dfs = (cur: BinaryTreeNode<K, V>) => {\n if (this.isLeaf(cur)) {\n leaves.push(callback(cur));\n }\n if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;\n if (this.isRealNode(cur.left)) dfs(cur.left);\n if (this.isRealNode(cur.right)) dfs(cur.right);\n };\n\n dfs(startNode);\n } else {\n const queue = new Queue([startNode]);\n while (queue.length > 0) {\n const cur = queue.shift();\n if (this.isRealNode(cur)) {\n if (this.isLeaf(cur)) {\n leaves.push(callback(cur));\n }\n if (this.isRealNode(cur.left)) queue.push(cur.left);\n if (this.isRealNode(cur.right)) queue.push(cur.right);\n }\n }\n }\n\n return leaves;\n }\n\n listLevels<C extends NodeCallback<BinaryTreeNode<K, V>>>(\n callback?: C,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType,\n includeNull?: false\n ): ReturnType<C>[][];\n\n listLevels<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback?: C,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType,\n includeNull?: true\n ): ReturnType<C>[][];\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `listLevels` function in TypeScript generates a list of nodes at each level of a binary tree,\n * using either recursive or iterative traversal based on the specified iteration type.\n * @param {C} callback - The `callback` parameter is a function that will be applied to each node in\n * the binary tree during the traversal. It is used to process each node and determine what\n * information to include in the output for each level of the tree.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `listLevels` function represents the starting point for traversing the binary tree. It can be\n * either a key, a node, or an entry in the binary tree. If not provided, the default value is the\n * root of the binary tree.\n * @param {IterationType} iterationType - The `iterationType` parameter in the `listLevels` function\n * determines the type of iteration to be performed on the binary tree nodes. It can have two\n * possible values:\n * @param [includeNull=false] - The `includeNull` parameter in the `listLevels` method determines\n * whether or not to include null nodes in the traversal of the binary tree. If `includeNull` is set\n * to `true`, the traversal will include null nodes in the levels of the tree. If set to `false`,\n * null\n * @returns The `listLevels` method returns an array of arrays, where each inner array represents a\n * level in a binary tree. Each inner array contains the return value of the provided callback\n * function applied to the nodes at that level.\n */\n listLevels<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType,\n includeNull = false\n ): ReturnType<C>[][] {\n startNode = this.ensureNode(startNode);\n const levelsNodes: ReturnType<C>[][] = [];\n if (!startNode) return levelsNodes;\n\n if (iterationType === 'RECURSIVE') {\n const _recursive = (node: BinaryTreeNode<K, V> | null, level: number) => {\n if (!levelsNodes[level]) levelsNodes[level] = [];\n levelsNodes[level].push(callback(node));\n if (includeNull) {\n if (node && this.isRealNodeOrNull(node.left)) _recursive(node.left, level + 1);\n if (node && this.isRealNodeOrNull(node.right)) _recursive(node.right, level + 1);\n } else {\n if (node && node.left) _recursive(node.left, level + 1);\n if (node && node.right) _recursive(node.right, level + 1);\n }\n };\n\n _recursive(startNode, 0);\n } else {\n const stack: [BinaryTreeNode<K, V> | null, number][] = [[startNode, 0]];\n\n while (stack.length > 0) {\n const head = stack.pop()!;\n const [node, level] = head;\n\n if (!levelsNodes[level]) levelsNodes[level] = [];\n levelsNodes[level].push(callback(node));\n\n if (includeNull) {\n if (node && this.isRealNodeOrNull(node.right)) stack.push([node.right, level + 1]);\n if (node && this.isRealNodeOrNull(node.left)) stack.push([node.left, level + 1]);\n } else {\n if (node && node.right) stack.push([node.right, level + 1]);\n if (node && node.left) stack.push([node.left, level + 1]);\n }\n }\n }\n\n return levelsNodes;\n }\n\n morris<C extends NodeCallback<BinaryTreeNode<K, V>>>(\n callback?: C,\n pattern?: DFSOrderPattern,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): ReturnType<C>[];\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `morris` function in TypeScript performs a Depth-First Search traversal on a binary tree using\n * Morris Traversal algorithm with different order patterns.\n * @param {C} callback - The `callback` parameter in the `morris` function is a function that will be\n * called on each node in the binary tree during the traversal. It is of type `C`, which extends the\n * `NodeCallback<BinaryTreeNode<K, V> | null>` type. The default value for `callback` is `this._DEFAULT\n * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `morris` function specifies\n * the type of Depth-First Search (DFS) order pattern to traverse the binary tree. The possible\n * values for the `pattern` parameter are:\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `morris`\n * function is the starting point for the Morris traversal algorithm. It represents the root node of\n * the binary tree or the node from which the traversal should begin. It can be provided as either a\n * key, a node, an entry, or a reference\n * @returns The `morris` function is returning an array of values that are the result of applying the\n * provided callback function to each node in the binary tree in the specified order pattern (IN,\n * PRE, or POST).\n */\n morris<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n pattern: DFSOrderPattern = 'IN',\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root\n ): ReturnType<C>[] {\n startNode = this.ensureNode(startNode);\n if (!startNode) return [];\n const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];\n\n let cur: BinaryTreeNode<K, V> | null | undefined = startNode;\n const _reverseEdge = (node: BinaryTreeNode<K, V> | null | undefined) => {\n let pre: BinaryTreeNode<K, V> | null | undefined = null;\n let next: BinaryTreeNode<K, V> | null | undefined = null;\n while (node) {\n next = node.right;\n node.right = pre;\n pre = node;\n node = next;\n }\n return pre;\n };\n const _printEdge = (node: BinaryTreeNode<K, V> | null | undefined) => {\n const tail: BinaryTreeNode<K, V> | null | undefined = _reverseEdge(node);\n let cur: BinaryTreeNode<K, V> | null | undefined = tail;\n while (cur) {\n ans.push(callback(cur));\n cur = cur.right;\n }\n _reverseEdge(tail);\n };\n switch (pattern) {\n case 'IN':\n while (cur) {\n if (cur.left) {\n const predecessor = this.getPredecessor(cur);\n if (!predecessor.right) {\n predecessor.right = cur;\n cur = cur.left;\n continue;\n } else {\n predecessor.right = null;\n }\n }\n ans.push(callback(cur));\n cur = cur.right;\n }\n break;\n case 'PRE':\n while (cur) {\n if (cur.left) {\n const predecessor = this.getPredecessor(cur);\n if (!predecessor.right) {\n predecessor.right = cur;\n ans.push(callback(cur));\n cur = cur.left;\n continue;\n } else {\n predecessor.right = null;\n }\n } else {\n ans.push(callback(cur));\n }\n cur = cur.right;\n }\n break;\n case 'POST':\n while (cur) {\n if (cur.left) {\n const predecessor = this.getPredecessor(cur);\n if (predecessor.right === null) {\n predecessor.right = cur;\n cur = cur.left;\n continue;\n } else {\n predecessor.right = null;\n _printEdge(cur.left);\n }\n }\n cur = cur.right;\n }\n _printEdge(startNode);\n break;\n }\n return ans;\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `clone` function creates a deep copy of a tree structure by traversing it using breadth-first\n * search.\n * @returns The `clone()` method is returning a cloned copy of the tree with the same structure and\n * values as the original tree. The method creates a new tree, iterates over the nodes of the\n * original tree using breadth-first search (bfs), and adds the nodes to the new tree. If a node in\n * the original tree is null, a null node is added to the cloned tree. If a node\n */\n clone() {\n const cloned = this.createTree();\n this._clone(cloned);\n return cloned;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function iterates over key-value pairs in a tree data structure and creates a new\n * tree with elements that satisfy a given predicate.\n * @param predicate - The `predicate` parameter in the `filter` method is a function that will be\n * called with four arguments: the `value` of the current entry, the `key` of the current entry, the\n * `index` of the current entry in the iteration, and the reference to the tree itself (`\n * @param {any} [thisArg] - The `thisArg` parameter in the `filter` method allows you to specify the\n * value of `this` that should be used when executing the `predicate` function. This is useful when\n * the `predicate` function relies on the context of a specific object or value. By providing a\n * `thisArg\n * @returns The `filter` method is returning a new tree that contains entries that pass the provided\n * predicate function.\n */\n filter(predicate: EntryCallback<K, V | undefined, boolean>, thisArg?: any) {\n const newTree = this.createTree();\n let index = 0;\n for (const [key, value] of this) {\n if (predicate.call(thisArg, key, value, index++, this)) {\n newTree.add([key, value]);\n }\n }\n return newTree;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function in TypeScript creates a new BinaryTree by applying a callback function to each\n * entry in the original BinaryTree.\n * @param callback - A function that will be called for each entry in the current binary tree. It\n * takes the key, value (which can be undefined), and an array containing the mapped key and value as\n * arguments.\n * @param [options] - The `options` parameter in the `map` method is of type `BinaryTreeOptions<MK,\n * MV, MR>`. It is an optional parameter that allows you to specify additional options for the binary\n * tree being created during the mapping process. These options could include things like custom\n * comparators, initial\n * @param {any} [thisArg] - The `thisArg` parameter in the `map` method is used to specify the value\n * of `this` when executing the `callback` function. It allows you to set the context (value of\n * `this`) within the callback function. If `thisArg` is provided, it will be passed\n * @returns The `map` function is returning a new `BinaryTree` instance filled with entries that are\n * the result of applying the provided `callback` function to each entry in the original tree.\n */\n map(\n callback: EntryCallback<K, V | undefined, [MK, MV]>,\n options?: BinaryTreeOptions<MK, MV, MR>,\n thisArg?: any\n ): BinaryTree<MK, MV, MR> {\n const newTree = new BinaryTree<MK, MV, MR>([], options);\n let index = 0;\n for (const [key, value] of this) {\n newTree.add(callback.call(thisArg, key, value, index++, this));\n }\n return newTree;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `toVisual` in TypeScript overrides the visual representation of a binary tree with\n * customizable options for displaying undefined, null, and sentinel nodes.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `toVisual` method is used to specify the starting point for visualizing the binary tree structure.\n * It can be a node, key, entry, or the root of the tree. If no specific starting point is provided,\n * the default is set to the root\n * @param {BinaryTreePrintOptions} [options] - The `options` parameter in the `toVisual` method is an\n * object that contains the following properties:\n * @returns The `override toVisual` method returns a string that represents the visual display of the\n * binary tree based on the provided options for showing undefined, null, and Red-Black NIL nodes.\n * The method constructs the visual representation by calling the `_displayAux` method and appending\n * the lines to the output string. The final output string contains the visual representation of the\n * binary tree with the specified options.\n */\n override toVisual(\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n options?: BinaryTreePrintOptions\n ): string {\n const opts = { isShowUndefined: false, isShowNull: true, isShowRedBlackNIL: false, ...options };\n startNode = this.ensureNode(startNode);\n let output = '';\n if (!startNode) return output;\n\n if (opts.isShowUndefined) output += `U for undefined\\n`;\n if (opts.isShowNull) output += `N for null\\n`;\n if (opts.isShowRedBlackNIL) output += `S for Sentinel Node(NIL)\\n`;\n\n const display = (root: BinaryTreeNode<K, V> | null | undefined): void => {\n const [lines] = this._displayAux(root, opts);\n let paragraph = '';\n for (const line of lines) {\n paragraph += line + '\\n';\n }\n output += paragraph;\n };\n\n display(startNode);\n return output;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `print` in TypeScript overrides the default print behavior to log a visual\n * representation of the binary tree to the console.\n * @param {BinaryTreePrintOptions} [options] - The `options` parameter is used to specify the\n * printing options for the binary tree. It is an optional parameter that allows you to customize how\n * the binary tree is printed, such as choosing between different traversal orders or formatting\n * options.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `override print` method is used to specify the starting point for printing the binary tree. It can\n * be either a key, a node, an entry, or the root of the tree. If no specific starting point is\n * provided, the default value is set to\n */\n override print(\n options?: BinaryTreePrintOptions,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root\n ) {\n console.log(this.toVisual(startNode, options));\n }\n\n protected _clone(cloned: BinaryTree<K, V, R, MK, MV, MR>) {\n this.bfs(\n node => {\n if (node === null) cloned.add(null);\n else {\n if (this._isMapMode) cloned.add([node.key, this._store.get(node.key)]);\n else cloned.add([node.key, node.value]);\n }\n },\n this._root,\n this.iterationType,\n true\n );\n if (this._isMapMode) cloned._store = this._store;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `keyValueNodeEntryRawToNodeAndValue` converts various input types into a node object\n * or returns null.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The\n * `keyValueNodeEntryRawToNodeAndValue` function takes in a parameter `keyNodeOrEntry`, which\n * can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. This parameter represents either a key, a\n * node, an entry\n * @param {V} [value] - The `value` parameter in the `keyValueNodeEntryRawToNodeAndValue` function is\n * an optional parameter of type `V`. It represents the value associated with the key in the node\n * being created. If a `value` is provided, it will be used when creating the node. If\n * @returns The `keyValueNodeEntryRawToNodeAndValue` function returns an optional node\n * (`BinaryTreeNode<K, V> | null | undefined`) based on the input parameters provided. The function checks the type of the\n * input parameter (`keyNodeOrEntry`) and processes it accordingly to return a node or null\n * value.\n */\n protected _keyValueNodeOrEntryToNodeAndValue(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V\n ): [BinaryTreeNode<K, V> | null | undefined, V | undefined] {\n if (keyNodeOrEntry === undefined) return [undefined, undefined];\n if (keyNodeOrEntry === null) return [null, undefined];\n\n if (this.isNode(keyNodeOrEntry)) return [keyNodeOrEntry, value];\n\n if (this.isEntry(keyNodeOrEntry)) {\n const [key, entryValue] = keyNodeOrEntry;\n if (key === undefined) return [undefined, undefined];\n else if (key === null) return [null, undefined];\n const finalValue = value ?? entryValue;\n return [this.createNode(key, finalValue), finalValue];\n }\n\n return [this.createNode(keyNodeOrEntry, value), value];\n }\n\n protected _dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(\n callback: C,\n pattern?: DFSOrderPattern,\n onlyOne?: boolean,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType,\n includeNull?: boolean,\n shouldVisitLeft?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean,\n shouldVisitRight?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean,\n shouldVisitRoot?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean,\n shouldProcessRoot?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean\n ): ReturnType<C>[];\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `_dfs` function performs a depth-first search traversal on a binary tree, with customizable\n * options for traversal order and node processing.\n * @param {C} callback - The `callback` parameter in the `_dfs` method is a function that will be\n * called on each node visited during the depth-first search traversal. It is a generic type `C` that\n * extends `NodeCallback<BinaryTreeNode<K, V> | null>`. The default value for `callback`\n * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the\n * order in which the nodes are visited during a depth-first search traversal. It can have one of the\n * following values:\n * @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `_dfs` method is a boolean flag\n * that determines whether the traversal should stop after processing a single node. If `onlyOne` is\n * set to `true`, the traversal will return as soon as a single node is processed. If it is set to\n * `false\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined}\n * startNode - The `startNode` parameter in the `_dfs` method is used to specify the starting node\n * for the depth-first search traversal. It can be provided in different forms:\n * @param {IterationType} iterationType - The `iterationType` parameter in the `_dfs` method\n * specifies whether the traversal should be done recursively or iteratively. It can have two\n * possible values:\n * @param [includeNull=false] - The `includeNull` parameter in the `_dfs` method determines whether\n * null nodes should be included in the traversal process. If `includeNull` is set to `true`, the\n * method will consider null nodes as valid nodes to visit or process. If `includeNull` is set to\n * `false`,\n * @param shouldVisitLeft - The `shouldVisitLeft` parameter in the `_dfs` method is a function that\n * determines whether the left child of a node should be visited during the Depth-First Search\n * traversal. By default, it checks if the node is not null or undefined before visiting the left\n * child. You can customize this behavior\n * @param shouldVisitRight - The `shouldVisitRight` parameter in the `_dfs` method is a function that\n * determines whether to visit the right child node of the current node during a depth-first search\n * traversal. The default implementation of this function checks if the node is not null or undefined\n * before deciding to visit it.\n * @param shouldVisitRoot - The `shouldVisitRoot` parameter in the `_dfs` method is a function that\n * determines whether a given node should be visited during the depth-first search traversal. The\n * function takes a node as an argument and returns a boolean value indicating whether the node\n * should be visited.\n * @param shouldProcessRoot - The `shouldProcessRoot` parameter in the `_dfs` method is a function\n * that determines whether the root node should be processed during the Depth-First Search traversal.\n * It takes a node (BinaryTreeNode<K, V> | null | undefined) as input and returns a boolean value. If\n * the function\n * @returns The `_dfs` method returns an array of the return type of the provided callback function\n * `C`.\n */\n protected _dfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n pattern: DFSOrderPattern = 'IN',\n onlyOne: boolean = false,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType,\n includeNull = false,\n shouldVisitLeft: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => !!node,\n shouldVisitRight: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => !!node,\n shouldVisitRoot: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => {\n if (includeNull) return this.isRealNodeOrNull(node);\n return this.isRealNode(node);\n },\n shouldProcessRoot: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => this.isRealNodeOrNull(node)\n ): ReturnType<C>[] {\n startNode = this.ensureNode(startNode);\n if (!startNode) return [];\n const ans: ReturnType<C>[] = [];\n\n if (iterationType === 'RECURSIVE') {\n const dfs = (node: BinaryTreeNode<K, V> | null) => {\n if (!shouldVisitRoot(node)) return;\n\n const visitLeft = () => {\n if (shouldVisitLeft(node) && node?.left !== undefined) dfs(node?.left);\n };\n const visitRight = () => {\n if (shouldVisitRight(node) && node?.right !== undefined) dfs(node?.right);\n };\n\n switch (pattern) {\n case 'IN':\n visitLeft();\n if (shouldProcessRoot(node)) {\n ans.push(callback(node));\n if (onlyOne) return;\n }\n visitRight();\n break;\n case 'PRE':\n if (shouldProcessRoot(node)) {\n ans.push(callback(node));\n if (onlyOne) return;\n }\n visitLeft();\n visitRight();\n break;\n case 'POST':\n visitLeft();\n visitRight();\n if (shouldProcessRoot(node)) {\n ans.push(callback(node));\n if (onlyOne) return;\n }\n break;\n }\n };\n\n dfs(startNode);\n } else {\n const stack: DFSStackItem<BinaryTreeNode<K, V>>[] = [{ opt: DFSOperation.VISIT, node: startNode }];\n\n const pushLeft = (cur: DFSStackItem<BinaryTreeNode<K, V>>) => {\n if (shouldVisitLeft(cur.node)) stack.push({ opt: DFSOperation.VISIT, node: cur.node?.left });\n };\n const pushRight = (cur: DFSStackItem<BinaryTreeNode<K, V>>) => {\n if (shouldVisitRight(cur.node)) stack.push({ opt: DFSOperation.VISIT, node: cur.node?.right });\n };\n const pushRoot = (cur: DFSStackItem<BinaryTreeNode<K, V>>) => {\n if (shouldVisitRoot(cur.node)) stack.push({ opt: DFSOperation.PROCESS, node: cur.node });\n };\n\n while (stack.length > 0) {\n const cur = stack.pop();\n if (cur === undefined) continue;\n if (!shouldVisitRoot(cur.node)) continue;\n if (cur.opt === DFSOperation.PROCESS) {\n if (shouldProcessRoot(cur.node) && cur.node !== undefined) {\n ans.push(callback(cur.node));\n if (onlyOne) return ans;\n }\n } else {\n switch (pattern) {\n case 'IN':\n pushRight(cur);\n pushRoot(cur);\n pushLeft(cur);\n break;\n case 'PRE':\n pushRight(cur);\n pushLeft(cur);\n pushRoot(cur);\n break;\n case 'POST':\n pushRoot(cur);\n pushRight(cur);\n pushLeft(cur);\n break;\n }\n }\n }\n }\n\n return ans;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_getIterator` returns an iterable iterator for a binary tree data structure, either\n * using an iterative approach or a recursive approach based on the specified iteration type.\n * @param node - The `node` parameter in the `_getIterator` method represents the current node being\n * processed during iteration. It is initially set to the root node of the data structure (or the\n * node passed as an argument), and then it is traversed through the data structure based on the\n * iteration type specified (`ITER\n * @returns The `_getIterator` method returns an IterableIterator containing key-value pairs of nodes\n * in a binary tree structure. The method uses an iterative approach to traverse the tree based on\n * the `iterationType` property. If the `iterationType` is set to 'ITERATIVE', the method uses a\n * stack to perform an in-order traversal of the tree. If the `iterationType` is not 'ITERATIVE\n */\n protected *_getIterator(node = this._root): IterableIterator<[K, V | undefined]> {\n if (!node) return;\n\n if (this.iterationType === 'ITERATIVE') {\n const stack: (BinaryTreeNode<K, V> | null | undefined)[] = [];\n let current: BinaryTreeNode<K, V> | null | undefined = node;\n\n while (current || stack.length > 0) {\n while (this.isRealNode(current)) {\n stack.push(current);\n current = current.left;\n }\n\n current = stack.pop();\n\n if (this.isRealNode(current)) {\n if (this._isMapMode) yield [current.key, this._store.get(current.key)];\n else yield [current.key, current.value];\n current = current.right;\n }\n }\n } else {\n if (node.left && this.isRealNode(node)) {\n yield* this[Symbol.iterator](node.left);\n }\n if (this._isMapMode) yield [node.key, this._store.get(node.key)];\n else yield [node.key, node.value];\n if (node.right && this.isRealNode(node)) {\n yield* this[Symbol.iterator](node.right);\n }\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `_displayAux` in TypeScript is responsible for generating the display layout of nodes\n * in a binary tree based on specified options.\n * @param node - The `node` parameter in the `_displayAux` function represents a node in a binary\n * tree. It can be either a valid node containing a key or a special type of node like null,\n * undefined, or a Red-Black tree NIL node. The function checks the type of the node and its\n * @param {BinaryTreePrintOptions} options - The `options` parameter in the `_displayAux` function\n * contains the following properties:\n * @returns The `_displayAux` function returns a `NodeDisplayLayout`, which is an array containing\n * information about how to display a node in a binary tree. The `NodeDisplayLayout` consists of four\n * elements:\n */\n protected _displayAux(\n node: BinaryTreeNode<K, V> | null | undefined,\n options: BinaryTreePrintOptions\n ): NodeDisplayLayout {\n const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;\n const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];\n\n // Check if node is null or undefined or key is NaN\n if (node === null && !isShowNull) {\n return emptyDisplayLayout;\n } else if (node === undefined && !isShowUndefined) {\n return emptyDisplayLayout;\n } else if (this.isNIL(node) && !isShowRedBlackNIL) {\n return emptyDisplayLayout;\n } else if (node !== null && node !== undefined) {\n // Display logic of normal nodes\n\n const key = node.key,\n line = this.isNIL(node) ? 'S' : String(key),\n width = line.length;\n\n return _buildNodeDisplay(\n line,\n width,\n this._displayAux(node.left, options),\n this._displayAux(node.right, options)\n );\n } else {\n // For cases where none of the conditions are met, null, undefined, and NaN nodes are not displayed\n const line = node === undefined ? 'U' : 'N',\n width = line.length;\n\n return _buildNodeDisplay(line, width, [[''], 1, 0, 0], [[''], 1, 0, 0]);\n }\n\n function _buildNodeDisplay(line: string, width: number, left: NodeDisplayLayout, right: NodeDisplayLayout) {\n const [leftLines, leftWidth, leftHeight, leftMiddle] = left;\n const [rightLines, rightWidth, rightHeight, rightMiddle] = right;\n const firstLine =\n ' '.repeat(Math.max(0, leftMiddle + 1)) +\n '_'.repeat(Math.max(0, leftWidth - leftMiddle - 1)) +\n line +\n '_'.repeat(Math.max(0, rightMiddle)) +\n ' '.repeat(Math.max(0, rightWidth - rightMiddle));\n\n const secondLine =\n (leftHeight > 0\n ? ' '.repeat(leftMiddle) + '/' + ' '.repeat(leftWidth - leftMiddle - 1)\n : ' '.repeat(leftWidth)) +\n ' '.repeat(width) +\n (rightHeight > 0\n ? ' '.repeat(rightMiddle) + '\\\\' + ' '.repeat(rightWidth - rightMiddle - 1)\n : ' '.repeat(rightWidth));\n\n const mergedLines = [firstLine, secondLine];\n\n for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {\n const leftLine = i < leftHeight ? leftLines[i] : ' '.repeat(leftWidth);\n const rightLine = i < rightHeight ? rightLines[i] : ' '.repeat(rightWidth);\n mergedLines.push(leftLine + ' '.repeat(width) + rightLine);\n }\n\n return <NodeDisplayLayout>[\n mergedLines,\n leftWidth + width + rightWidth,\n Math.max(leftHeight, rightHeight) + 2,\n leftWidth + Math.floor(width / 2)\n ];\n }\n }\n\n protected _DEFAULT_NODE_CALLBACK = (node: BinaryTreeNode<K, V> | null | undefined) => (node ? node.key : undefined);\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The _swapProperties function swaps key and value properties between two nodes in a binary tree.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } srcNode - The `srcNode` parameter in the\n * `_swapProperties` method can be either a BTNRep object containing key and value\n * properties, or it can be of type R.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } destNode - The `destNode` parameter in the\n * `_swapProperties` method represents the node or entry where the properties will be swapped with\n * the `srcNode`. It can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. The method ensures that\n * both `srcNode\n * @returns The `_swapProperties` method returns either the `destNode` with its key and value swapped\n * with the `srcNode`, or `undefined` if either `srcNode` or `destNode` is falsy.\n */\n protected _swapProperties(\n srcNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n destNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): BinaryTreeNode<K, V> | undefined {\n srcNode = this.ensureNode(srcNode);\n destNode = this.ensureNode(destNode);\n\n if (srcNode && destNode) {\n const { key, value } = destNode;\n const tempNode = this.createNode(key, value);\n\n if (tempNode) {\n destNode.key = srcNode.key;\n if (!this._isMapMode) destNode.value = srcNode.value;\n\n srcNode.key = tempNode.key;\n if (!this._isMapMode) srcNode.value = tempNode.value;\n }\n\n return destNode;\n }\n return undefined;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The _replaceNode function replaces an old node with a new node in a binary tree structure.\n * @param {BinaryTreeNode<K, V>} oldNode - The `oldNode` parameter represents the node that you want to replace in a\n * tree data structure.\n * @param {BinaryTreeNode<K, V>} newNode - The `newNode` parameter in the `_replaceNode` function represents the node\n * that will replace the `oldNode` in a tree data structure. This function is responsible for\n * updating the parent, left child, right child, and root (if necessary) references when replacing a\n * node in the tree.\n * @returns The method `_replaceNode` is returning the `newNode` that was passed as a parameter after\n * replacing the `oldNode` with it in the binary tree structure.\n */\n protected _replaceNode(oldNode: BinaryTreeNode<K, V>, newNode: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> {\n if (oldNode.parent) {\n if (oldNode.parent.left === oldNode) {\n oldNode.parent.left = newNode;\n } else if (oldNode.parent.right === oldNode) {\n oldNode.parent.right = newNode;\n }\n }\n newNode.left = oldNode.left;\n newNode.right = oldNode.right;\n newNode.parent = oldNode.parent;\n if (this._root === oldNode) {\n this._setRoot(newNode);\n }\n\n return newNode;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function _setRoot sets the root node of a data structure while updating the parent reference\n * of the previous root node.\n * @param v - The parameter `v` in the `_setRoot` method is of type `BinaryTreeNode<K, V> | null | undefined`, which means\n * it can either be an optional `BinaryTreeNode<K, V>` type or `null`.\n */\n protected _setRoot(v: BinaryTreeNode<K, V> | null | undefined) {\n if (v) {\n v.parent = undefined;\n }\n this._root = v;\n }\n\n protected _ensurePredicate(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V>>\n ): NodePredicate<BinaryTreeNode<K, V>>;\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_ensurePredicate` in TypeScript ensures that the input is converted into a valid\n * predicate function for a binary tree node.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The\n * `_ensurePredicate` method in the provided code snippet is responsible for ensuring that the input\n * parameter `keyNodeEntryOrPredicate` is transformed into a valid predicate function that can be\n * used for filtering nodes in a binary tree.\n * @returns A NodePredicate<BinaryTreeNode<K, V>> function is being returned.\n */\n protected _ensurePredicate(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V> | null>\n ): NodePredicate<BinaryTreeNode<K, V> | null> {\n if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined)\n return (node: BinaryTreeNode<K, V> | null | undefined) => (node ? false : false);\n\n if (this._isPredicate(keyNodeEntryOrPredicate)) return keyNodeEntryOrPredicate;\n\n if (this.isRealNode(keyNodeEntryOrPredicate))\n return (node: BinaryTreeNode<K, V> | null) => node === keyNodeEntryOrPredicate;\n\n if (this.isEntry(keyNodeEntryOrPredicate)) {\n const [key] = keyNodeEntryOrPredicate;\n return (node: BinaryTreeNode<K, V> | null) => {\n if (!node) return false;\n return node.key === key;\n };\n }\n\n return (node: BinaryTreeNode<K, V> | null) => {\n if (!node) return false;\n return node.key === keyNodeEntryOrPredicate;\n };\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_isPredicate` checks if a given parameter is a function.\n * @param {any} p - The parameter `p` is a variable of type `any`, which means it can hold any type\n * of value. In this context, the function `_isPredicate` is checking if `p` is a function that\n * satisfies the type `NodePredicate<BinaryTreeNode<K, V>>`.\n * @returns The function is checking if the input `p` is a function and returning a boolean value\n * based on that check. If `p` is a function, it will return `true`, indicating that `p` is a\n * predicate function for a binary tree node. If `p` is not a function, it will return `false`.\n */\n protected _isPredicate(p: any): p is NodePredicate<BinaryTreeNode<K, V>> {\n return typeof p === 'function';\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_extractKey` in TypeScript returns the key from a given input, which can be a node,\n * entry, raw data, or null/undefined.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `_extractKey` method you provided is a\n * TypeScript method that takes in a parameter `keyNodeOrEntry` of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `,\n * where `BTNRep` is a generic type with keys `K`, `V`, and `BinaryTreeNode<K, V>`, and `\n * @returns The `_extractKey` method returns the key value extracted from the `keyNodeOrEntry`\n * parameter. The return value can be a key value of type `K`, `null`, or `undefined`, depending on\n * the conditions checked in the method.\n */\n protected _extractKey(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): K | null | undefined {\n if (keyNodeOrEntry === null) return null;\n if (keyNodeOrEntry === undefined) return;\n if (keyNodeOrEntry === this._NIL) return;\n if (this.isNode(keyNodeOrEntry)) return keyNodeOrEntry.key;\n\n if (this.isEntry(keyNodeOrEntry)) return keyNodeOrEntry[0];\n\n return keyNodeOrEntry;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_setValue` sets a value in a store based on a key, handling cases where the key or\n * value is null or undefined.\n * @param {K | null | undefined} key - The `key` parameter can be of type `K`, `null`, or\n * `undefined`.\n * @param {V | undefined} value - The `value` parameter in the `_setValue` method can be of type `V`\n * or `undefined`.\n * @returns The method `_setValue` returns `false` if either the `key` is `null` or `undefined`, or\n * if the `value` is `undefined`. Otherwise, it returns the result of calling the `set` method on the\n * `_store` object with the `key` and `value` arguments.\n */\n protected _setValue(key: K | null | undefined, value: V | undefined) {\n if (key === null || key === undefined) return false;\n if (value === undefined) return false;\n return this._store.set(key, value);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The _clearNodes function sets the root node to undefined and resets the size to 0.\n */\n protected _clearNodes() {\n this._setRoot(undefined);\n this._size = 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The _clearValues function clears all values stored in the _store object.\n */\n protected _clearValues() {\n this._store.clear();\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type {\n BSTNOptKeyOrNode,\n BSTOptions,\n BTNRep,\n Comparable,\n Comparator,\n CP,\n DFSOrderPattern,\n EntryCallback,\n IterationType,\n NodeCallback,\n NodePredicate,\n OptNode\n} from '../../types';\nimport { BinaryTree, BinaryTreeNode } from './binary-tree';\nimport { IBinaryTree } from '../../interfaces';\nimport { Queue } from '../queue';\nimport { isComparable } from '../../utils';\nimport { Range } from '../../common';\n\nexport class BSTNode<K = any, V = any> extends BinaryTreeNode<K, V> {\n override parent?: BSTNode<K, V> = undefined;\n\n /**\n * This TypeScript constructor function initializes an instance with a key and an optional value.\n * @param {K} key - The `key` parameter is typically used to uniquely identify an object or element\n * within a data structure. It serves as a reference or identifier for accessing or manipulating the\n * associated value.\n * @param {V} [value] - The `value` parameter in the constructor is optional, meaning it does not\n * have to be provided when creating an instance of the class. If a value is not provided, it will\n * default to `undefined`.\n */\n constructor(key: K, value?: V) {\n super(key, value);\n }\n\n override _left?: BSTNode<K, V> | null | undefined = undefined;\n\n override get left(): BSTNode<K, V> | null | undefined {\n return this._left;\n }\n\n override set left(v: BSTNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._left = v;\n }\n\n override _right?: BSTNode<K, V> | null | undefined = undefined;\n\n override get right(): BSTNode<K, V> | null | undefined {\n return this._right;\n }\n\n override set right(v: BSTNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n}\n\n/**\n * 1. Node Order: Each node's left child has a lesser value, and the right child has a greater value.\n * 2. Unique Keys: No duplicate keys in a standard BST.\n * 3. Efficient Search: Enables quick search, minimum, and maximum operations.\n * 4. Inorder Traversal: Yields nodes in ascending order.\n * 5. Logarithmic Operations: Ideal operations like insertion, deletion, and searching are O(log n) time-efficient.\n * 6. Balance Variability: Can become unbalanced; special types maintain balance.\n * 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.\n * @example\n * // Merge 3 sorted datasets\n * const dataset1 = new BST<number, string>([\n * [1, 'A'],\n * [7, 'G']\n * ]);\n * const dataset2 = [\n * [2, 'B'],\n * [6, 'F']\n * ];\n * const dataset3 = new BST<number, string>([\n * [3, 'C'],\n * [5, 'E'],\n * [4, 'D']\n * ]);\n *\n * // Merge datasets into a single BinarySearchTree\n * const merged = new BST<number, string>(dataset1);\n * merged.addMany(dataset2);\n * merged.merge(dataset3);\n *\n * // Verify merged dataset is in sorted order\n * console.log([...merged.values()]); // ['A', 'B', 'C', 'D', 'E', 'F', 'G']\n * @example\n * // Find elements in a range\n * const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);\n * console.log(bst.search(new Range(5, 10))); // [5, 7, 10]\n * console.log(bst.rangeSearch([4, 12], node => node.key.toString())); // ['5', '7', '10', '12']\n * console.log(bst.search(new Range(4, 12, true, false))); // [5, 7, 10]\n * console.log(bst.rangeSearch([15, 20])); // [15, 18]\n * console.log(bst.search(new Range(15, 20, false))); // [18]\n * @example\n * // Find lowest common ancestor\n * const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);\n *\n * // LCA helper function\n * const findLCA = (num1: number, num2: number): number | undefined => {\n * const path1 = bst.getPathToRoot(num1);\n * const path2 = bst.getPathToRoot(num2);\n * // Find the first common ancestor\n * return findFirstCommon(path1, path2);\n * };\n *\n * function findFirstCommon(arr1: number[], arr2: number[]): number | undefined {\n * for (const num of arr1) {\n * if (arr2.indexOf(num) !== -1) {\n * return num;\n * }\n * }\n * return undefined;\n * }\n *\n * // Assertions\n * console.log(findLCA(3, 10)); // 7\n * console.log(findLCA(5, 35)); // 15\n * console.log(findLCA(20, 30)); // 25\n */\nexport class BST<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends BinaryTree<K, V, R, MK, MV, MR>\n implements IBinaryTree<K, V, R, MK, MV, MR>\n{\n /**\n * This TypeScript constructor initializes a binary search tree with optional options and adds\n * elements if provided.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an\n * iterable that can contain elements of type `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It is used to\n * initialize the binary search tree with keys, nodes, entries, or raw data.\n * @param [options] - The `options` parameter is an optional object that can contain the following\n * properties:\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n > = [],\n options?: BSTOptions<K, V, R>\n ) {\n super([], options);\n\n if (options) {\n const { specifyComparable, isReverse } = options;\n if (typeof specifyComparable === 'function') this._specifyComparable = specifyComparable;\n if (isReverse !== undefined) this._isReverse = isReverse;\n }\n\n if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);\n }\n\n protected override _root?: BSTNode<K, V> = undefined;\n\n override get root(): OptNode<BSTNode<K, V>> {\n return this._root;\n }\n\n protected _isReverse: boolean = false;\n\n get isReverse(): boolean {\n return this._isReverse;\n }\n\n protected _comparator: Comparator<K> = (a: K, b: K): number => {\n if (isComparable(a) && isComparable(b)) {\n if (a > b) return 1;\n if (a < b) return -1;\n return 0;\n }\n if (this._specifyComparable) {\n if (this._specifyComparable(a) > this._specifyComparable(b)) return 1;\n if (this._specifyComparable(a) < this._specifyComparable(b)) return -1;\n return 0;\n }\n if (typeof a === 'object' || typeof b === 'object') {\n throw TypeError(\n `When comparing object types, a custom specifyComparable must be defined in the constructor's options parameter.`\n );\n }\n\n return 0;\n };\n\n get comparator() {\n return this._comparator;\n }\n\n protected _specifyComparable?: (key: K) => Comparable;\n\n get specifyComparable() {\n return this._specifyComparable;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a new BSTNode with the given key and value and returns it.\n * @param {K} key - The key parameter is of type K, which represents the type of the key for the node\n * being created.\n * @param {V} [value] - The \"value\" parameter is an optional parameter of type V. It represents the\n * value associated with the key in the node being created.\n * @returns The method is returning a new instance of the BSTNode class, casted as the BSTNode<K, V> type.\n */\n override createNode(key: K, value?: V): BSTNode<K, V> {\n return new BSTNode<K, V>(key, this._isMapMode ? undefined : value);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a new binary search tree with the specified options.\n * @param [options] - The `options` parameter is an optional object that allows you to customize the\n * behavior of the `createTree` method. It accepts a partial `BSTOptions` object, which has the\n * following properties:\n * @returns a new instance of the BST class with the provided options.\n */\n override createTree(options?: BSTOptions<K, V, R>) {\n return new BST<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n isMapMode: this._isMapMode,\n specifyComparable: this._specifyComparable,\n toEntryFn: this._toEntryFn,\n isReverse: this._isReverse,\n ...options\n });\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function ensures the existence of a node in a data structure and returns it, or undefined if\n * it doesn't exist.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can accept a value of type `R`, which represents the key, node,\n * entry, or raw element that needs to be ensured in the tree.\n * @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional\n * parameter that specifies the type of iteration to be used when ensuring a node. It has a default\n * value of `'ITERATIVE'`.\n * @returns The method is returning either the node that was ensured or `undefined` if the node could\n * not be ensured.\n */\n override ensureNode(\n keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType: IterationType = this.iterationType\n ): OptNode<BSTNode<K, V>> {\n return super.ensureNode(keyNodeOrEntry, iterationType) ?? undefined;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if the input is an instance of the BSTNode class.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be of type `R` or `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.\n * @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is\n * an instance of the `BSTNode` class.\n */\n override isNode(\n keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is BSTNode<K, V> {\n return keyNodeOrEntry instanceof BSTNode;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"override isValidKey\" checks if a key is comparable based on a given comparator.\n * @param {any} key - The `key` parameter is a value that will be checked to determine if it is of\n * type `K`.\n * @returns The `override isValidKey(key: any): key is K` function is returning a boolean value based on\n * the result of the `isComparable` function with the condition `this._compare !==\n * this._DEFAULT_COMPARATOR`.\n */\n override isValidKey(key: any): key is K {\n return isComparable(key, this._specifyComparable !== undefined);\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The `add` function in TypeScript adds a new node to a binary search tree based on the key value.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can accept a value of type `R` or `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.\n * @param {V} [value] - The `value` parameter is an optional value that can be associated with the\n * key in the binary search tree. If provided, it will be stored in the node along with the key.\n * @returns a boolean value.\n */\n override add(\n keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V\n ): boolean {\n const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);\n if (newNode === undefined) return false;\n\n if (this._root === undefined) {\n this._setRoot(newNode);\n if (this._isMapMode) this._setValue(newNode?.key, newValue);\n this._size++;\n return true;\n }\n\n let current = this._root;\n while (current !== undefined) {\n if (this._compare(current.key, newNode.key) === 0) {\n this._replaceNode(current, newNode);\n if (this._isMapMode) this._setValue(current.key, newValue);\n return true;\n } else if (this._compare(current.key, newNode.key) > 0) {\n if (current.left === undefined) {\n current.left = newNode;\n if (this._isMapMode) this._setValue(newNode?.key, newValue);\n this._size++;\n return true;\n }\n if (current.left !== null) current = current.left;\n } else {\n if (current.right === undefined) {\n current.right = newNode;\n if (this._isMapMode) this._setValue(newNode?.key, newValue);\n this._size++;\n return true;\n }\n if (current.right !== null) current = current.right;\n }\n }\n\n return false;\n }\n\n /**\n * Time Complexity: O(k log n)\n * Space Complexity: O(k + log n)\n *\n * The `addMany` function in TypeScript adds multiple keys or nodes to a data structure and returns\n * an array indicating whether each key or node was successfully inserted.\n * @param keysNodesEntriesOrRaws - An iterable containing keys, nodes, entries, or raw\n * elements to be added to the data structure.\n * @param [values] - An optional iterable of values to be associated with the keys or nodes being\n * added. If provided, the values will be assigned to the corresponding keys or nodes in the same\n * order. If not provided, undefined will be assigned as the value for each key or node.\n * @param [isBalanceAdd=true] - A boolean flag indicating whether the tree should be balanced after\n * adding the elements. If set to true, the tree will be balanced using a binary search tree\n * algorithm. If set to false, the elements will be added without balancing the tree. The default\n * value is true.\n * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that\n * specifies the type of iteration to use when adding multiple keys or nodes to the binary search\n * tree. It can have two possible values:\n * @returns The function `addMany` returns an array of booleans indicating whether each element was\n * successfully inserted into the data structure.\n */\n override addMany(\n keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, BSTNode<K, V>>>,\n values?: Iterable<V | undefined>,\n isBalanceAdd = true,\n iterationType: IterationType = this.iterationType\n ): boolean[] {\n const inserted: boolean[] = [];\n\n let valuesIterator: Iterator<V | undefined> | undefined;\n\n if (values) {\n valuesIterator = values[Symbol.iterator]();\n }\n\n if (!isBalanceAdd) {\n for (let kve of keysNodesEntriesOrRaws) {\n const value = valuesIterator?.next().value;\n if (this.isRaw(kve)) kve = this._toEntryFn!(kve);\n inserted.push(this.add(kve, value));\n }\n return inserted;\n }\n\n const realBTNExemplars: {\n key: R | K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined;\n value: V | undefined;\n orgIndex: number;\n }[] = [];\n\n let i = 0;\n for (const kve of keysNodesEntriesOrRaws) {\n realBTNExemplars.push({ key: kve, value: valuesIterator?.next().value, orgIndex: i });\n i++;\n }\n\n let sorted: {\n key: R | K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined;\n value: V | undefined;\n orgIndex: number;\n }[] = [];\n\n sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => {\n let keyA: K | undefined | null, keyB: K | undefined | null;\n if (this.isRaw(a)) keyA = this._toEntryFn!(a)[0];\n else if (this.isEntry(a)) keyA = a[0];\n else if (this.isRealNode(a)) keyA = a.key;\n else {\n keyA = a as K;\n }\n\n if (this.isRaw(b)) keyB = this._toEntryFn!(b)[0];\n else if (this.isEntry(b)) keyB = b[0];\n else if (this.isRealNode(b)) keyB = b.key;\n else {\n keyB = b as K;\n }\n\n if (keyA !== undefined && keyA !== null && keyB !== undefined && keyB !== null) {\n return this._compare(keyA, keyB);\n }\n return 0;\n });\n\n const _dfs = (\n arr: {\n key: R | K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined;\n value: V | undefined;\n orgIndex: number;\n }[]\n ) => {\n if (arr.length === 0) return;\n\n const mid = Math.floor((arr.length - 1) / 2);\n const { key, value } = arr[mid];\n const { orgIndex } = arr[mid];\n if (this.isRaw(key)) {\n const entry = this._toEntryFn!(key);\n inserted[orgIndex] = this.add(entry);\n } else {\n inserted[orgIndex] = this.add(key, value);\n }\n _dfs(arr.slice(0, mid));\n _dfs(arr.slice(mid + 1));\n };\n\n const _iterate = () => {\n const n = sorted.length;\n const stack: [[number, number]] = [[0, n - 1]];\n while (stack.length > 0) {\n const popped = stack.pop();\n if (popped) {\n const [l, r] = popped;\n if (l <= r) {\n const m = l + Math.floor((r - l) / 2);\n const { key, value } = sorted[m];\n const { orgIndex } = sorted[m];\n if (this.isRaw(key)) {\n const entry = this._toEntryFn!(key);\n inserted[orgIndex] = this.add(entry);\n } else {\n inserted[orgIndex] = this.add(key, value);\n }\n stack.push([m + 1, r]);\n stack.push([l, m - 1]);\n }\n }\n }\n };\n\n if (iterationType === 'RECURSIVE') {\n _dfs(sorted);\n } else {\n _iterate();\n }\n\n return inserted;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(k + log n)\n *\n * The function `search` in TypeScript overrides the search behavior in a binary tree structure based\n * on specified criteria.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BSTNode<K, V>>} keyNodeEntryOrPredicate - The\n * `keyNodeEntryOrPredicate` parameter in the `override search` method can accept one of the\n * following types:\n * @param [onlyOne=false] - The `onlyOne` parameter is a boolean flag that determines whether the\n * search should stop after finding the first matching node. If `onlyOne` is set to `true`, the\n * search will return as soon as a matching node is found. If `onlyOne` is set to `false`, the\n * @param {C} callback - The `callback` parameter in the `override search` function is a function\n * that will be called on each node that matches the search criteria. It is of type `C`, which\n * extends `NodeCallback<BSTNode<K, V> | null>`. The callback function should accept a node of type `BSTNode<K, V>` as its\n * argument and\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `override search`\n * method represents the node from which the search operation will begin. It is the starting point\n * for searching within the tree data structure. The method ensures that the `startNode` is a valid\n * node before proceeding with the search operation. If the `\n * @param {IterationType} iterationType - The `iterationType` parameter in the `override search`\n * function determines the type of iteration to be used during the search operation. It can have two\n * possible values:\n * @returns The `override search` method returns an array of values that match the search criteria\n * specified by the input parameters. The method performs a search operation on a binary tree\n * structure based on the provided key, predicate, and other options. The search results are\n * collected in an array and returned as the output of the method.\n */\n override search<C extends NodeCallback<BSTNode<K, V>>>(\n keyNodeEntryOrPredicate:\n | K\n | BSTNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BSTNode<K, V>>\n | Range<K>,\n onlyOne = false,\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C>[] {\n if (keyNodeEntryOrPredicate === undefined) return [];\n if (keyNodeEntryOrPredicate === null) return [];\n startNode = this.ensureNode(startNode);\n if (!startNode) return [];\n let predicate: NodePredicate<BSTNode<K, V>>;\n\n const isRange = this.isRange(keyNodeEntryOrPredicate);\n // Set predicate based on parameter type\n if (isRange) {\n predicate = node => {\n if (!node) return false;\n return keyNodeEntryOrPredicate.isInRange(node.key, this._comparator);\n };\n } else {\n predicate = this._ensurePredicate(keyNodeEntryOrPredicate);\n }\n const shouldVisitLeft = (cur: BSTNode<K, V> | null | undefined) => {\n if (!cur) return false;\n if (!this.isRealNode(cur.left)) return false;\n if (isRange) {\n const range = keyNodeEntryOrPredicate;\n const leftS = this.isReverse ? range.high : range.low;\n const leftI = this.isReverse ? range.includeHigh : range.includeLow;\n return (leftI && this._compare(cur.key, leftS) >= 0) || (!leftI && this._compare(cur.key, leftS) > 0);\n }\n if (!isRange && !this._isPredicate(keyNodeEntryOrPredicate)) {\n const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);\n return benchmarkKey !== null && benchmarkKey !== undefined && this._compare(cur.key, benchmarkKey) > 0;\n }\n return true;\n };\n\n const shouldVisitRight = (cur: BSTNode<K, V> | null | undefined) => {\n if (!cur) return false;\n if (!this.isRealNode(cur.right)) return false;\n if (isRange) {\n const range = keyNodeEntryOrPredicate;\n const rightS = this.isReverse ? range.low : range.high;\n const rightI = this.isReverse ? range.includeLow : range.includeLow;\n\n return (rightI && this._compare(cur.key, rightS) <= 0) || (!rightI && this._compare(cur.key, rightS) < 0);\n }\n if (!isRange && !this._isPredicate(keyNodeEntryOrPredicate)) {\n const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);\n return benchmarkKey !== null && benchmarkKey !== undefined && this._compare(cur.key, benchmarkKey) < 0;\n }\n return true;\n };\n return super._dfs(\n callback,\n 'IN',\n onlyOne,\n startNode,\n iterationType,\n false,\n shouldVisitLeft,\n shouldVisitRight,\n () => true,\n cur => {\n if (cur) return predicate(cur);\n return false;\n }\n );\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(k + log n)\n *\n * The `rangeSearch` function searches for nodes within a specified range in a binary search tree.\n * @param {Range<K> | [K, K]} range - The `range` parameter in the `rangeSearch` function can be\n * either a `Range` object or an array of two elements representing the range boundaries.\n * @param {C} callback - The `callback` parameter in the `rangeSearch` function is a callback\n * function that is used to process each node that is found within the specified range during the\n * search operation. It is of type `NodeCallback<BSTNode<K, V> | null>`, where `BSTNode<K, V>` is the type of nodes in the\n * data structure.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `rangeSearch`\n * function represents the node from which the search for nodes within the specified range will\n * begin. It is the starting point for the range search operation.\n * @param {IterationType} iterationType - The `iterationType` parameter in the `rangeSearch` function\n * is used to specify the type of iteration to be performed during the search operation. It has a\n * default value of `this.iterationType`, which suggests that it is likely a property of the class or\n * object that the `rangeSearch`\n * @returns The `rangeSearch` function is returning the result of calling the `search` method with\n * the specified parameters.\n */\n rangeSearch<C extends NodeCallback<BSTNode<K, V>>>(\n range: Range<K> | [K, K],\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ) {\n const searchRange: Range<K> = range instanceof Range ? range : new Range(range[0], range[1]);\n return this.search(searchRange, false, callback, startNode, iterationType);\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * This function retrieves a node based on a given keyNodeEntryOrPredicate within a binary search tree structure.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BSTNode<K, V>>} keyNodeEntryOrPredicate - The `keyNodeEntryOrPredicate`\n * parameter can be of type `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `, `R`, or `NodePredicate<BSTNode<K, V>>`.\n * @param {BSTNOptKeyOrNode<K, BSTNode<K, V>>} startNode - The `startNode` parameter in the `getNode` method\n * is used to specify the starting point for searching nodes in the binary search tree. If no\n * specific starting point is provided, the default value is set to `this._root`, which is the root\n * node of the binary search tree.\n * @param {IterationType} iterationType - The `iterationType` parameter in the `getNode` method is a\n * parameter that specifies the type of iteration to be used. It has a default value of\n * `this.iterationType`, which means it will use the iteration type defined in the class instance if\n * no value is provided when calling the method.\n * @returns The `getNode` method is returning an optional binary search tree node (`OptNode<BSTNode<K, V>>`).\n * It is using the `getNodes` method to find the node based on the provided keyNodeEntryOrPredicate, beginning at\n * the specified root node (`startNode`) and using the specified iteration type. The method then\n * returns the first node found or `undefined` if no node is found.\n */\n override getNode(\n keyNodeEntryOrPredicate:\n | K\n | BSTNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BSTNode<K, V>>,\n startNode: BSTNOptKeyOrNode<K, BSTNode<K, V>> = this._root,\n iterationType: IterationType = this.iterationType\n ): OptNode<BSTNode<K, V>> {\n return this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0] ?? undefined;\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The function `dfs` in TypeScript overrides the base class method with default parameters and\n * returns the result of the super class `dfs` method.\n * @param {C} callback - The `callback` parameter is a function that will be called for each node\n * visited during the Depth-First Search traversal. It is a generic type `C` that extends the\n * `NodeCallback` interface for `BSTNode<K, V>`. The default value for `callback` is `this._\n * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `override dfs` method\n * specifies the order in which the Depth-First Search (DFS) traversal should be performed on the\n * Binary Search Tree (BST). The possible values for the `pattern` parameter are:\n * @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `override dfs` method is a\n * boolean flag that indicates whether you want to stop the depth-first search traversal after\n * finding the first matching node or continue searching for all matching nodes. If `onlyOne` is set\n * to `true`, the traversal will stop after finding\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} startNode -\n * The `startNode` parameter in the `override dfs` method can be one of the following types:\n * @param {IterationType} iterationType - The `iterationType` parameter in the `override dfs` method\n * specifies the type of iteration to be performed during the Depth-First Search (DFS) traversal of a\n * Binary Search Tree (BST). It is used to determine the order in which nodes are visited during the\n * traversal. The possible values for `\n * @returns The `override` function is returning the result of calling the `dfs` method from the\n * superclass, with the provided arguments `callback`, `pattern`, `onlyOne`, `startNode`, and\n * `iterationType`. The return type is an array of the return type of the callback function `C`.\n */\n override dfs<C extends NodeCallback<BSTNode<K, V>>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n pattern: DFSOrderPattern = 'IN',\n onlyOne: boolean = false,\n startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C>[] {\n return super.dfs(callback, pattern, onlyOne, startNode, iterationType);\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The function overrides the breadth-first search method and returns an array of the return types of\n * the callback function.\n * @param {C} callback - The `callback` parameter is a function that will be called for each node\n * visited during the breadth-first search. It should take a single argument, which is the current\n * node being visited, and it can return a value of any type.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting\n * point for the breadth-first search. It can be either a root node, a key-value pair, or an entry\n * object. If no value is provided, the default value is the root of the tree.\n * @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type\n * of iteration to be performed during the breadth-first search (BFS) traversal. It can have one of\n * the following values:\n * @returns an array of the return type of the callback function.\n */\n override bfs<C extends NodeCallback<BSTNode<K, V>>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C>[] {\n return super.bfs(callback, startNode, iterationType, false);\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The function overrides the listLevels method from the superclass and returns an array of arrays\n * containing the results of the callback function applied to each level of the tree.\n * @param {C} callback - The `callback` parameter is a generic type `C` that extends\n * `NodeCallback<BSTNode<K, V> | null>`. It represents a callback function that will be called for each node in the\n * tree during the iteration process.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting\n * point for listing the levels of the binary tree. It can be either a root node of the tree, a\n * key-value pair representing a node in the tree, or a key representing a node in the tree. If no\n * value is provided, the root of\n * @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type\n * of iteration to be performed on the tree. It can have one of the following values:\n * @returns The method is returning a two-dimensional array of the return type of the callback\n * function.\n */\n override listLevels<C extends NodeCallback<BSTNode<K, V>>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C>[][] {\n return super.listLevels(callback, startNode, iterationType, false);\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `lesserOrGreaterTraverse` function traverses a binary tree and applies a callback function to\n * each node that meets a certain condition based on a target node and a comparison value.\n * @param {C} callback - The `callback` parameter is a function that will be called for each node\n * that meets the condition specified by the `lesserOrGreater` parameter. It takes a single argument,\n * which is the current node being traversed, and returns a value of any type.\n * @param {CP} lesserOrGreater - The `lesserOrGreater` parameter is used to determine whether to\n * traverse nodes that are lesser, greater, or both than the `targetNode`. It accepts the values -1,\n * 0, or 1, where:\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } targetNode - The `targetNode` parameter is the node in\n * the binary tree that you want to start traversing from. It can be specified either by providing\n * the key of the node, the node itself, or an entry containing the key and value of the node. If no\n * `targetNode` is provided,\n * @param {IterationType} iterationType - The `iterationType` parameter determines the type of\n * traversal to be performed on the binary tree. It can have two possible values:\n * @returns The function `lesserOrGreaterTraverse` returns an array of values of type\n * `ReturnType<C>`, which is the return type of the callback function passed as an argument.\n */\n lesserOrGreaterTraverse<C extends NodeCallback<BSTNode<K, V>>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n lesserOrGreater: CP = -1,\n targetNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C>[] {\n const targetNodeEnsured = this.ensureNode(targetNode);\n const ans: ReturnType<NodeCallback<BSTNode<K, V>>>[] = [];\n if (!this._root) return ans;\n if (!targetNodeEnsured) return ans;\n\n const targetKey = targetNodeEnsured.key;\n\n if (iterationType === 'RECURSIVE') {\n const dfs = (cur: BSTNode<K, V>) => {\n const compared = this._compare(cur.key, targetKey);\n if (Math.sign(compared) === lesserOrGreater) ans.push(callback(cur));\n // TODO here can be optimized to O(log n)\n if (this.isRealNode(cur.left)) dfs(cur.left);\n if (this.isRealNode(cur.right)) dfs(cur.right);\n };\n\n dfs(this._root);\n return ans;\n } else {\n const queue = new Queue<BSTNode<K, V>>([this._root]);\n while (queue.length > 0) {\n const cur = queue.shift();\n if (this.isRealNode(cur)) {\n const compared = this._compare(cur.key, targetKey);\n if (Math.sign(compared) === lesserOrGreater) ans.push(callback(cur));\n\n if (this.isRealNode(cur.left)) queue.push(cur.left);\n if (this.isRealNode(cur.right)) queue.push(cur.right);\n }\n }\n return ans;\n }\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `perfectlyBalance` function takes an optional `iterationType` parameter and returns `true` if\n * the binary search tree is perfectly balanced, otherwise it returns `false`.\n * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that\n * specifies the type of iteration to use when building a balanced binary search tree. It has a\n * default value of `this.iterationType`, which means it will use the iteration type specified in the\n * current instance of the class.\n * @returns The function `perfectlyBalance` returns a boolean value.\n */\n perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {\n const sorted = this.dfs(node => node, 'IN'),\n n = sorted.length;\n this._clearNodes();\n\n if (sorted.length < 1) return false;\n if (iterationType === 'RECURSIVE') {\n const buildBalanceBST = (l: number, r: number) => {\n if (l > r) return;\n const m = l + Math.floor((r - l) / 2);\n const midNode = sorted[m];\n if (this._isMapMode && midNode !== null) this.add(midNode.key);\n else if (midNode !== null) this.add([midNode.key, midNode.value]);\n buildBalanceBST(l, m - 1);\n buildBalanceBST(m + 1, r);\n };\n\n buildBalanceBST(0, n - 1);\n return true;\n } else {\n const stack: [[number, number]] = [[0, n - 1]];\n while (stack.length > 0) {\n const popped = stack.pop();\n if (popped) {\n const [l, r] = popped;\n if (l <= r) {\n const m = l + Math.floor((r - l) / 2);\n const midNode = sorted[m];\n if (this._isMapMode && midNode !== null) this.add(midNode.key);\n else if (midNode !== null) this.add([midNode.key, midNode.value]);\n stack.push([m + 1, r]);\n stack.push([l, m - 1]);\n }\n }\n }\n return true;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The function `isAVLBalanced` checks if a binary tree is AVL balanced using either a recursive or\n * iterative approach.\n * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that\n * specifies the type of iteration to use when checking if the AVL tree is balanced. It has a default\n * value of `this.iterationType`, which means it will use the iteration type specified in the current\n * instance of the AVL tree.\n * @returns a boolean value.\n */\n isAVLBalanced(iterationType: IterationType = this.iterationType): boolean {\n if (!this._root) return true;\n\n let balanced = true;\n\n if (iterationType === 'RECURSIVE') {\n const _height = (cur: BSTNode<K, V> | null | undefined): number => {\n if (!cur) return 0;\n const leftHeight = _height(cur.left),\n rightHeight = _height(cur.right);\n if (Math.abs(leftHeight - rightHeight) > 1) balanced = false;\n return Math.max(leftHeight, rightHeight) + 1;\n };\n _height(this._root);\n } else {\n const stack: BSTNode<K, V>[] = [];\n let node: OptNode<BSTNode<K, V>> = this._root,\n last: OptNode<BSTNode<K, V>> = undefined;\n const depths: Map<BSTNode<K, V>, number> = new Map();\n\n while (stack.length > 0 || node) {\n if (node) {\n stack.push(node);\n if (node.left !== null) node = node.left;\n } else {\n node = stack[stack.length - 1];\n if (!node.right || last === node.right) {\n node = stack.pop();\n if (node) {\n const left = node.left ? depths.get(node.left)! : -1;\n const right = node.right ? depths.get(node.right)! : -1;\n if (Math.abs(left - right) > 1) return false;\n depths.set(node, 1 + Math.max(left, right));\n last = node;\n node = undefined;\n }\n } else node = node.right;\n }\n }\n }\n\n return balanced;\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `map` function in TypeScript overrides the default map behavior for a binary search tree by\n * applying a callback function to each entry and creating a new tree with the results.\n * @param callback - A function that will be called for each entry in the BST. It takes four\n * arguments: the key, the value (which can be undefined), the index of the entry, and a reference to\n * the BST itself.\n * @param [options] - The `options` parameter in the `override map` method is of type `BSTOptions<MK,\n * MV, MR>`. It is an optional parameter that allows you to specify additional options for the Binary\n * Search Tree (BST) being created in the `map` method. These options could include configuration\n * @param {any} [thisArg] - The `thisArg` parameter in the `override map` method is used to specify\n * the value of `this` that should be used when executing the `callback` function. It allows you to\n * set the context or scope in which the callback function will be called. This can be useful when\n * you want\n * @returns The `map` method is returning a new Binary Search Tree (`BST`) instance with the entries\n * transformed by the provided callback function.\n */\n override map(\n callback: EntryCallback<K, V | undefined, [MK, MV]>,\n options?: BSTOptions<MK, MV, MR>,\n thisArg?: any\n ): BST<MK, MV, MR> {\n const newTree = new BST<MK, MV, MR>([], options);\n let index = 0;\n for (const [key, value] of this) {\n newTree.add(callback.call(thisArg, key, value, index++, this));\n }\n return newTree;\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The function `clone` overrides the default cloning behavior to create a deep copy of a tree\n * structure.\n * @returns The `cloned` object is being returned.\n */\n override clone() {\n const cloned = this.createTree();\n this._clone(cloned);\n return cloned;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function overrides a method and converts a key, value pair or entry or raw element to a node.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - A variable that can be of\n * type R or K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined . It represents either a key, a node, an entry, or a raw\n * element.\n * @param {V} [value] - The `value` parameter is an optional value of type `V`. It represents the\n * value associated with a key in a key-value pair.\n * @returns either a BSTNode<K, V> object or undefined.\n */\n protected override _keyValueNodeOrEntryToNodeAndValue(\n keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V\n ): [OptNode<BSTNode<K, V>>, V | undefined] {\n const [node, entryValue] = super._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);\n if (node === null) return [undefined, undefined];\n return [node, value ?? entryValue];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function sets the root of a tree-like structure and updates the parent property of the new\n * root.\n * @param {OptNode<BSTNode<K, V>>} v - v is a parameter of type BSTNode<K, V> or undefined.\n */\n protected override _setRoot(v: OptNode<BSTNode<K, V>>) {\n if (v) {\n v.parent = undefined;\n }\n this._root = v;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The _compare function compares two values using a specified comparator function and optionally\n * reverses the result.\n * @param {K} a - The parameter `a` is of type `K`, which is used as an input for comparison in the\n * `_compare` method.\n * @param {K} b - The parameter `b` in the `_compare` function is of type `K`.\n * @returns The `_compare` method is returning the result of the ternary expression. If `_isReverse`\n * is true, it returns the negation of the result of calling the `_comparator` function with\n * arguments `a` and `b`. If `_isReverse` is false, it returns the result of calling the\n * `_comparator` function with arguments `a` and `b`.\n */\n protected _compare(a: K, b: K) {\n return this._isReverse ? -this._comparator(a, b) : this._comparator(a, b);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport { getMSB } from '../../utils';\n\n/**\n *\n */\nexport class BinaryIndexedTree {\n protected readonly _freq: number;\n protected readonly _max: number;\n\n /**\n * The constructor initializes the properties of an object, including default frequency, maximum\n * value, a freqMap data structure, the most significant bit, and the count of negative frequencies.\n * @param - - `frequency`: The default frequency value. It is optional and has a default\n * value of 0.\n */\n constructor({ frequency = 0, max }: { frequency?: number; max: number }) {\n this._freq = frequency;\n this._max = max;\n this._freqMap = { 0: 0 };\n this._msb = getMSB(max);\n this._negativeCount = frequency < 0 ? max : 0;\n }\n\n protected _freqMap: Record<number, number>;\n\n /**\n * The function returns the frequency map of numbers.\n * @returns The `_freqMap` property, which is a record with number keys and number values, is being\n * returned.\n */\n get freqMap(): Record<number, number> {\n return this._freqMap;\n }\n\n protected _msb: number;\n\n /**\n * The function returns the value of the _msb property.\n * @returns The `_msb` property of the object.\n */\n get msb(): number {\n return this._msb;\n }\n\n protected _negativeCount: number;\n\n /**\n * The function returns the value of the _negativeCount property.\n * @returns The method is returning the value of the variable `_negativeCount`, which is of type\n * `number`.\n */\n get negativeCount(): number {\n return this._negativeCount;\n }\n\n /**\n * The above function returns the value of the protected variable `_freq`.\n * @returns The frequency value stored in the protected variable `_freq`.\n */\n get freq(): number {\n return this._freq;\n }\n\n /**\n * The above function returns the maximum value.\n * @returns The maximum value stored in the variable `_max`.\n */\n get max(): number {\n return this._max;\n }\n\n /**\n * The function \"readSingle\" reads a single number from a specified index.\n * @param {number} index - The `index` parameter is a number that represents the index of an element in a\n * collection or array.\n * @returns a number.\n */\n readSingle(index: number): number {\n this._checkIndex(index);\n return this._readSingle(index);\n }\n\n /**\n * The \"update\" function updates the value at a given index by adding a delta and triggers a callback\n * to notify of the change.\n * @param {number} position - The `index` parameter represents the index of the element that needs to be\n * updated in the data structure.\n * @param {number} change - The \"delta\" parameter represents the change in value that needs to be\n * applied to the frequency at the specified index.\n */\n update(position: number, change: number): void {\n this._checkIndex(position);\n const freqCur = this._readSingle(position);\n\n this._update(position, change);\n this._updateNegativeCount(freqCur, freqCur + change);\n }\n\n /**\n * The function \"writeSingle\" checks the index and writes a single value with a given frequency.\n * @param {number} index - The `index` parameter is a number that represents the index of an element. It\n * is used to identify the specific element that needs to be written.\n * @param {number} freq - The `freq` parameter represents the frequency value that needs to be\n * written.\n */\n writeSingle(index: number, freq: number): void {\n this._checkIndex(index);\n this._writeSingle(index, freq);\n }\n\n /**\n * The read function takes a count parameter, checks if it is an integer, and returns the result of\n * calling the _read function with the count parameter clamped between 0 and the maximum value.\n * @param {number} count - The `count` parameter is a number that represents the number of items to\n * read.\n * @returns a number.\n */\n read(count: number): number {\n if (!Number.isInteger(count)) {\n throw new Error('Invalid count');\n }\n return this._read(Math.max(Math.min(count, this.max), 0));\n }\n\n /**\n * The function returns the lower bound of a non-descending sequence that sums up to a given number.\n * @param {number} sum - The `sum` parameter is a number that represents the target sum that we want\n * to find in the sequence.\n * @returns The lowerBound function is returning a number.\n */\n lowerBound(sum: number): number {\n if (this.negativeCount > 0) {\n throw new Error('Sequence is not non-descending');\n }\n return this._binarySearch(sum, (x, y) => x < y);\n }\n\n /**\n * The upperBound function returns the index of the first element in a sequence that is greater than\n * or equal to a given sum.\n * @param {number} sum - The \"sum\" parameter is a number that represents the target sum that we want\n * to find in the sequence.\n * @returns The upperBound function is returning a number.\n */\n upperBound(sum: number): number {\n if (this.negativeCount > 0) {\n throw new Error('Must not be descending');\n }\n return this._binarySearch(sum, (x, y) => x <= y);\n }\n\n /**\n * The function calculates the prefix sum of an array using a binary indexed tree.\n * @param {number} i - The parameter \"i\" in the function \"getPrefixSum\" represents the index of the element in the\n * array for which we want to calculate the prefix sum.\n * @returns The function `getPrefixSum` returns the prefix sum of the elements in the binary indexed tree up to index\n * `i`.\n */\n getPrefixSum(i: number): number {\n this._checkIndex(i);\n i++; // Convert to 1-based index\n\n let sum = 0;\n while (i > 0) {\n sum += this._getFrequency(i);\n i -= i & -i;\n }\n\n return sum;\n }\n\n /**\n * The function returns the value of a specific index in a freqMap data structure, or a default value if\n * the index is not found.\n * @param {number} index - The `index` parameter is a number that represents the index of a node in a\n * freqMap data structure.\n * @returns a number.\n */\n protected _getFrequency(index: number): number {\n if (index in this.freqMap) {\n return this.freqMap[index];\n }\n\n return this.freq * (index & -index);\n }\n\n /**\n * The function _updateFrequency adds a delta value to the element at the specified index in the freqMap array.\n * @param {number} index - The index parameter is a number that represents the index of the freqMap\n * element that needs to be updated.\n * @param {number} delta - The `delta` parameter represents the change in value that needs to be\n * added to the freqMap at the specified `index`.\n */\n protected _updateFrequency(index: number, delta: number): void {\n this.freqMap[index] = this._getFrequency(index) + delta;\n }\n\n /**\n * The function checks if the given index is valid and within the range.\n * @param {number} index - The parameter \"index\" is of type number and represents the index value\n * that needs to be checked.\n */\n protected _checkIndex(index: number): void {\n if (!Number.isInteger(index)) {\n throw new Error('Invalid index: Index must be an integer.');\n }\n if (index < 0 || index >= this.max) {\n throw new Error('Index out of range: Index must be within the range [0, this.max).');\n }\n }\n\n /**\n * The function calculates the sum of elements in an array up to a given index using a binary indexed\n * freqMap.\n * @param {number} index - The `index` parameter is a number that represents the index of an element in a\n * data structure.\n * @returns a number.\n */\n protected _readSingle(index: number): number {\n index = index + 1;\n let sum = this._getFrequency(index);\n const z = index - (index & -index);\n\n index--;\n\n while (index !== z) {\n sum -= this._getFrequency(index);\n index -= index & -index;\n }\n\n return sum;\n }\n\n /**\n * The function `_updateNegativeCount` updates a counter based on changes in frequency values.\n * @param {number} freqCur - The current frequency value.\n * @param {number} freqNew - The freqNew parameter represents the new frequency value.\n */\n protected _updateNegativeCount(freqCur: number, freqNew: number): void {\n if (freqCur < 0 && freqNew >= 0) {\n this._negativeCount--;\n } else if (freqCur >= 0 && freqNew < 0) {\n this._negativeCount++;\n }\n }\n\n /**\n * The `_update` function updates the values in a binary indexed freqMap starting from a given index and\n * propagating the changes to its parent nodes.\n * @param {number} index - The `index` parameter is a number that represents the index of the element in\n * the data structure that needs to be updated.\n * @param {number} delta - The `delta` parameter represents the change in value that needs to be\n * applied to the elements in the data structure.\n */\n protected _update(index: number, delta: number): void {\n index = index + 1;\n\n while (index <= this.max) {\n this._updateFrequency(index, delta);\n index += index & -index;\n }\n }\n\n /**\n * The `_writeSingle` function updates the frequency at a specific index and triggers a callback if\n * the frequency has changed.\n * @param {number} index - The `index` parameter is a number that represents the index of the element\n * being modified or accessed.\n * @param {number} freq - The `freq` parameter represents the new frequency value that needs to be\n * written to the specified index `index`.\n */\n protected _writeSingle(index: number, freq: number): void {\n const freqCur = this._readSingle(index);\n\n this._update(index, freq - freqCur);\n this._updateNegativeCount(freqCur, freq);\n }\n\n /**\n * The `_read` function calculates the sum of values in a binary freqMap up to a given count.\n * @param {number} count - The `count` parameter is a number that represents the number of elements\n * to read from the freqMap.\n * @returns the sum of the values obtained from calling the `_getFrequency` method for each index in the\n * range from `count` to 1.\n */\n protected _read(count: number): number {\n let index = count;\n let sum = 0;\n while (index) {\n sum += this._getFrequency(index);\n index -= index & -index;\n }\n\n return sum;\n }\n\n /**\n * The function `_binarySearch` performs a binary search to find the largest number that satisfies a given\n * condition.\n * @param {number} sum - The sum parameter is a number that represents the target sum value.\n * @param before - The `before` parameter is a function that takes two numbers `x` and `y` as\n * arguments and returns a boolean value. It is used to determine if `x` is less than or equal to\n * `y`. The purpose of this function is to compare two numbers and determine their order.\n * @returns the value of the variable \"left\".\n */\n protected _binarySearch(sum: number, before: (x: number, y: number) => boolean): number {\n let left = 0;\n let right = this.msb << 1;\n let sumT = sum;\n\n while (right > left + 1) {\n const middle = (left + right) >> 1;\n const sumM = this._getFrequency(middle);\n\n if (middle <= this.max && before(sumM, sumT)) {\n sumT -= sumM;\n left = middle;\n } else {\n right = middle;\n }\n }\n return left;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n\nimport type { SegmentTreeNodeVal } from '../../types';\n\nexport class SegmentTreeNode {\n /**\n * The constructor initializes the properties of a SegmentTreeNode object.\n * @param {number} start - The `start` parameter represents the starting index of the segment covered\n * by this node in a segment tree.\n * @param {number} end - The `end` parameter represents the end index of the segment covered by this\n * node in a segment tree.\n * @param {number} sum - The `sum` parameter represents the sum of the values in the range covered by\n * the segment tree node.\n * @param {SegmentTreeNodeVal | undefined} [value] - The `value` parameter is an optional parameter\n * of type `SegmentTreeNodeVal`. It represents the value associated with the segment tree node.\n */\n constructor(start: number, end: number, sum: number, value?: SegmentTreeNodeVal | undefined) {\n this._start = start;\n this._end = end;\n this._sum = sum;\n this._value = value || undefined;\n }\n\n protected _start = 0;\n\n /**\n * The function returns the value of the protected variable _start.\n * @returns The start value, which is of type number.\n */\n get start(): number {\n return this._start;\n }\n\n /**\n * The above function sets the value of the \"start\" property.\n * @param {number} value - The value parameter is of type number.\n */\n set start(value: number) {\n this._start = value;\n }\n\n protected _end = 0;\n\n /**\n * The function returns the value of the protected variable `_end`.\n * @returns The value of the protected property `_end`.\n */\n get end(): number {\n return this._end;\n }\n\n /**\n * The above function sets the value of the \"end\" property.\n * @param {number} value - The value parameter is a number that represents the new value for the end\n * property.\n */\n set end(value: number) {\n this._end = value;\n }\n\n protected _value: SegmentTreeNodeVal | undefined = undefined;\n\n /**\n * The function returns the value of a segment tree node.\n * @returns The value being returned is either a `SegmentTreeNodeVal` object or `undefined`.\n */\n get value(): SegmentTreeNodeVal | undefined {\n return this._value;\n }\n\n /**\n * The function sets the value of a segment tree node.\n * @param {SegmentTreeNodeVal | undefined} value - The `value` parameter is of type\n * `SegmentTreeNodeVal` or `undefined`.\n */\n set value(value: SegmentTreeNodeVal | undefined) {\n this._value = value;\n }\n\n protected _sum = 0;\n\n /**\n * The function returns the value of the sum property.\n * @returns The method is returning the value of the variable `_sum`.\n */\n get sum(): number {\n return this._sum;\n }\n\n /**\n * The above function sets the value of the sum property.\n * @param {number} value - The parameter \"value\" is of type \"number\".\n */\n set sum(value: number) {\n this._sum = value;\n }\n\n protected _left: SegmentTreeNode | undefined = undefined;\n\n /**\n * The function returns the left child of a segment tree node.\n * @returns The `left` property of the `SegmentTreeNode` object is being returned. It is of type\n * `SegmentTreeNode` or `undefined`.\n */\n get left(): SegmentTreeNode | undefined {\n return this._left;\n }\n\n /**\n * The function sets the value of the left property of a SegmentTreeNode object.\n * @param {SegmentTreeNode | undefined} value - The value parameter is of type SegmentTreeNode or\n * undefined.\n */\n set left(value: SegmentTreeNode | undefined) {\n this._left = value;\n }\n\n protected _right: SegmentTreeNode | undefined = undefined;\n\n /**\n * The function returns the right child of a segment tree node.\n * @returns The `getRight()` method is returning a value of type `SegmentTreeNode` or `undefined`.\n */\n get right(): SegmentTreeNode | undefined {\n return this._right;\n }\n\n /**\n * The function sets the right child of a segment tree node.\n * @param {SegmentTreeNode | undefined} value - The `value` parameter is of type `SegmentTreeNode |\n * undefined`. This means that it can accept either a `SegmentTreeNode` object or `undefined` as its\n * value.\n */\n set right(value: SegmentTreeNode | undefined) {\n this._right = value;\n }\n}\n\nexport class SegmentTree {\n /**\n * The constructor initializes the values, start, end, and root properties of an object.\n * @param {number[]} values - An array of numbers that will be used to build a binary search tree.\n * @param {number} [start] - The `start` parameter is the index of the first element in the `values` array that should\n * be included in the range. If no value is provided for `start`, it defaults to 0, which means the range starts from\n * the beginning of the array.\n * @param {number} [end] - The \"end\" parameter is the index of the last element in the \"values\" array that should be\n * included in the range. If not provided, it defaults to the index of the last element in the \"values\" array.\n */\n constructor(values: number[], start?: number, end?: number) {\n start = start || 0;\n end = end || values.length - 1;\n this._values = values;\n this._start = start;\n this._end = end;\n\n if (values.length > 0) {\n this._root = this.build(start, end);\n } else {\n this._root = undefined;\n this._values = [];\n }\n }\n\n protected _values: number[] = [];\n\n /**\n * The function returns an array of numbers.\n * @returns An array of numbers is being returned.\n */\n get values(): number[] {\n return this._values;\n }\n\n protected _start = 0;\n\n /**\n * The function returns the value of the protected variable _start.\n * @returns The start value, which is of type number.\n */\n get start(): number {\n return this._start;\n }\n\n protected _end: number;\n\n /**\n * The function returns the value of the protected variable `_end`.\n * @returns The value of the protected property `_end`.\n */\n get end(): number {\n return this._end;\n }\n\n protected _root: SegmentTreeNode | undefined;\n\n /**\n * The function returns the root node of a segment tree.\n * @returns The `root` property of the class `SegmentTreeNode` or `undefined` if it is not defined.\n */\n get root(): SegmentTreeNode | undefined {\n return this._root;\n }\n\n /**\n * The build function creates a segment tree by recursively dividing the given range into smaller segments and assigning\n * the sum of values to each segment.\n * @param {number} start - The `start` parameter represents the starting index of the segment or range for which we are\n * building the segment tree.\n * @param {number} end - The \"end\" parameter represents the ending index of the segment or range for which we want to\n * build a segment tree.\n * @returns a SegmentTreeNode object.\n */\n build(start: number, end: number): SegmentTreeNode {\n if (start > end) {\n return new SegmentTreeNode(start, end, 0);\n }\n if (start === end) return new SegmentTreeNode(start, end, this._values[start]);\n\n const mid = start + Math.floor((end - start) / 2);\n const left = this.build(start, mid);\n const right = this.build(mid + 1, end);\n const cur = new SegmentTreeNode(start, end, left.sum + right.sum);\n cur.left = left;\n cur.right = right;\n return cur;\n }\n\n /**\n * The function updates the value of a node in a segment tree and recalculates the sum of its children if they exist.\n * @param {number} index - The index parameter represents the index of the node in the segment tree that needs to be\n * updated.\n * @param {number} sum - The `sum` parameter represents the new value that should be assigned to the `sum` property of\n * the `SegmentTreeNode` at the specified `index`.\n * @param {SegmentTreeNodeVal} [value] - The `value` parameter is an optional value that can be assigned to the `value`\n * property of the `SegmentTreeNode` object. It is not currently used in the code, but you can uncomment the line `//\n * cur.value = value;` and pass a value for `value` in the\n * @returns The function does not return anything.\n */\n updateNode(index: number, sum: number, value?: SegmentTreeNodeVal) {\n const root = this.root || undefined;\n if (!root) {\n return;\n }\n const dfs = (cur: SegmentTreeNode, index: number, sum: number, value?: SegmentTreeNodeVal) => {\n if (cur.start === cur.end && cur.start === index) {\n cur.sum = sum;\n if (value !== undefined) cur.value = value;\n return;\n }\n const mid = cur.start + Math.floor((cur.end - cur.start) / 2);\n if (index <= mid) {\n if (cur.left) {\n dfs(cur.left, index, sum, value);\n }\n } else {\n if (cur.right) {\n dfs(cur.right, index, sum, value);\n }\n }\n if (cur.left && cur.right) {\n cur.sum = cur.left.sum + cur.right.sum;\n }\n };\n\n dfs(root, index, sum, value);\n }\n\n /**\n * The function `querySumByRange` calculates the sum of values within a given range in a segment tree.\n * @param {number} indexA - The starting index of the range for which you want to calculate the sum.\n * @param {number} indexB - The parameter `indexB` represents the ending index of the range for which you want to\n * calculate the sum.\n * @returns The function `querySumByRange` returns a number.\n */\n querySumByRange(indexA: number, indexB: number): number {\n const root = this.root || undefined;\n if (!root) {\n return 0;\n }\n\n if (indexA < 0 || indexB >= this.values.length || indexA > indexB) {\n return NaN;\n }\n\n const dfs = (cur: SegmentTreeNode, i: number, j: number): number => {\n if (i <= cur.start && j >= cur.end) {\n // The range [i, j] completely covers the current node's range [cur.start, cur.end]\n return cur.sum;\n }\n const mid = cur.start + Math.floor((cur.end - cur.start) / 2);\n if (j <= mid) {\n if (cur.left) {\n return dfs(cur.left, i, j);\n } else {\n return NaN;\n }\n } else if (i > mid) {\n if (cur.right) {\n return dfs(cur.right, i, j);\n } else {\n return NaN;\n }\n } else {\n // Query both left and right subtrees\n let leftSum = 0;\n let rightSum = 0;\n if (cur.left) {\n leftSum = dfs(cur.left, i, mid);\n }\n if (cur.right) {\n rightSum = dfs(cur.right, mid + 1, j);\n }\n return leftSum + rightSum;\n }\n };\n return dfs(root, indexA, indexB);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport { BST, BSTNode } from './bst';\nimport type { AVLTreeOptions, BinaryTreeDeleteResult, BSTNOptKeyOrNode, EntryCallback } from '../../types';\nimport { IBinaryTree } from '../../interfaces';\n\nexport class AVLTreeNode<K = any, V = any> extends BSTNode<K, V> {\n override parent?: AVLTreeNode<K, V> = undefined;\n\n /**\n * This TypeScript constructor function initializes an instance with a key and an optional value.\n * @param {K} key - The `key` parameter is typically used to uniquely identify an object or element\n * within a data structure. It serves as a reference or identifier for accessing or manipulating the\n * associated value or data.\n * @param {V} [value] - The `value` parameter in the constructor is optional, meaning it does not\n * have to be provided when creating an instance of the class. If a value is not provided, it will\n * default to `undefined`.\n */\n constructor(key: K, value?: V) {\n super(key, value);\n }\n\n override _left?: AVLTreeNode<K, V> | null | undefined = undefined;\n\n override get left(): AVLTreeNode<K, V> | null | undefined {\n return this._left;\n }\n\n override set left(v: AVLTreeNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._left = v;\n }\n\n override _right?: AVLTreeNode<K, V> | null | undefined = undefined;\n\n override get right(): AVLTreeNode<K, V> | null | undefined {\n return this._right;\n }\n\n override set right(v: AVLTreeNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n}\n\n/**\n * 1. Height-Balanced: Each node's left and right subtrees differ in height by no more than one.\n * 2. Automatic Rebalancing: AVL trees rebalance themselves automatically during insertions and deletions.\n * 3. Rotations for Balancing: Utilizes rotations (single or double) to maintain balance after updates.\n * 4. Order Preservation: Maintains the binary search tree property where left child values are less than the parent, and right child values are greater.\n * 5. Efficient Lookups: Offers O(log n) search time, where 'n' is the number of nodes, due to its balanced nature.\n * 6. Complex Insertions and Deletions: Due to rebalancing, these operations are more complex than in a regular BST.\n * 7. Path Length: The path length from the root to any leaf is longer compared to an unbalanced BST, but shorter than a linear chain of nodes.\n * @example\n * // Find elements in a range\n * // In interval queries, AVL trees, with their strictly balanced structure and lower height, offer better query efficiency, making them ideal for frequent and high-performance interval queries. In contrast, Red-Black trees, with lower update costs, are more suitable for scenarios involving frequent insertions and deletions where the requirements for interval queries are less demanding.\n * type Datum = { timestamp: Date; temperature: number };\n * // Fixed dataset of CPU temperature readings\n * const cpuData: Datum[] = [\n * { timestamp: new Date('2024-12-02T00:00:00'), temperature: 55.1 },\n * { timestamp: new Date('2024-12-02T00:01:00'), temperature: 56.3 },\n * { timestamp: new Date('2024-12-02T00:02:00'), temperature: 54.8 },\n * { timestamp: new Date('2024-12-02T00:03:00'), temperature: 57.2 },\n * { timestamp: new Date('2024-12-02T00:04:00'), temperature: 58.0 },\n * { timestamp: new Date('2024-12-02T00:05:00'), temperature: 59.4 },\n * { timestamp: new Date('2024-12-02T00:06:00'), temperature: 60.1 },\n * { timestamp: new Date('2024-12-02T00:07:00'), temperature: 61.3 },\n * { timestamp: new Date('2024-12-02T00:08:00'), temperature: 62.0 },\n * { timestamp: new Date('2024-12-02T00:09:00'), temperature: 63.5 },\n * { timestamp: new Date('2024-12-02T00:10:00'), temperature: 64.0 },\n * { timestamp: new Date('2024-12-02T00:11:00'), temperature: 62.8 },\n * { timestamp: new Date('2024-12-02T00:12:00'), temperature: 61.5 },\n * { timestamp: new Date('2024-12-02T00:13:00'), temperature: 60.2 },\n * { timestamp: new Date('2024-12-02T00:14:00'), temperature: 59.8 },\n * { timestamp: new Date('2024-12-02T00:15:00'), temperature: 58.6 },\n * { timestamp: new Date('2024-12-02T00:16:00'), temperature: 57.4 },\n * { timestamp: new Date('2024-12-02T00:17:00'), temperature: 56.2 },\n * { timestamp: new Date('2024-12-02T00:18:00'), temperature: 55.7 },\n * { timestamp: new Date('2024-12-02T00:19:00'), temperature: 54.5 },\n * { timestamp: new Date('2024-12-02T00:20:00'), temperature: 53.2 },\n * { timestamp: new Date('2024-12-02T00:21:00'), temperature: 52.8 },\n * { timestamp: new Date('2024-12-02T00:22:00'), temperature: 51.9 },\n * { timestamp: new Date('2024-12-02T00:23:00'), temperature: 50.5 },\n * { timestamp: new Date('2024-12-02T00:24:00'), temperature: 49.8 },\n * { timestamp: new Date('2024-12-02T00:25:00'), temperature: 48.7 },\n * { timestamp: new Date('2024-12-02T00:26:00'), temperature: 47.5 },\n * { timestamp: new Date('2024-12-02T00:27:00'), temperature: 46.3 },\n * { timestamp: new Date('2024-12-02T00:28:00'), temperature: 45.9 },\n * { timestamp: new Date('2024-12-02T00:29:00'), temperature: 45.0 }\n * ];\n *\n * // Create an AVL tree to store CPU temperature data\n * const cpuTemperatureTree = new AVLTree<Date, number, Datum>(cpuData, {\n * toEntryFn: ({ timestamp, temperature }) => [timestamp, temperature]\n * });\n *\n * // Query a specific time range (e.g., from 00:05 to 00:15)\n * const rangeStart = new Date('2024-12-02T00:05:00');\n * const rangeEnd = new Date('2024-12-02T00:15:00');\n * const rangeResults = cpuTemperatureTree.rangeSearch([rangeStart, rangeEnd], node => ({\n * minute: node ? node.key.getMinutes() : 0,\n * temperature: cpuTemperatureTree.get(node ? node.key : undefined)\n * }));\n *\n * console.log(rangeResults); // [\n * // { minute: 5, temperature: 59.4 },\n * // { minute: 6, temperature: 60.1 },\n * // { minute: 7, temperature: 61.3 },\n * // { minute: 8, temperature: 62 },\n * // { minute: 9, temperature: 63.5 },\n * // { minute: 10, temperature: 64 },\n * // { minute: 11, temperature: 62.8 },\n * // { minute: 12, temperature: 61.5 },\n * // { minute: 13, temperature: 60.2 },\n * // { minute: 14, temperature: 59.8 },\n * // { minute: 15, temperature: 58.6 }\n * // ]\n */\nexport class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends BST<K, V, R, MK, MV, MR>\n implements IBinaryTree<K, V, R, MK, MV, MR>\n{\n /**\n * This TypeScript constructor initializes an AVLTree with keys, nodes, entries, or raw data provided\n * in an iterable format.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an\n * iterable that can contain either `\n K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` objects or `R` objects. It is\n * used to initialize the AVLTree with key-value pairs or raw data entries. If provided\n * @param [options] - The `options` parameter in the constructor is of type `AVLTreeOptions<K, V,\n * R>`. It is an optional parameter that allows you to specify additional options for configuring the\n * AVL tree. These options could include things like custom comparators, initial capacity, or any\n * other configuration settings specific\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n > = [],\n options?: AVLTreeOptions<K, V, R>\n ) {\n super([], options);\n if (keysNodesEntriesOrRaws) super.addMany(keysNodesEntriesOrRaws);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a new AVL tree node with the given key and value.\n * @param {K} key - The key parameter is of type K, which represents the key of the node being\n * created.\n * @param {V} [value] - The \"value\" parameter is an optional parameter of type V. It represents the\n * value associated with the key in the node being created.\n * @returns The method is returning a new instance of the AVLTreeNode class, casted as the generic\n * type AVLTreeNode<K, V>.\n */\n override createNode(key: K, value?: V): AVLTreeNode<K, V> {\n return new AVLTreeNode<K, V>(key, this._isMapMode ? undefined : value) as AVLTreeNode<K, V>;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a new AVL tree with the specified options and returns it.\n * @param {AVLTreeOptions} [options] - The `options` parameter is an optional object that can be\n * passed to the `createTree` function. It is used to customize the behavior of the AVL tree that is\n * being created.\n * @returns a new AVLTree object.\n */\n override createTree(options?: AVLTreeOptions<K, V, R>) {\n return new AVLTree<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n isMapMode: this._isMapMode,\n specifyComparable: this._specifyComparable,\n toEntryFn: this._toEntryFn,\n isReverse: this._isReverse,\n ...options\n });\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if the input is an instance of AVLTreeNode.\n * @param {K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be of type `R` or `\n K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.\n * @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is\n * an instance of the `AVLTreeNode` class.\n */\n override isNode(\n keyNodeOrEntry: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is AVLTreeNode<K, V> {\n return keyNodeOrEntry instanceof AVLTreeNode;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function overrides the add method of a class and inserts a key-value pair into a data\n * structure, then balances the path.\n * @param { K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can accept values of type `R`, `\n K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `\n * @param {V} [value] - The `value` parameter is an optional value that you want to associate with\n * the key or node being added to the data structure.\n * @returns The method is returning a boolean value.\n */\n override add(\n keyNodeOrEntry: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V\n ): boolean {\n if (keyNodeOrEntry === null) return false;\n const inserted = super.add(keyNodeOrEntry, value);\n if (inserted) this._balancePath(keyNodeOrEntry);\n return inserted;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function overrides the delete method in a TypeScript class, performs deletion, and then\n * balances the tree if necessary.\n * @param { K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`\n * parameter in the `override delete` method can be one of the following types:\n * @returns The `delete` method is being overridden in this code snippet. It first calls the `delete`\n * method from the superclass (presumably a parent class) with the provided `predicate`, which could\n * be a key, node, entry, or a custom predicate. The result of this deletion operation is stored in\n * `deletedResults`, which is an array of `BinaryTreeDeleteResult` objects.\n */\n override delete(\n keyNodeOrEntry: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): BinaryTreeDeleteResult<AVLTreeNode<K, V>>[] {\n const deletedResults = super.delete(keyNodeOrEntry);\n for (const { needBalanced } of deletedResults) {\n if (needBalanced) {\n this._balancePath(needBalanced);\n }\n }\n return deletedResults;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function in TypeScript overrides the default map behavior of an AVLTree data structure\n * by applying a callback function to each entry and creating a new AVLTree with the results.\n * @param callback - A function that will be called for each entry in the AVLTree. It takes four\n * arguments: the key, the value (which can be undefined), the index of the entry, and a reference to\n * the AVLTree itself.\n * @param [options] - The `options` parameter in the `override map` function is of type\n * `AVLTreeOptions<MK, MV, MR>`. It is an optional parameter that allows you to specify additional\n * options for the AVL tree being created during the mapping process. These options could include\n * custom comparators, initial\n * @param {any} [thisArg] - The `thisArg` parameter in the `override map` function is used to specify\n * the value of `this` when executing the `callback` function. It allows you to set the context\n * (value of `this`) within the callback function. This can be useful when you want to access\n * properties or\n * @returns The `map` method is returning a new AVLTree instance (`newTree`) with the entries\n * modified by the provided callback function.\n */\n override map(\n callback: EntryCallback<K, V | undefined, [MK, MV]>,\n options?: AVLTreeOptions<MK, MV, MR>,\n thisArg?: any\n ): AVLTree<MK, MV, MR> {\n const newTree = new AVLTree<MK, MV, MR>([], options);\n let index = 0;\n for (const [key, value] of this) {\n newTree.add(callback.call(thisArg, key, value, index++, this));\n }\n return newTree;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `clone` overrides the default cloning behavior to create a deep copy of a tree\n * structure.\n * @returns A cloned tree object is being returned.\n */\n override clone() {\n const cloned = this.createTree();\n this._clone(cloned);\n return cloned;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_swapProperties` function swaps the key, value, and height properties between two nodes in a\n * binary search tree.\n * @param {BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>} srcNode - The `srcNode` parameter represents either a node\n * object (`AVLTreeNode<K, V>`) or a key-value pair (`R`) that is being swapped with another node.\n * @param {BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>} destNode - The `destNode` parameter is either an instance of\n * `R` or an instance of `BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>`.\n * @returns The method is returning the `destNodeEnsured` object if both `srcNodeEnsured` and\n * `destNodeEnsured` are truthy. Otherwise, it returns `undefined`.\n */\n protected override _swapProperties(\n srcNode: BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>,\n destNode: BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>\n ): AVLTreeNode<K, V> | undefined {\n const srcNodeEnsured = this.ensureNode(srcNode);\n const destNodeEnsured = this.ensureNode(destNode);\n\n if (srcNodeEnsured && destNodeEnsured) {\n const { key, value, height } = destNodeEnsured;\n const tempNode = this.createNode(key, value);\n\n if (tempNode) {\n tempNode.height = height;\n\n destNodeEnsured.key = srcNodeEnsured.key;\n if (!this._isMapMode) destNodeEnsured.value = srcNodeEnsured.value;\n destNodeEnsured.height = srcNodeEnsured.height;\n\n srcNodeEnsured.key = tempNode.key;\n if (!this._isMapMode) srcNodeEnsured.value = tempNode.value;\n srcNodeEnsured.height = tempNode.height;\n }\n\n return destNodeEnsured;\n }\n return undefined;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function calculates the balance factor of a node in a binary tree.\n * @param {AVLTreeNode<K, V>} node - The parameter \"node\" is of type \"AVLTreeNode<K, V>\", which likely represents a node in a\n * binary tree data structure.\n * @returns the balance factor of a given node. The balance factor is calculated by subtracting the\n * height of the left subtree from the height of the right subtree.\n */\n protected _balanceFactor(node: AVLTreeNode<K, V>): number {\n if (!node.right)\n // node has no right subtree\n return -node.height;\n else if (!node.left)\n // node has no left subtree\n return +node.height;\n else return node.right.height - node.left.height;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function updates the height of a node in a binary tree based on the heights of its left and\n * right children.\n * @param {AVLTreeNode<K, V>} node - The parameter \"node\" represents a node in a binary tree data structure.\n */\n protected _updateHeight(node: AVLTreeNode<K, V>): void {\n if (!node.left && !node.right) node.height = 0;\n else if (!node.left) {\n const rightHeight = node.right ? node.right.height : 0;\n node.height = 1 + rightHeight;\n } else if (!node.right) node.height = 1 + node.left.height;\n else node.height = 1 + Math.max(node.right.height, node.left.height);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_balanceLL` function performs a left-left rotation to balance a binary search tree.\n * @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.\n */\n protected _balanceLL(A: AVLTreeNode<K, V>): void {\n const parentOfA = A.parent;\n const B = A.left;\n if (B !== null) A.parent = B;\n if (B && B.right) {\n B.right.parent = A;\n }\n if (B) B.parent = parentOfA;\n if (A === this.root) {\n if (B) this._setRoot(B);\n } else {\n if (parentOfA?.left === A) {\n parentOfA.left = B;\n } else {\n if (parentOfA) parentOfA.right = B;\n }\n }\n\n if (B) {\n A.left = B.right;\n B.right = A;\n }\n this._updateHeight(A);\n if (B) this._updateHeight(B);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_balanceLR` function performs a left-right rotation to balance a binary tree.\n * @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.\n */\n protected _balanceLR(A: AVLTreeNode<K, V>): void {\n const parentOfA = A.parent;\n const B = A.left;\n let C = undefined;\n if (B) {\n C = B.right;\n }\n if (A && C !== null) A.parent = C;\n if (B && C !== null) B.parent = C;\n\n if (C) {\n if (C.left) {\n if (B !== null) C.left.parent = B;\n }\n if (C.right) {\n C.right.parent = A;\n }\n C.parent = parentOfA;\n }\n\n if (A === this.root) {\n if (C) this._setRoot(C);\n } else {\n if (parentOfA) {\n if (parentOfA.left === A) {\n parentOfA.left = C;\n } else {\n parentOfA.right = C;\n }\n }\n }\n\n if (C) {\n A.left = C.right;\n if (B) B.right = C.left;\n C.left = B;\n C.right = A;\n }\n\n this._updateHeight(A);\n if (B) this._updateHeight(B);\n if (C) this._updateHeight(C);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_balanceRR` performs a right-right rotation to balance a binary tree.\n * @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.\n */\n protected _balanceRR(A: AVLTreeNode<K, V>): void {\n const parentOfA = A.parent;\n const B = A.right;\n if (B !== null) A.parent = B;\n if (B) {\n if (B.left) {\n B.left.parent = A;\n }\n B.parent = parentOfA;\n }\n\n if (A === this.root) {\n if (B) this._setRoot(B);\n } else {\n if (parentOfA) {\n if (parentOfA.left === A) {\n parentOfA.left = B;\n } else {\n parentOfA.right = B;\n }\n }\n }\n\n if (B) {\n A.right = B.left;\n B.left = A;\n }\n this._updateHeight(A);\n if (B) this._updateHeight(B);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_balanceRL` performs a right-left rotation to balance a binary tree.\n * @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.\n */\n protected _balanceRL(A: AVLTreeNode<K, V>): void {\n const parentOfA = A.parent;\n const B = A.right;\n let C = undefined;\n if (B) {\n C = B.left;\n }\n\n if (C !== null) A.parent = C;\n if (B && C !== null) B.parent = C;\n\n if (C) {\n if (C.left) {\n C.left.parent = A;\n }\n if (C.right) {\n if (B !== null) C.right.parent = B;\n }\n C.parent = parentOfA;\n }\n\n if (A === this.root) {\n if (C) this._setRoot(C);\n } else {\n if (parentOfA) {\n if (parentOfA.left === A) {\n parentOfA.left = C;\n } else {\n parentOfA.right = C;\n }\n }\n }\n\n if (C) A.right = C.left;\n if (B && C) B.left = C.right;\n if (C) C.left = A;\n if (C) C.right = B;\n\n this._updateHeight(A);\n if (B) this._updateHeight(B);\n if (C) this._updateHeight(C);\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The `_balancePath` function is used to update the heights of nodes and perform rotation operations\n * to restore balance in an AVL tree after inserting a node.\n * @param { K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } node - The `node` parameter can be of type `R` or\n * `\n K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.\n */\n protected _balancePath(node: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): void {\n node = this.ensureNode(node);\n const path = this.getPathToRoot(node, node => node, false); // first O(log n) + O(log n)\n for (let i = 0; i < path.length; i++) {\n // second O(log n)\n const A = path[i];\n if (A) {\n // Update Heights: After inserting a node, backtrack from the insertion point to the root node, updating the height of each node along the way.\n this._updateHeight(A); // first O(1)\n // Check Balance: Simultaneously with height updates, check if each node violates the balance property of an AVL tree.\n // Balance Restoration: If a balance issue is discovered after inserting a node, it requires balance restoration operations. Balance restoration includes four basic cases where rotation operations need to be performed to fix the balance:\n switch (\n this._balanceFactor(A) // second O(1)\n ) {\n case -2:\n if (A && A.left) {\n if (this._balanceFactor(A.left) <= 0) {\n // second O(1)\n // Left Rotation (LL Rotation): When the inserted node is in the left subtree of the left subtree, causing an imbalance.\n this._balanceLL(A);\n } else {\n // Left-Right Rotation (LR Rotation): When the inserted node is in the right subtree of the left subtree, causing an imbalance.\n this._balanceLR(A);\n }\n }\n break;\n case +2:\n if (A && A.right) {\n if (this._balanceFactor(A.right) >= 0) {\n // Right Rotation (RR Rotation): When the inserted node is in the right subtree of the right subtree, causing an imbalance.\n this._balanceRR(A);\n } else {\n // Right-Left Rotation (RL Rotation): When the inserted node is in the left subtree of the right subtree, causing an imbalance.\n this._balanceRL(A);\n }\n }\n }\n // TODO So far, no sure if this is necessary that Recursive Repair: Once rotation operations are executed, it may cause imbalance issues at higher levels of the tree. Therefore, you need to recursively check and repair imbalance problems upwards until you reach the root node.\n }\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function replaces an old node with a new node and sets the height of the new node to be the\n * same as the old node.\n * @param {AVLTreeNode<K, V>} oldNode - The `oldNode` parameter represents the node that needs to be replaced in\n * the data structure.\n * @param {AVLTreeNode<K, V>} newNode - The `newNode` parameter is the new node that will replace the `oldNode` in\n * the data structure.\n * @returns The method is returning the result of calling the `_replaceNode` method from the\n * superclass, with the `oldNode` and `newNode` as arguments.\n */\n protected override _replaceNode(oldNode: AVLTreeNode<K, V>, newNode: AVLTreeNode<K, V>): AVLTreeNode<K, V> {\n newNode.height = oldNode.height;\n\n return super._replaceNode(oldNode, newNode);\n }\n}\n","import type { BinaryTreeDeleteResult, CRUD, EntryCallback, OptNode, RBTNColor, RedBlackTreeOptions } from '../../types';\nimport { BST, BSTNode } from './bst';\nimport { IBinaryTree } from '../../interfaces';\n\nexport class RedBlackTreeNode<K = any, V = any> extends BSTNode<K, V> {\n override parent?: RedBlackTreeNode<K, V> = undefined;\n\n /**\n * The constructor initializes a node with a key, value, and color for a Red-Black Tree.\n * @param {K} key - The `key` parameter is a key of type `K` that is used to identify the node in a\n * Red-Black Tree data structure.\n * @param {V} [value] - The `value` parameter in the constructor is an optional parameter of type\n * `V`. It represents the value associated with the key in the data structure being constructed.\n * @param {RBTNColor} [color=BLACK] - The `color` parameter in the constructor is used to specify the\n * color of the node in a Red-Black Tree. It has a default value of 'BLACK' if not provided\n * explicitly.\n */\n constructor(key: K, value?: V, color: RBTNColor = 'BLACK') {\n super(key, value);\n this._color = color;\n }\n\n override _left?: RedBlackTreeNode<K, V> | null | undefined = undefined;\n\n override get left(): RedBlackTreeNode<K, V> | null | undefined {\n return this._left;\n }\n\n override set left(v: RedBlackTreeNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._left = v;\n }\n\n override _right?: RedBlackTreeNode<K, V> | null | undefined = undefined;\n\n override get right(): RedBlackTreeNode<K, V> | null | undefined {\n return this._right;\n }\n\n override set right(v: RedBlackTreeNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n}\n\n/**\n * 1. Efficient self-balancing, but not completely balanced. Compared with AVLTree, the addition and deletion efficiency is high but the query efficiency is slightly lower.\n * 2. It is BST itself. Compared with Heap which is not completely ordered, RedBlackTree is completely ordered.\n * @example\n * // using Red-Black Tree as a price-based index for stock data\n * // Define the structure of individual stock records\n * interface StockRecord {\n * price: number; // Stock price (key for indexing)\n * symbol: string; // Stock ticker symbol\n * volume: number; // Trade volume\n * }\n *\n * // Simulate stock market data as it might come from an external feed\n * const marketStockData: StockRecord[] = [\n * { price: 142.5, symbol: 'AAPL', volume: 1000000 },\n * { price: 335.2, symbol: 'MSFT', volume: 800000 },\n * { price: 3285.04, symbol: 'AMZN', volume: 500000 },\n * { price: 267.98, symbol: 'META', volume: 750000 },\n * { price: 234.57, symbol: 'GOOGL', volume: 900000 }\n * ];\n *\n * // Extend the stock record type to include metadata for database usage\n * type StockTableRecord = StockRecord & { lastUpdated: Date };\n *\n * // Create a Red-Black Tree to index stock records by price\n * // Simulates a database index with stock price as the key for quick lookups\n * const priceIndex = new RedBlackTree<number, StockTableRecord, StockRecord>(marketStockData, {\n * toEntryFn: stockRecord => [\n * stockRecord.price, // Use stock price as the key\n * {\n * ...stockRecord,\n * lastUpdated: new Date() // Add a timestamp for when the record was indexed\n * }\n * ]\n * });\n *\n * // Query the stock with the highest price\n * const highestPricedStock = priceIndex.getRightMost();\n * console.log(priceIndex.get(highestPricedStock)?.symbol); // 'AMZN' // Amazon has the highest price\n *\n * // Query stocks within a specific price range (200 to 400)\n * const stocksInRange = priceIndex.rangeSearch(\n * [200, 400], // Price range\n * node => priceIndex.get(node)?.symbol // Extract stock symbols for the result\n * );\n * console.log(stocksInRange); // ['GOOGL', 'META', 'MSFT']\n */\nexport class RedBlackTree<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends BST<K, V, R, MK, MV, MR>\n implements IBinaryTree<K, V, R, MK, MV, MR>\n{\n /**\n * This TypeScript constructor initializes a Red-Black Tree with optional keys, nodes, entries, or\n * raw data.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an\n * iterable that can contain either `K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined` objects or `R` objects. It\n * is used to initialize the Red-Black Tree with keys, nodes, entries, or\n * @param [options] - The `options` parameter in the constructor is of type `RedBlackTreeOptions<K,\n * V, R>`. It is an optional parameter that allows you to specify additional options for the\n * RedBlackTree class. These options could include configuration settings, behavior customization, or\n * any other parameters that are specific to\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n > = [],\n options?: RedBlackTreeOptions<K, V, R>\n ) {\n super([], options);\n\n this._root = this.NIL;\n\n if (keysNodesEntriesOrRaws) {\n this.addMany(keysNodesEntriesOrRaws);\n }\n }\n\n protected override _root: RedBlackTreeNode<K, V> | undefined;\n\n override get root(): RedBlackTreeNode<K, V> | undefined {\n return this._root;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a new Red-Black Tree node with the specified key, value, and color.\n * @param {K} key - The key parameter represents the key value of the node being created. It is of\n * type K, which is a generic type that can be replaced with any specific type when using the\n * function.\n * @param {V} [value] - The `value` parameter is an optional parameter that represents the value\n * associated with the key in the node. It is not required and can be omitted if you only need to\n * create a node with a key.\n * @param {RBTNColor} [color=BLACK] - The \"color\" parameter is used to specify the color of the node\n * in a Red-Black Tree. It can have two possible values: \"RED\" or \"BLACK\". By default, the color is\n * set to \"BLACK\" if not specified.\n * @returns A new instance of a RedBlackTreeNode with the specified key, value, and color is being\n * returned.\n */\n override createNode(key: K, value?: V, color: RBTNColor = 'BLACK'): RedBlackTreeNode<K, V> {\n return new RedBlackTreeNode<K, V>(key, this._isMapMode ? undefined : value, color);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a new Red-Black Tree with the specified options.\n * @param [options] - The `options` parameter is an optional object that contains additional\n * configuration options for creating the Red-Black Tree. It has the following properties:\n * @returns a new instance of a RedBlackTree object.\n */\n override createTree(options?: RedBlackTreeOptions<K, V, R>) {\n return new RedBlackTree<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n isMapMode: this._isMapMode,\n specifyComparable: this._specifyComparable,\n toEntryFn: this._toEntryFn,\n ...options\n });\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if the input is an instance of the RedBlackTreeNode class.\n * @param {K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be of type `R` or `K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`.\n * @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is\n * an instance of the `RedBlackTreeNode` class.\n */\n override isNode(\n keyNodeOrEntry: K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is RedBlackTreeNode<K, V> {\n return keyNodeOrEntry instanceof RedBlackTreeNode;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The \"clear\" function sets the root node of a data structure to a sentinel value and resets the\n * size counter to zero.\n */\n override clear() {\n super.clear();\n this._root = this.NIL;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function adds a new node to a binary search tree and returns true if the node was successfully\n * added.\n * @param {K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can accept a value of type `R` or `K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`.\n * @param {V} [value] - The `value` parameter is an optional value that you want to associate with\n * the key in the data structure. It represents the value that you want to add or update in the data\n * structure.\n * @returns The method is returning a boolean value. If a new node is successfully added to the tree,\n * the method returns true. If the node already exists and its value is updated, the method also\n * returns true. If the node cannot be added or updated, the method returns false.\n */\n override add(\n keyNodeOrEntry: K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V\n ): boolean {\n const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);\n if (!this.isRealNode(newNode)) return false;\n\n const insertStatus = this._insert(newNode);\n\n if (insertStatus === 'CREATED') {\n // Ensure the root is black\n if (this.isRealNode(this._root)) {\n this._root.color = 'BLACK';\n } else {\n return false;\n }\n if (this._isMapMode) this._setValue(newNode.key, newValue);\n this._size++;\n return true;\n }\n if (insertStatus === 'UPDATED') {\n if (this._isMapMode) this._setValue(newNode.key, newValue);\n return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function overrides the delete method in a binary tree data structure to remove a node based on\n * a given predicate and maintain the binary search tree properties.\n * @param {K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The `keyNodeOrEntry`\n * parameter in the `override delete` method is used to specify the condition or key based on which a\n * node should be deleted from the binary tree. It can be a key, a node, an entry, or a predicate\n * function that determines which node(s) should be deleted.\n * @returns The `override delete` method is returning an array of `BinaryTreeDeleteResult<RedBlackTreeNode<K, V>>`\n * objects. Each object in the array contains information about the deleted node and whether\n * balancing is needed.\n */\n override delete(\n keyNodeOrEntry: K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): BinaryTreeDeleteResult<RedBlackTreeNode<K, V>>[] {\n if (keyNodeOrEntry === null) return [];\n\n const results: BinaryTreeDeleteResult<RedBlackTreeNode<K, V>>[] = [];\n let nodeToDelete: OptNode<RedBlackTreeNode<K, V>>;\n if (this._isPredicate(keyNodeOrEntry)) nodeToDelete = this.getNode(keyNodeOrEntry);\n else nodeToDelete = this.isRealNode(keyNodeOrEntry) ? keyNodeOrEntry : this.getNode(keyNodeOrEntry);\n\n if (!nodeToDelete) {\n return results;\n }\n\n let originalColor = nodeToDelete.color;\n let replacementNode: RedBlackTreeNode<K, V> | undefined;\n\n if (!this.isRealNode(nodeToDelete.left)) {\n if (nodeToDelete.right !== null) {\n replacementNode = nodeToDelete.right;\n this._transplant(nodeToDelete, nodeToDelete.right);\n }\n } else if (!this.isRealNode(nodeToDelete.right)) {\n replacementNode = nodeToDelete.left;\n this._transplant(nodeToDelete, nodeToDelete.left);\n } else {\n const successor = this.getLeftMost(node => node, nodeToDelete.right);\n if (successor) {\n originalColor = successor.color;\n if (successor.right !== null) replacementNode = successor.right;\n\n if (successor.parent === nodeToDelete) {\n if (this.isRealNode(replacementNode)) {\n replacementNode.parent = successor;\n }\n } else {\n if (successor.right !== null) {\n this._transplant(successor, successor.right);\n successor.right = nodeToDelete.right;\n }\n if (this.isRealNode(successor.right)) {\n successor.right.parent = successor;\n }\n }\n\n this._transplant(nodeToDelete, successor);\n successor.left = nodeToDelete.left;\n if (this.isRealNode(successor.left)) {\n successor.left.parent = successor;\n }\n successor.color = nodeToDelete.color;\n }\n }\n if (this._isMapMode) this._store.delete(nodeToDelete.key);\n this._size--;\n\n // If the original color was black, fix the tree\n if (originalColor === 'BLACK') {\n this._deleteFixup(replacementNode);\n }\n\n results.push({ deleted: nodeToDelete, needBalanced: undefined });\n\n return results;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function in TypeScript overrides the default behavior to create a new Red-Black Tree by\n * applying a callback to each entry in the original tree.\n * @param callback - A function that will be called for each entry in the tree, with parameters\n * representing the key, value, index, and the tree itself. It should return an entry for the new\n * tree.\n * @param [options] - The `options` parameter in the `map` method is of type `RedBlackTreeOptions<MK, MV,\n * MR>`. This parameter allows you to specify additional options or configurations for the Red-Black\n * Tree that will be created during the mapping process. These options could include things like\n * custom comparators\n * @param {any} [thisArg] - The `thisArg` parameter in the `override map` function is used to specify\n * the value of `this` when executing the `callback` function. It allows you to set the context\n * (value of `this`) for the callback function. This can be useful when you want to access properties\n * or\n * @returns A new Red-Black Tree is being returned, where each entry has been transformed using the\n * provided callback function.\n */\n override map(\n callback: EntryCallback<K, V | undefined, [MK, MV]>,\n options?: RedBlackTreeOptions<MK, MV, MR>,\n thisArg?: any\n ): RedBlackTree<MK, MV, MR> {\n const newTree = new RedBlackTree<MK, MV, MR>([], options);\n let index = 0;\n for (const [key, value] of this) {\n newTree.add(callback.call(thisArg, key, value, index++, this));\n }\n return newTree;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `clone` overrides the default cloning behavior to create a deep copy of a tree\n * structure.\n * @returns The `cloned` object is being returned.\n */\n override clone() {\n const cloned = this.createTree();\n this._clone(cloned);\n return cloned;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function sets the root of a tree-like structure and updates the parent property of the new\n * root.\n * @param {RedBlackTreeNode<K, V> | undefined} v - v is a parameter of type RedBlackTreeNode<K, V> or undefined.\n */\n protected override _setRoot(v: RedBlackTreeNode<K, V> | undefined) {\n if (v) {\n v.parent = undefined;\n }\n this._root = v;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function replaces an old node with a new node while preserving the color of the old node.\n * @param {RedBlackTreeNode<K, V>} oldNode - The `oldNode` parameter represents the node that needs to be replaced in\n * the data structure.\n * @param {RedBlackTreeNode<K, V>} newNode - The `newNode` parameter is of type `RedBlackTreeNode<K, V>`, which represents a node in a\n * data structure.\n * @returns The method is returning the result of calling the `_replaceNode` method from the\n * superclass, with the `oldNode` and `newNode` parameters.\n */\n protected override _replaceNode(\n oldNode: RedBlackTreeNode<K, V>,\n newNode: RedBlackTreeNode<K, V>\n ): RedBlackTreeNode<K, V> {\n newNode.color = oldNode.color;\n\n return super._replaceNode(oldNode, newNode);\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The `_insert` function inserts a node into a binary search tree and performs necessary fix-ups to\n * maintain the red-black tree properties.\n * @param {RedBlackTreeNode<K, V>} node - The `node` parameter represents the node that needs to be inserted into the\n * binary search tree.\n * @returns a string value indicating the result of the insertion operation. It can return either\n * 'UPDATED' if the node with the same key already exists and was updated, or 'CREATED' if a new node\n * was created and inserted into the tree.\n */\n protected _insert(node: RedBlackTreeNode<K, V>): CRUD {\n let current = this.root;\n let parent: RedBlackTreeNode<K, V> | undefined = undefined;\n\n while (this.isRealNode(current)) {\n parent = current;\n const compared = this._compare(node.key, current.key);\n if (compared < 0) {\n current = current.left ?? this.NIL;\n } else if (compared > 0) {\n current = current.right ?? this.NIL;\n } else {\n this._replaceNode(current, node);\n return 'UPDATED';\n }\n }\n\n node.parent = parent;\n\n if (!parent) {\n this._setRoot(node);\n } else if (this._compare(node.key, parent.key) < 0) {\n parent.left = node;\n } else {\n parent.right = node;\n }\n\n node.left = this.NIL;\n node.right = this.NIL;\n node.color = 'RED';\n\n this._insertFixup(node);\n return 'CREATED';\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_transplant` is used to replace a node `u` with another node `v` in a binary tree.\n * @param {RedBlackTreeNode<K, V>} u - The parameter \"u\" represents a node in a binary tree.\n * @param {RedBlackTreeNode<K, V> | undefined} v - The parameter `v` is of type `RedBlackTreeNode<K, V> | undefined`, which means it can\n * either be a `RedBlackTreeNode<K, V>` object or `undefined`.\n */\n protected _transplant(u: RedBlackTreeNode<K, V>, v: RedBlackTreeNode<K, V> | undefined): void {\n if (!u.parent) {\n this._setRoot(v);\n } else if (u === u.parent.left) {\n u.parent.left = v;\n } else {\n u.parent.right = v;\n }\n\n if (v) {\n v.parent = u.parent;\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The `_insertFixup` function is used to fix the Red-Black Tree after inserting a new node.\n * @param {RedBlackTreeNode<K, V> | undefined} z - The parameter `z` represents a node in the Red-Black Tree data\n * structure. It can either be a valid node or `undefined`.\n */\n protected _insertFixup(z: RedBlackTreeNode<K, V> | undefined): void {\n // Continue fixing the tree as long as the parent of z is red\n while (z?.parent?.color === 'RED') {\n // Check if the parent of z is the left child of its parent\n if (z.parent === z.parent.parent?.left) {\n // Case 1: The uncle (y) of z is red\n const y = z.parent.parent.right;\n if (y?.color === 'RED') {\n // Set colors to restore properties of Red-Black Tree\n z.parent.color = 'BLACK';\n y.color = 'BLACK';\n z.parent.parent.color = 'RED';\n // Move up the tree to continue fixing\n z = z.parent.parent;\n } else {\n // Case 2: The uncle (y) of z is black, and z is a right child\n if (z === z.parent.right) {\n // Perform a left rotation to transform the case into Case 3\n z = z.parent;\n this._leftRotate(z);\n }\n\n // Case 3: The uncle (y) of z is black, and z is a left child\n // Adjust colors and perform a right rotation\n if (z && this.isRealNode(z.parent) && this.isRealNode(z.parent.parent)) {\n z.parent.color = 'BLACK';\n z.parent.parent.color = 'RED';\n this._rightRotate(z.parent.parent);\n }\n }\n } else {\n // Symmetric case for the right child (left and right exchanged)\n // Follow the same logic as above with left and right exchanged\n const y: RedBlackTreeNode<K, V> | undefined = z?.parent?.parent?.left ?? undefined;\n if (y?.color === 'RED') {\n z.parent.color = 'BLACK';\n y.color = 'BLACK';\n z.parent.parent!.color = 'RED';\n z = z.parent.parent;\n } else {\n if (z === z.parent.left) {\n z = z.parent;\n this._rightRotate(z);\n }\n\n if (z && this.isRealNode(z.parent) && this.isRealNode(z.parent.parent)) {\n z.parent.color = 'BLACK';\n z.parent.parent.color = 'RED';\n this._leftRotate(z.parent.parent);\n }\n }\n }\n }\n\n // Ensure that the root is black after fixing\n if (this.isRealNode(this._root)) this._root.color = 'BLACK';\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The `_deleteFixup` function is used to fix the red-black tree after a node deletion by adjusting\n * the colors and performing rotations.\n * @param {RedBlackTreeNode<K, V> | undefined} node - The `node` parameter represents a node in a binary tree. It can\n * be either a valid node object or `undefined`.\n * @returns The function does not return any value. It has a return type of `void`, which means it\n * does not return anything.\n */\n protected _deleteFixup(node: RedBlackTreeNode<K, V> | undefined): void {\n // Early exit condition\n if (!node || node === this.root || node.color === 'BLACK') {\n if (node) {\n node.color = 'BLACK'; // Ensure the final node is black\n }\n return;\n }\n\n while (node && node !== this.root && node.color === 'BLACK') {\n const parent: RedBlackTreeNode<K, V> | undefined = node.parent;\n\n if (!parent) {\n break; // Ensure the loop terminates if there's an issue with the tree structure\n }\n\n if (node === parent.left) {\n let sibling = parent.right;\n\n // Cases 1 and 2: Sibling is red or both children of sibling are black\n if (sibling?.color === 'RED') {\n sibling.color = 'BLACK';\n parent.color = 'RED';\n this._leftRotate(parent);\n sibling = parent.right;\n }\n\n // Case 3: Sibling's left child is black\n if ((sibling?.left?.color ?? 'BLACK') === 'BLACK') {\n if (sibling) sibling.color = 'RED';\n node = parent;\n } else {\n // Case 4: Adjust colors and perform a right rotation\n if (sibling?.left) sibling.left.color = 'BLACK';\n if (sibling) sibling.color = parent.color;\n parent.color = 'BLACK';\n this._rightRotate(parent);\n node = this.root;\n }\n } else {\n // Symmetric case for the right child (left and right exchanged)\n let sibling = parent.left;\n\n // Cases 1 and 2: Sibling is red or both children of sibling are black\n if (sibling?.color === 'RED') {\n sibling.color = 'BLACK';\n if (parent) parent.color = 'RED';\n this._rightRotate(parent);\n if (parent) sibling = parent.left;\n }\n\n // Case 3: Sibling's left child is black\n if ((sibling?.right?.color ?? 'BLACK') === 'BLACK') {\n if (sibling) sibling.color = 'RED';\n node = parent;\n } else {\n // Case 4: Adjust colors and perform a left rotation\n if (sibling?.right) sibling.right.color = 'BLACK';\n if (sibling) sibling.color = parent.color;\n if (parent) parent.color = 'BLACK';\n this._leftRotate(parent);\n node = this.root;\n }\n }\n }\n\n // Ensure that the final node (possibly the root) is black\n if (node) {\n node.color = 'BLACK';\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_leftRotate` function performs a left rotation on a given node in a binary tree.\n * @param {RedBlackTreeNode<K, V> | undefined} x - The parameter `x` is of type `RedBlackTreeNode<K, V> | undefined`. It represents a\n * node in a binary tree or `undefined` if there is no node.\n * @returns void, which means it does not return any value.\n */\n protected _leftRotate(x: RedBlackTreeNode<K, V> | undefined): void {\n if (!x || !x.right) {\n return;\n }\n\n const y = x.right;\n x.right = y.left;\n\n if (this.isRealNode(y.left)) {\n y.left.parent = x;\n }\n\n y.parent = x.parent;\n\n if (!x.parent) {\n this._setRoot(y);\n } else if (x === x.parent.left) {\n x.parent.left = y;\n } else {\n x.parent.right = y;\n }\n\n y.left = x;\n x.parent = y;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_rightRotate` function performs a right rotation on a given node in a binary tree.\n * @param {RedBlackTreeNode<K, V> | undefined} y - The parameter `y` is of type `RedBlackTreeNode<K, V> | undefined`. It represents a\n * node in a binary tree or `undefined` if there is no node.\n * @returns void, which means it does not return any value.\n */\n protected _rightRotate(y: RedBlackTreeNode<K, V> | undefined): void {\n if (!y || !y.left) {\n return;\n }\n\n const x = y.left;\n y.left = x.right;\n\n if (this.isRealNode(x.right)) {\n x.right.parent = y;\n }\n\n x.parent = y.parent;\n\n if (!y.parent) {\n this._setRoot(x);\n } else if (y === y.parent.left) {\n y.parent.left = x;\n } else {\n y.parent.right = x;\n }\n\n x.right = y;\n y.parent = x;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport { AVLTreeMultiMapOptions, BTNOptKeyOrNull } from '../../types';\nimport { AVLTree, AVLTreeNode } from './avl-tree';\nimport { IBinaryTree } from '../../interfaces';\n\nexport class AVLTreeMultiMapNode<K = any, V = any> extends AVLTreeNode<K, V[]> {\n override parent?: AVLTreeMultiMapNode<K, V> = undefined;\n\n /**\n * This TypeScript constructor initializes an object with a key of type K and an array of values of\n * type V.\n * @param {K} key - The `key` parameter is typically used to store a unique identifier or key for the\n * data being stored in the data structure. It helps in quickly accessing or retrieving the\n * associated value in the data structure.\n * @param {V[]} value - The `value` parameter in the constructor represents an array of values of\n * type `V`.\n */\n constructor(key: K, value: V[]) {\n super(key, value);\n }\n\n override _left?: AVLTreeMultiMapNode<K, V> | null | undefined = undefined;\n\n override get left(): AVLTreeMultiMapNode<K, V> | null | undefined {\n return this._left;\n }\n\n override set left(v: AVLTreeMultiMapNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._left = v;\n }\n\n override _right?: AVLTreeMultiMapNode<K, V> | null | undefined = undefined;\n\n override get right(): AVLTreeMultiMapNode<K, V> | null | undefined {\n return this._right;\n }\n\n override set right(v: AVLTreeMultiMapNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n}\n\n/**\n *\n */\nexport class AVLTreeMultiMap<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends AVLTree<K, V[], R, MK, MV[], MR>\n implements IBinaryTree<K, V[], R, MK, MV, MR>\n{\n /**\n * The constructor initializes an AVLTreeMultiMap with the provided keys, nodes, entries, or raw data\n * and options.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an\n * iterable that can contain either key-value pairs represented as `BTNRep<K, V[],\n * AVLTreeMultiMapNode<K, V>>` or raw data represented as `R`. This parameter is used to initialize\n * the AVLTreeMulti\n * @param [options] - The `options` parameter in the constructor is of type\n * `AVLTreeMultiMapOptions<K, V[], R>`. It is an optional parameter that allows you to specify\n * additional options for configuring the AVLTreeMultiMap instance.\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | R\n > = [],\n options?: AVLTreeMultiMapOptions<K, V[], R>\n ) {\n super([], { ...options, isMapMode: true });\n if (keysNodesEntriesOrRaws) {\n this.addMany(keysNodesEntriesOrRaws);\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `createTree` in TypeScript overrides the creation of an AVLTreeMultiMap with\n * specified options.\n * @param [options] - The `options` parameter in the `createTree` function is of type\n * `AVLTreeMultiMapOptions<K, V[], R>`. This means it is an object that can have properties of type\n * `K`, `V[]`, and `R`. The function creates a new `AVL\n * @returns The `createTree` method is returning a new instance of `AVLTreeMultiMap` with the\n * provided options.\n */\n override createTree(options?: AVLTreeMultiMapOptions<K, V[], R>) {\n return new AVLTreeMultiMap<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n specifyComparable: this._specifyComparable,\n toEntryFn: this._toEntryFn,\n isReverse: this._isReverse,\n isMapMode: this._isMapMode,\n ...options\n });\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `createNode` function in TypeScript overrides the default implementation to create a new\n * AVLTreeMultiMapNode with a specified key and value array.\n * @param {K} key - The `key` parameter represents the key of the node being created in the\n * AVLTreeMultiMap.\n * @param {V[]} value - The `value` parameter in the `createNode` method represents an array of\n * values associated with a specific key in the AVLTreeMultiMapNode. If no value is provided when\n * calling the method, an empty array `[]` is used as the default value.\n * @returns An AVLTreeMultiMapNode object is being returned, with the specified key and value. If the\n * AVLTreeMultiMap is in map mode, an empty array is used as the value, otherwise the provided value\n * array is used.\n */\n override createNode(key: K, value: V[] = []): AVLTreeMultiMapNode<K, V> {\n return new AVLTreeMultiMapNode<K, V>(key, this._isMapMode ? [] : value);\n }\n\n override add(\n keyNodeOrEntry: K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined\n ): boolean;\n\n override add(key: K, value: V): boolean;\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `add` in this TypeScript code overrides the superclass method to add key-value pairs\n * to an AVLTreeMultiMap, handling different input types and scenarios.\n * @param [key] - The `key` parameter in the `override add` method represents the key of the entry to\n * be added to the AVLTreeMultiMap. It can be of type `K`, which is the key type of the map. The key\n * can be a single key value, a node of the AVLTree\n * @param {V[]} [values] - The `values` parameter in the `add` method represents an array of values\n * that you want to add to the AVLTreeMultiMap. It can contain one or more values associated with a\n * specific key.\n * @returns The `add` method is returning a boolean value, which indicates whether the operation was\n * successful or not.\n */\n override add(\n keyNodeOrEntry: K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | K,\n value?: V\n ): boolean {\n if (this.isRealNode(keyNodeOrEntry)) return super.add(keyNodeOrEntry);\n\n const _commonAdd = (key?: BTNOptKeyOrNull<K>, values?: V[]) => {\n if (key === undefined || key === null) return false;\n\n const _addToValues = () => {\n const existingValues = this.get(key);\n if (existingValues !== undefined && values !== undefined) {\n for (const value of values) existingValues.push(value);\n return true;\n }\n return false;\n };\n\n const _addByNode = () => {\n const existingNode = this.getNode(key);\n if (this.isRealNode(existingNode)) {\n const existingValues = this.get(existingNode);\n if (existingValues === undefined) {\n super.add(key, values);\n return true;\n }\n if (values !== undefined) {\n for (const value of values) existingValues.push(value);\n return true;\n } else {\n return false;\n }\n } else {\n return super.add(key, values);\n }\n };\n\n if (this._isMapMode) {\n return _addByNode() || _addToValues();\n }\n return _addToValues() || _addByNode();\n };\n\n if (this.isEntry(keyNodeOrEntry)) {\n const [key, values] = keyNodeOrEntry;\n return _commonAdd(key, value !== undefined ? [value] : values);\n }\n\n return _commonAdd(keyNodeOrEntry, value !== undefined ? [value] : undefined);\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `deleteValue` removes a specific value from a key in an AVLTreeMultiMap data\n * structure and deletes the entire node if no values are left for that key.\n * @param {K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | K} keyNodeOrEntry - The `keyNodeOrEntry`\n * parameter in the `deleteValue` function can be either a `BTNRep` object representing a key-value\n * pair in the AVLTreeMultiMapNode, or just the key itself.\n * @param {V} value - The `value` parameter in the `deleteValue` function represents the specific\n * value that you want to delete from the multi-map data structure associated with a particular key.\n * The function checks if the value exists in the array of values associated with the key, and if\n * found, removes it from the array.\n * @returns The `deleteValue` function returns a boolean value. It returns `true` if the specified\n * `value` was successfully deleted from the array of values associated with the `keyNodeOrEntry`. If\n * the value was not found in the array, it returns `false`.\n */\n deleteValue(\n keyNodeOrEntry: K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | K,\n value: V\n ): boolean {\n const values = this.get(keyNodeOrEntry);\n if (Array.isArray(values)) {\n const index = values.indexOf(value);\n if (index === -1) return false;\n values.splice(index, 1);\n\n // If no values left, remove the entire node\n if (values.length === 0) this.delete(keyNodeOrEntry);\n\n return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `clone` overrides the default cloning behavior to create a deep copy of a tree\n * structure.\n * @returns A cloned tree object is being returned.\n */\n override clone() {\n const cloned = this.createTree();\n this._clone(cloned);\n return cloned;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { BTNOptKeyOrNull, TreeMultiMapOptions } from '../../types';\nimport { RedBlackTree, RedBlackTreeNode } from './red-black-tree';\nimport { IBinaryTree } from '../../interfaces';\n\nexport class TreeMultiMapNode<K = any, V = any> extends RedBlackTreeNode<K, V[]> {\n override parent?: TreeMultiMapNode<K, V> = undefined;\n\n /**\n * This TypeScript constructor initializes an object with a key of type K and an array of values of\n * type V.\n * @param {K} key - The `key` parameter is typically used to store a unique identifier or key for the\n * data being stored in the data structure. It helps in quickly accessing or retrieving the\n * associated value in the data structure.\n * @param {V[]} value - The `value` parameter in the constructor represents an array of values of\n * type `V`.\n */\n constructor(key: K, value?: V[]) {\n super(key, value);\n }\n\n override _left?: TreeMultiMapNode<K, V> | null | undefined = undefined;\n\n override get left(): TreeMultiMapNode<K, V> | null | undefined {\n return this._left;\n }\n\n override set left(v: TreeMultiMapNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._left = v;\n }\n\n override _right?: TreeMultiMapNode<K, V> | null | undefined = undefined;\n\n override get right(): TreeMultiMapNode<K, V> | null | undefined {\n return this._right;\n }\n\n override set right(v: TreeMultiMapNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n}\n\n/**\n *\n * @example\n * // players ranked by score with their equipment\n * type Equipment = {\n * name: string; // Equipment name\n * quality: 'legendary' | 'epic' | 'rare' | 'common';\n * level: number;\n * };\n *\n * type Player = {\n * name: string;\n * score: number;\n * equipments: Equipment[];\n * };\n *\n * // Mock player data with their scores and equipment\n * const players: Player[] = [\n * {\n * name: 'DragonSlayer',\n * score: 8750,\n * equipments: [\n * { name: 'AWM', quality: 'legendary', level: 85 },\n * { name: 'Level 3 Helmet', quality: 'epic', level: 80 },\n * { name: 'Extended Quickdraw Mag', quality: 'rare', level: 75 },\n * { name: 'Compensator', quality: 'epic', level: 78 },\n * { name: 'Vertical Grip', quality: 'rare', level: 72 }\n * ]\n * },\n * {\n * name: 'ShadowNinja',\n * score: 7200,\n * equipments: [\n * { name: 'M416', quality: 'epic', level: 75 },\n * { name: 'Ghillie Suit', quality: 'rare', level: 70 },\n * { name: 'Red Dot Sight', quality: 'common', level: 65 },\n * { name: 'Extended QuickDraw Mag', quality: 'rare', level: 68 }\n * ]\n * },\n * {\n * name: 'RuneMaster',\n * score: 9100,\n * equipments: [\n * { name: 'KAR98K', quality: 'legendary', level: 90 },\n * { name: 'Level 3 Vest', quality: 'legendary', level: 85 },\n * { name: 'Holographic Sight', quality: 'epic', level: 82 },\n * { name: 'Suppressor', quality: 'legendary', level: 88 },\n * { name: 'Level 3 Backpack', quality: 'epic', level: 80 }\n * ]\n * },\n * {\n * name: 'BattleKing',\n * score: 8500,\n * equipments: [\n * { name: 'AUG', quality: 'epic', level: 82 },\n * { name: 'Red Dot Sight', quality: 'rare', level: 75 },\n * { name: 'Extended Mag', quality: 'common', level: 70 },\n * { name: 'Tactical Stock', quality: 'rare', level: 76 }\n * ]\n * },\n * {\n * name: 'SniperElite',\n * score: 7800,\n * equipments: [\n * { name: 'M24', quality: 'legendary', level: 88 },\n * { name: 'Compensator', quality: 'epic', level: 80 },\n * { name: 'Scope 8x', quality: 'legendary', level: 85 },\n * { name: 'Level 2 Helmet', quality: 'rare', level: 75 }\n * ]\n * },\n * {\n * name: 'RushMaster',\n * score: 7500,\n * equipments: [\n * { name: 'Vector', quality: 'rare', level: 72 },\n * { name: 'Level 2 Helmet', quality: 'common', level: 65 },\n * { name: 'Quickdraw Mag', quality: 'common', level: 60 },\n * { name: 'Laser Sight', quality: 'rare', level: 68 }\n * ]\n * },\n * {\n * name: 'GhostWarrior',\n * score: 8200,\n * equipments: [\n * { name: 'SCAR-L', quality: 'epic', level: 78 },\n * { name: 'Extended Quickdraw Mag', quality: 'rare', level: 70 },\n * { name: 'Holographic Sight', quality: 'epic', level: 75 },\n * { name: 'Suppressor', quality: 'rare', level: 72 },\n * { name: 'Vertical Grip', quality: 'common', level: 65 }\n * ]\n * },\n * {\n * name: 'DeathDealer',\n * score: 7300,\n * equipments: [\n * { name: 'SKS', quality: 'epic', level: 76 },\n * { name: 'Holographic Sight', quality: 'rare', level: 68 },\n * { name: 'Extended Mag', quality: 'common', level: 65 }\n * ]\n * },\n * {\n * name: 'StormRider',\n * score: 8900,\n * equipments: [\n * { name: 'MK14', quality: 'legendary', level: 92 },\n * { name: 'Level 3 Backpack', quality: 'legendary', level: 85 },\n * { name: 'Scope 8x', quality: 'epic', level: 80 },\n * { name: 'Suppressor', quality: 'legendary', level: 88 },\n * { name: 'Tactical Stock', quality: 'rare', level: 75 }\n * ]\n * },\n * {\n * name: 'CombatLegend',\n * score: 7600,\n * equipments: [\n * { name: 'UMP45', quality: 'rare', level: 74 },\n * { name: 'Level 2 Vest', quality: 'common', level: 67 },\n * { name: 'Red Dot Sight', quality: 'common', level: 62 },\n * { name: 'Extended Mag', quality: 'rare', level: 70 }\n * ]\n * }\n * ];\n *\n * // Create a TreeMultiMap for player rankings\n * const playerRankings = new TreeMultiMap<number, Equipment, Player>(players, {\n * toEntryFn: ({ score, equipments }) => [score, equipments],\n * isMapMode: false\n * });\n *\n * const topPlayersEquipments = playerRankings.rangeSearch([8900, 10000], node => playerRankings.get(node));\n * console.log(topPlayersEquipments); // [\n * // [\n * // {\n * // name: 'MK14',\n * // quality: 'legendary',\n * // level: 92\n * // },\n * // { name: 'Level 3 Backpack', quality: 'legendary', level: 85 },\n * // {\n * // name: 'Scope 8x',\n * // quality: 'epic',\n * // level: 80\n * // },\n * // { name: 'Suppressor', quality: 'legendary', level: 88 },\n * // {\n * // name: 'Tactical Stock',\n * // quality: 'rare',\n * // level: 75\n * // }\n * // ],\n * // [\n * // { name: 'KAR98K', quality: 'legendary', level: 90 },\n * // {\n * // name: 'Level 3 Vest',\n * // quality: 'legendary',\n * // level: 85\n * // },\n * // { name: 'Holographic Sight', quality: 'epic', level: 82 },\n * // {\n * // name: 'Suppressor',\n * // quality: 'legendary',\n * // level: 88\n * // },\n * // { name: 'Level 3 Backpack', quality: 'epic', level: 80 }\n * // ]\n * // ]\n */\nexport class TreeMultiMap<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends RedBlackTree<K, V[], R, MK, MV[], MR>\n implements IBinaryTree<K, V[], R, MK, MV, MR>\n{\n /**\n * The constructor initializes an TreeMultiMap with the provided keys, nodes, entries, or raw data\n * and options.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an\n * iterable that can contain either key-value pairs represented as `BTNRep<K, V[],\n * TreeMultiMapNode<K, V>>` or raw data represented as `R`. This parameter is used to initialize\n * the RedBlackTreeMulti\n * @param [options] - The `options` parameter in the constructor is of type\n * `TreeMultiMapOptions<K, V[], R>`. It is an optional parameter that allows you to specify\n * additional options for configuring the TreeMultiMap instance.\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | TreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | R\n > = [],\n options?: TreeMultiMapOptions<K, V[], R>\n ) {\n super([], { ...options });\n if (keysNodesEntriesOrRaws) {\n this.addMany(keysNodesEntriesOrRaws);\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `createTree` function in TypeScript overrides the default implementation to create a new\n * TreeMultiMap with specified options.\n * @param [options] - The `options` parameter in the `createTree` method is of type\n * `TreeMultiMapOptions<K, V[], R>`. This parameter allows you to pass additional configuration\n * options when creating a new `TreeMultiMap` instance. It includes properties such as\n * `iterationType`, `specifyComparable\n * @returns A new instance of `TreeMultiMap` is being returned, with an empty array as the initial\n * data and the provided options merged with the existing properties of the current object.\n */\n override createTree(options?: TreeMultiMapOptions<K, V[], R>) {\n return new TreeMultiMap<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n specifyComparable: this._specifyComparable,\n toEntryFn: this._toEntryFn,\n isReverse: this._isReverse,\n isMapMode: this._isMapMode,\n ...options\n });\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `createNode` overrides the creation of a new TreeMultiMapNode with a specified key\n * and value array.\n * @param {K} key - The `key` parameter represents the key of the node being created in the\n * `TreeMultiMap`.\n * @param {V[]} value - The `value` parameter in the `createNode` method represents an array of\n * values associated with a specific key in the TreeMultiMap data structure.\n * @returns A new instance of `TreeMultiMapNode<K, V>` is being returned with the specified key and\n * value. If `_isMapMode` is true, an empty array is passed as the value, otherwise the provided\n * value is used.\n */\n override createNode(key: K, value: V[] = []): TreeMultiMapNode<K, V> {\n return new TreeMultiMapNode<K, V>(key, this._isMapMode ? [] : value);\n }\n\n override add(\n keyNodeOrEntry: K | TreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined\n ): boolean;\n\n override add(key: K, value: V): boolean;\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function overrides the add method to handle different types of input for a TreeMultiMap data\n * structure.\n * @param [key] - The `key` parameter in the `override add` method represents the key of the entry to\n * be added to the TreeMultiMap. It can be of type `K`, which is the key type of the TreeMultiMap, or\n * it can be a TreeMultiMapNode containing the key and its\n * @param {V[]} [values] - The `values` parameter in the `add` method represents an array of values\n * that you want to add to the TreeMultiMap. It can contain one or more values of type `V`.\n * @returns The `add` method is returning a boolean value, which indicates whether the operation was\n * successful or not.\n */\n override add(\n keyNodeOrEntry: K | TreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined,\n value?: V\n ): boolean {\n if (this.isRealNode(keyNodeOrEntry)) return super.add(keyNodeOrEntry);\n\n const _commonAdd = (key?: BTNOptKeyOrNull<K>, values?: V[]) => {\n if (key === undefined || key === null) return false;\n\n const _addToValues = () => {\n const existingValues = this.get(key);\n if (existingValues !== undefined && values !== undefined) {\n for (const value of values) existingValues.push(value);\n return true;\n }\n return false;\n };\n\n const _addByNode = () => {\n const existingNode = this.getNode(key);\n if (this.isRealNode(existingNode)) {\n const existingValues = this.get(existingNode);\n if (existingValues === undefined) {\n super.add(key, values);\n return true;\n }\n if (values !== undefined) {\n for (const value of values) existingValues.push(value);\n return true;\n } else {\n return false;\n }\n } else {\n return super.add(key, values);\n }\n };\n\n if (this._isMapMode) {\n return _addByNode() || _addToValues();\n }\n return _addToValues() || _addByNode();\n };\n\n if (this.isEntry(keyNodeOrEntry)) {\n const [key, values] = keyNodeOrEntry;\n return _commonAdd(key, value !== undefined ? [value] : values);\n }\n\n return _commonAdd(keyNodeOrEntry, value !== undefined ? [value] : undefined);\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `deleteValue` removes a specific value from a key in a TreeMultiMap data structure\n * and deletes the entire node if no values are left for that key.\n * @param {K | TreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined} keyNodeOrEntry - The `keyNodeOrEntry`\n * parameter in the `deleteValue` function can be either a `BTNRep` object containing a key and an\n * array of values, or just a key itself.\n * @param {V} value - The `value` parameter in the `deleteValue` function represents the specific\n * value that you want to remove from the multi-map data structure associated with a particular key.\n * The function checks if the value exists in the array of values associated with the key, and if\n * found, removes it from the array.\n * @returns The `deleteValue` function returns a boolean value - `true` if the specified `value` was\n * successfully deleted from the values associated with the `keyNodeOrEntry`, and `false` otherwise.\n */\n deleteValue(\n keyNodeOrEntry: K | TreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined,\n value: V\n ): boolean {\n const values = this.get(keyNodeOrEntry);\n if (Array.isArray(values)) {\n const index = values.indexOf(value);\n if (index === -1) return false;\n values.splice(index, 1);\n\n // If no values left, remove the entire node\n if (values.length === 0) this.delete(keyNodeOrEntry);\n\n return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `clone` overrides the default cloning behavior to create a deep copy of a tree\n * structure.\n * @returns The `cloned` object is being returned.\n */\n override clone() {\n const cloned = this.createTree();\n this._clone(cloned);\n return cloned;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type {\n BinaryTreeDeleteResult,\n BSTNOptKeyOrNode,\n EntryCallback,\n IterationType,\n OptNode,\n RBTNColor,\n TreeCounterOptions\n} from '../../types';\nimport { IBinaryTree } from '../../interfaces';\nimport { RedBlackTree, RedBlackTreeNode } from './red-black-tree';\n\nexport class TreeCounterNode<K = any, V = any> extends RedBlackTreeNode<K, V> {\n override parent?: TreeCounterNode<K, V> = undefined;\n\n /**\n * The constructor function initializes a Red-Black Tree node with a key, value, count, and color.\n * @param {K} key - The key parameter represents the key of the node in the Red-Black Tree. It is\n * used to identify and locate the node within the tree.\n * @param {V} [value] - The `value` parameter is an optional parameter that represents the value\n * associated with the key in the Red-Black Tree node. It is not required and can be omitted when\n * creating a new node.\n * @param [count=1] - The `count` parameter represents the number of occurrences of a particular key\n * in the Red-Black Tree. It is an optional parameter with a default value of 1.\n * @param {RBTNColor} [color=BLACK] - The `color` parameter is used to specify the color of the node\n * in a Red-Black Tree. It is optional and has a default value of `'BLACK'`.\n */\n constructor(key: K, value?: V, count = 1, color: RBTNColor = 'BLACK') {\n super(key, value, color);\n this.count = count;\n }\n\n override _left?: TreeCounterNode<K, V> | null | undefined = undefined;\n\n override get left(): TreeCounterNode<K, V> | null | undefined {\n return this._left;\n }\n\n override set left(v: TreeCounterNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._left = v;\n }\n\n override _right?: TreeCounterNode<K, V> | null | undefined = undefined;\n\n override get right(): TreeCounterNode<K, V> | null | undefined {\n return this._right;\n }\n\n override set right(v: TreeCounterNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n}\n\n/**\n *\n */\nexport class TreeCounter<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends RedBlackTree<K, V, R, MK, MV, MR>\n implements IBinaryTree<K, V, R, MK, MV, MR>\n{\n /**\n * The constructor function initializes a TreeCounter object with optional initial data.\n * @param keysNodesEntriesOrRaws - The parameter `keysNodesEntriesOrRaws` is an\n * iterable that can contain keys, nodes, entries, or raw elements. It is used to initialize the\n * TreeCounter with initial data.\n * @param [options] - The `options` parameter is an optional object that can be used to customize the\n * behavior of the `TreeCounter` constructor. It can include properties such as `compareKeys` and\n * `compareValues`, which are functions used to compare keys and values respectively.\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n > = [],\n options?: TreeCounterOptions<K, V, R>\n ) {\n super([], options);\n if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);\n }\n\n protected _count = 0;\n\n // TODO the _count is not accurate after nodes count modified\n /**\n * The function calculates the sum of the count property of all nodes in a tree structure.\n * @returns the sum of the count property of all nodes in the tree.\n */\n get count(): number {\n return this._count;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function calculates the sum of the count property of all nodes in a tree using depth-first\n * search.\n * @returns the sum of the count property of all nodes in the tree.\n */\n getComputedCount(): number {\n let sum = 0;\n this.dfs(node => (sum += node ? node.count : 0));\n return sum;\n }\n\n /**\n * The function creates a new TreeCounterNode with the specified key, value, color, and count.\n * @param {K} key - The key parameter represents the key of the node being created. It is of type K,\n * which is a generic type representing the type of keys in the tree.\n * @param {V} [value] - The `value` parameter is an optional parameter that represents the value\n * associated with the key in the node. It is of type `V`, which can be any data type.\n * @param {RBTNColor} [color=BLACK] - The color parameter is used to specify the color of the node in\n * a Red-Black Tree. It can have two possible values: 'RED' or 'BLACK'. The default value is 'BLACK'.\n * @param {number} [count] - The `count` parameter represents the number of occurrences of a key in\n * the tree. It is an optional parameter and is used to keep track of the number of values associated\n * with a key in the tree.\n * @returns A new instance of the TreeCounterNode class, casted as TreeCounterNode<K, V>.\n */\n override createNode(key: K, value?: V, color: RBTNColor = 'BLACK', count?: number): TreeCounterNode<K, V> {\n return new TreeCounterNode(key, this._isMapMode ? undefined : value, count, color) as TreeCounterNode<K, V>;\n }\n\n /**\n * The function creates a new instance of a TreeCounter with the specified options and returns it.\n * @param [options] - The `options` parameter is an optional object that contains additional\n * configuration options for creating the `TreeCounter`. It is of type `TreeCounterOptions<K, V,\n * R>`.\n * @returns a new instance of the `TreeCounter` class, with the provided options merged with the\n * existing `iterationType` property. The returned value is casted as `TREE`.\n */\n override createTree(options?: TreeCounterOptions<K, V, R>) {\n return new TreeCounter<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n specifyComparable: this._specifyComparable,\n isMapMode: this._isMapMode,\n toEntryFn: this._toEntryFn,\n ...options\n });\n }\n\n /**\n * The function checks if the input is an instance of the TreeCounterNode class.\n * @param {K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be of type `R` or `K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`.\n * @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is\n * an instance of the `TreeCounterNode` class.\n */\n override isNode(\n keyNodeOrEntry: K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is TreeCounterNode<K, V> {\n return keyNodeOrEntry instanceof TreeCounterNode;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The function overrides the add method of a class and adds a new node to a data structure, updating\n * the count and returning a boolean indicating success.\n * @param {K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The\n * `keyNodeOrEntry` parameter can accept one of the following types:\n * @param {V} [value] - The `value` parameter represents the value associated with the key in the\n * data structure. It is an optional parameter, so it can be omitted if not needed.\n * @param [count=1] - The `count` parameter represents the number of times the key-value pair should\n * be added to the data structure. By default, it is set to 1, meaning that if no value is provided\n * for `count`, the key-value pair will be added once.\n * @returns The method is returning a boolean value. It returns true if the addition of the new node\n * was successful, and false otherwise.\n */\n override add(\n keyNodeOrEntry: K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V,\n count = 1\n ): boolean {\n const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value, count);\n const orgCount = newNode?.count || 0;\n const isSuccessAdded = super.add(newNode, newValue);\n\n if (isSuccessAdded) {\n this._count += orgCount;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The function `delete` in TypeScript overrides the deletion operation in a binary tree data\n * structure, handling cases where nodes have children and maintaining balance in the tree.\n * @param {K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The `predicate`\n * parameter in the `delete` method is used to specify the condition or key based on which a node\n * should be deleted from the binary tree. It can be a key, a node, or an entry.\n * @param [ignoreCount=false] - The `ignoreCount` parameter in the `override delete` method is a\n * boolean flag that determines whether to ignore the count of nodes when performing deletion. If\n * `ignoreCount` is set to `true`, the method will delete the node regardless of its count. If\n * `ignoreCount` is `false\n * @returns The `override delete` method returns an array of `BinaryTreeDeleteResult<TreeCounterNode<K, V>>` objects.\n */\n override delete(\n keyNodeOrEntry: K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n ignoreCount = false\n ): BinaryTreeDeleteResult<TreeCounterNode<K, V>>[] {\n if (keyNodeOrEntry === null) return [];\n\n const results: BinaryTreeDeleteResult<TreeCounterNode<K, V>>[] = [];\n\n let nodeToDelete: OptNode<TreeCounterNode<K, V>>;\n if (this._isPredicate(keyNodeOrEntry)) nodeToDelete = this.getNode(keyNodeOrEntry);\n else nodeToDelete = this.isRealNode(keyNodeOrEntry) ? keyNodeOrEntry : this.getNode(keyNodeOrEntry);\n\n if (!nodeToDelete) {\n return results;\n }\n\n let originalColor = nodeToDelete.color;\n let replacementNode: TreeCounterNode<K, V> | undefined;\n\n if (!this.isRealNode(nodeToDelete.left)) {\n if (nodeToDelete.right !== null) replacementNode = nodeToDelete.right;\n if (ignoreCount || nodeToDelete.count <= 1) {\n if (nodeToDelete.right !== null) {\n this._transplant(nodeToDelete, nodeToDelete.right);\n this._count -= nodeToDelete.count;\n }\n } else {\n nodeToDelete.count--;\n this._count--;\n results.push({ deleted: nodeToDelete, needBalanced: undefined });\n return results;\n }\n } else if (!this.isRealNode(nodeToDelete.right)) {\n replacementNode = nodeToDelete.left;\n if (ignoreCount || nodeToDelete.count <= 1) {\n this._transplant(nodeToDelete, nodeToDelete.left);\n this._count -= nodeToDelete.count;\n } else {\n nodeToDelete.count--;\n this._count--;\n results.push({ deleted: nodeToDelete, needBalanced: undefined });\n return results;\n }\n } else {\n const successor = this.getLeftMost(node => node, nodeToDelete.right);\n if (successor) {\n originalColor = successor.color;\n if (successor.right !== null) replacementNode = successor.right;\n\n if (successor.parent === nodeToDelete) {\n if (this.isRealNode(replacementNode)) {\n replacementNode.parent = successor;\n }\n } else {\n if (ignoreCount || nodeToDelete.count <= 1) {\n if (successor.right !== null) {\n this._transplant(successor, successor.right);\n this._count -= nodeToDelete.count;\n }\n } else {\n nodeToDelete.count--;\n this._count--;\n results.push({ deleted: nodeToDelete, needBalanced: undefined });\n return results;\n }\n successor.right = nodeToDelete.right;\n if (this.isRealNode(successor.right)) {\n successor.right.parent = successor;\n }\n }\n if (ignoreCount || nodeToDelete.count <= 1) {\n this._transplant(nodeToDelete, successor);\n this._count -= nodeToDelete.count;\n } else {\n nodeToDelete.count--;\n this._count--;\n results.push({ deleted: nodeToDelete, needBalanced: undefined });\n return results;\n }\n successor.left = nodeToDelete.left;\n if (this.isRealNode(successor.left)) {\n successor.left.parent = successor;\n }\n successor.color = nodeToDelete.color;\n }\n }\n this._size--;\n\n // If the original color was black, fix the tree\n if (originalColor === 'BLACK') {\n this._deleteFixup(replacementNode);\n }\n\n results.push({ deleted: nodeToDelete, needBalanced: undefined });\n\n return results;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The \"clear\" function overrides the parent class's \"clear\" function and also resets the count to\n * zero.\n */\n override clear() {\n super.clear();\n this._count = 0;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(log n)\n *\n * The `perfectlyBalance` function takes a sorted array of nodes and builds a balanced binary search\n * tree using either a recursive or iterative approach.\n * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that\n * specifies the type of iteration to use when building the balanced binary search tree. It has a\n * default value of `this.iterationType`, which means it will use the iteration type specified by the\n * `iterationType` property of the current object.\n * @returns The function `perfectlyBalance` returns a boolean value. It returns `true` if the\n * balancing operation is successful, and `false` if there are no nodes to balance.\n */\n override perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {\n const sorted = this.dfs(node => node, 'IN'),\n n = sorted.length;\n if (sorted.length < 1) return false;\n\n this.clear();\n\n if (iterationType === 'RECURSIVE') {\n const buildBalanceBST = (l: number, r: number) => {\n if (l > r) return;\n const m = l + Math.floor((r - l) / 2);\n const midNode = sorted[m];\n if (this._isMapMode && midNode !== null) this.add(midNode.key, undefined, midNode.count);\n else if (midNode !== null) this.add(midNode.key, midNode.value, midNode.count);\n buildBalanceBST(l, m - 1);\n buildBalanceBST(m + 1, r);\n };\n\n buildBalanceBST(0, n - 1);\n return true;\n } else {\n const stack: [[number, number]] = [[0, n - 1]];\n while (stack.length > 0) {\n const popped = stack.pop();\n if (popped) {\n const [l, r] = popped;\n if (l <= r) {\n const m = l + Math.floor((r - l) / 2);\n const midNode = sorted[m];\n if (this._isMapMode && midNode !== null) this.add(midNode.key, undefined, midNode.count);\n else if (midNode !== null) this.add(midNode.key, midNode.value, midNode.count);\n stack.push([m + 1, r]);\n stack.push([l, m - 1]);\n }\n }\n }\n return true;\n }\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The function overrides the clone method to create a deep copy of a tree object.\n * @returns The `clone()` method is returning a cloned instance of the `TREE` object.\n */\n override clone() {\n const cloned = this.createTree();\n this.bfs(node => cloned.add(node === null ? null : node.key, undefined, node === null ? 0 : node.count));\n if (this._isMapMode) cloned._store = this._store;\n return cloned;\n }\n\n /**\n * The `map` function in TypeScript overrides the default behavior to create a new TreeCounter with\n * modified entries based on a provided callback.\n * @param callback - The `callback` parameter is a function that will be called for each entry in the\n * map. It takes four arguments:\n * @param [options] - The `options` parameter in the `override map` function is of type\n * `TreeCounterOptions<MK, MV, MR>`. This parameter allows you to provide additional configuration\n * options when creating a new `TreeCounter` instance within the `map` function. These options could\n * include things like\n * @param {any} [thisArg] - The `thisArg` parameter in the `override map` function is used to specify\n * the value of `this` when executing the `callback` function. It allows you to set the context\n * (value of `this`) for the callback function when it is called within the `map` function. This\n * @returns A new TreeCounter instance is being returned, which is populated with entries generated\n * by the provided callback function.\n */\n override map(\n callback: EntryCallback<K, V | undefined, [MK, MV]>,\n options?: TreeCounterOptions<MK, MV, MR>,\n thisArg?: any\n ): TreeCounter<MK, MV, MR> {\n const newTree = new TreeCounter<MK, MV, MR>([], options);\n let index = 0;\n for (const [key, value] of this) {\n newTree.add(callback.call(thisArg, key, value, index++, this));\n }\n return newTree;\n }\n\n /**\n * The function `keyValueNodeEntryRawToNodeAndValue` takes in a key, value, and count and returns a\n * node based on the input.\n * @param {K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be of type `R` or `K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`.\n * @param {V} [value] - The `value` parameter is an optional value that represents the value\n * associated with the key in the node. It is used when creating a new node or updating the value of\n * an existing node.\n * @param [count=1] - The `count` parameter is an optional parameter that specifies the number of\n * times the key-value pair should be added to the data structure. If not provided, it defaults to 1.\n * @returns either a TreeCounterNode<K, V> object or undefined.\n */\n protected override _keyValueNodeOrEntryToNodeAndValue(\n keyNodeOrEntry: K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V,\n count = 1\n ): [TreeCounterNode<K, V> | undefined, V | undefined] {\n if (keyNodeOrEntry === undefined || keyNodeOrEntry === null) return [undefined, undefined];\n\n if (this.isNode(keyNodeOrEntry)) return [keyNodeOrEntry, value];\n\n if (this.isEntry(keyNodeOrEntry)) {\n const [key, entryValue] = keyNodeOrEntry;\n if (key === undefined || key === null) return [undefined, undefined];\n const finalValue = value ?? entryValue;\n return [this.createNode(key, finalValue, 'BLACK', count), finalValue];\n }\n\n return [this.createNode(keyNodeOrEntry, value, 'BLACK', count), value];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_swapProperties` function swaps the properties (key, value, count, color) between two nodes\n * in a binary search tree.\n * @param {R | BSTNOptKeyOrNode<K, TreeCounterNode<K, V>>} srcNode - The `srcNode` parameter represents the source node\n * that will be swapped with the `destNode`. It can be either an instance of the `R` class or an\n * instance of the `BSTNOptKeyOrNode<K, TreeCounterNode<K, V>>` class.\n * @param {R | BSTNOptKeyOrNode<K, TreeCounterNode<K, V>>} destNode - The `destNode` parameter represents the destination\n * node where the properties will be swapped with the source node.\n * @returns The method is returning the `destNode` after swapping its properties with the `srcNode`.\n * If either `srcNode` or `destNode` is undefined, it returns undefined.\n */\n protected override _swapProperties(\n srcNode: BSTNOptKeyOrNode<K, TreeCounterNode<K, V>>,\n destNode: BSTNOptKeyOrNode<K, TreeCounterNode<K, V>>\n ): TreeCounterNode<K, V> | undefined {\n srcNode = this.ensureNode(srcNode);\n destNode = this.ensureNode(destNode);\n if (srcNode && destNode) {\n const { key, value, count, color } = destNode;\n const tempNode = this.createNode(key, value, color, count);\n if (tempNode) {\n tempNode.color = color;\n\n destNode.key = srcNode.key;\n if (!this._isMapMode) destNode.value = srcNode.value;\n destNode.count = srcNode.count;\n destNode.color = srcNode.color;\n\n srcNode.key = tempNode.key;\n if (!this._isMapMode) srcNode.value = tempNode.value;\n srcNode.count = tempNode.count;\n srcNode.color = tempNode.color;\n }\n\n return destNode;\n }\n return undefined;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function replaces an old node with a new node and updates the count property of the new node.\n * @param {TreeCounterNode<K, V>} oldNode - The `oldNode` parameter is the node that you want to replace in the data\n * structure.\n * @param {TreeCounterNode<K, V>} newNode - The `newNode` parameter is an instance of the `TreeCounterNode<K, V>` class.\n * @returns The method is returning the result of calling the `_replaceNode` method from the\n * superclass, which is of type `TreeCounterNode<K, V>`.\n */\n protected override _replaceNode(\n oldNode: TreeCounterNode<K, V>,\n newNode: TreeCounterNode<K, V>\n ): TreeCounterNode<K, V> {\n newNode.count = oldNode.count + newNode.count;\n return super._replaceNode(oldNode, newNode);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type {\n AVLTreeCounterOptions,\n BinaryTreeDeleteResult,\n BSTNOptKeyOrNode,\n EntryCallback,\n IterationType\n} from '../../types';\nimport { IBinaryTree } from '../../interfaces';\nimport { AVLTree, AVLTreeNode } from './avl-tree';\n\nexport class AVLTreeCounterNode<K = any, V = any> extends AVLTreeNode<K, V> {\n override parent?: AVLTreeCounterNode<K, V> = undefined;\n\n /**\n * The constructor function initializes a BinaryTreeNode object with a key, value, and count.\n * @param {K} key - The `key` parameter is of type `K` and represents the unique identifier\n * of the binary tree node.\n * @param {V} [value] - The `value` parameter is an optional parameter of type `V`. It represents the value of the binary\n * tree node. If no value is provided, it will be `undefined`.\n * @param {number} [count=1] - The `count` parameter is a number that represents the number of times a particular value\n * occurs in a binary tree node. It has a default value of 1, which means that if no value is provided for the `count`\n * parameter when creating a new instance of the `BinaryTreeNode` class.\n */\n constructor(key: K, value?: V, count = 1) {\n super(key, value);\n this.count = count;\n }\n\n override _left?: AVLTreeCounterNode<K, V> | null | undefined = undefined;\n\n override get left(): AVLTreeCounterNode<K, V> | null | undefined {\n return this._left;\n }\n\n override set left(v: AVLTreeCounterNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._left = v;\n }\n\n override _right?: AVLTreeCounterNode<K, V> | null | undefined = undefined;\n\n override get right(): AVLTreeCounterNode<K, V> | null | undefined {\n return this._right;\n }\n\n override set right(v: AVLTreeCounterNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n}\n\n/**\n * The only distinction between a AVLTreeCounter and a AVLTree lies in the ability of the former to store duplicate nodes through the utilization of counters.\n */\nexport class AVLTreeCounter<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends AVLTree<K, V, R, MK, MV, MR>\n implements IBinaryTree<K, V, R, MK, MV, MR>\n{\n /**\n * The constructor initializes a new AVLTreeCounter object with optional initial elements.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter is an\n * iterable object that can contain either keys, nodes, entries, or raw elements.\n * @param [options] - The `options` parameter is an optional object that can be used to customize the\n * behavior of the AVLTreeCounter. It can include properties such as `compareKeys` and\n * `compareValues` functions to define custom comparison logic for keys and values, respectively.\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n > = [],\n options?: AVLTreeCounterOptions<K, V, R>\n ) {\n super([], options);\n if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);\n }\n\n protected _count = 0;\n\n /**\n * The function calculates the sum of the count property of all nodes in a tree using depth-first\n * search.\n * @returns the sum of the count property of all nodes in the tree.\n */\n get count(): number {\n return this._count;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function calculates the sum of the count property of all nodes in a tree using depth-first\n * search.\n * @returns the sum of the count property of all nodes in the tree.\n */\n getComputedCount(): number {\n let sum = 0;\n this.dfs(node => (sum += node.count));\n return sum;\n }\n\n /**\n * The function creates a new AVLTreeCounterNode with the specified key, value, and count.\n * @param {K} key - The key parameter represents the key of the node being created. It is of type K,\n * which is a generic type that can be replaced with any specific type when using the function.\n * @param {V} [value] - The `value` parameter is an optional parameter that represents the value\n * associated with the key in the node. It is of type `V`, which can be any data type.\n * @param {number} [count] - The `count` parameter represents the number of occurrences of a\n * key-value pair in the AVLTreeCounterNode. It is an optional parameter, so it can be omitted when\n * calling the `createNode` method. If provided, it specifies the initial count for the node.\n * @returns a new instance of the AVLTreeCounterNode class, casted as AVLTreeCounterNode<K, V>.\n */\n override createNode(key: K, value?: V, count?: number): AVLTreeCounterNode<K, V> {\n return new AVLTreeCounterNode(key, this._isMapMode ? undefined : value, count) as AVLTreeCounterNode<K, V>;\n }\n\n /**\n * The function creates a new AVLTreeCounter object with the specified options and returns it.\n * @param [options] - The `options` parameter is an optional object that contains additional\n * configuration options for creating the AVLTreeCounter. It can have the following properties:\n * @returns a new instance of the AVLTreeCounter class, with the specified options, as a TREE\n * object.\n */\n override createTree(options?: AVLTreeCounterOptions<K, V, R>) {\n return new AVLTreeCounter<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n isMapMode: this._isMapMode,\n specifyComparable: this._specifyComparable,\n toEntryFn: this._toEntryFn,\n isReverse: this._isReverse,\n ...options\n });\n }\n\n /**\n * The function checks if the input is an instance of AVLTreeCounterNode.\n * @param {K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be of type `R` or `K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`.\n * @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is\n * an instance of the `AVLTreeCounterNode` class.\n */\n override isNode(\n keyNodeOrEntry: K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is AVLTreeCounterNode<K, V> {\n return keyNodeOrEntry instanceof AVLTreeCounterNode;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The function overrides the add method of a TypeScript class to add a new node to a data structure\n * and update the count.\n * @param {K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The\n * `keyNodeOrEntry` parameter can accept a value of type `R`, which can be any type. It\n * can also accept a value of type `K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`, which represents a key, node,\n * entry, or raw element\n * @param {V} [value] - The `value` parameter represents the value associated with the key in the\n * data structure. It is an optional parameter, so it can be omitted if not needed.\n * @param [count=1] - The `count` parameter represents the number of times the key-value pair should\n * be added to the data structure. By default, it is set to 1, meaning that the key-value pair will\n * be added once. However, you can specify a different value for `count` if you want to add\n * @returns a boolean value.\n */\n override add(\n keyNodeOrEntry: K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V,\n count = 1\n ): boolean {\n const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value, count);\n if (newNode === undefined) return false;\n\n const orgNodeCount = newNode?.count || 0;\n const inserted = super.add(newNode, newValue);\n if (inserted) {\n this._count += orgNodeCount;\n }\n return true;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The function overrides the delete method in a binary tree data structure, handling deletion of\n * nodes and maintaining balance in the tree.\n * @param {K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The `predicate`\n * parameter in the `delete` method is used to specify the condition for deleting a node from the\n * binary tree. It can be a key, node, or entry that determines which\n * node(s) should be deleted.\n * @param [ignoreCount=false] - The `ignoreCount` parameter in the `override delete` method is a\n * boolean flag that determines whether to ignore the count of the node being deleted. If\n * `ignoreCount` is set to `true`, the method will delete the node regardless of its count. If\n * `ignoreCount` is set to\n * @returns The `delete` method overrides the default delete behavior in a binary tree data\n * structure. It takes a predicate or node to be deleted and an optional flag to ignore count. The\n * method returns an array of `BinaryTreeDeleteResult` objects, each containing information about the\n * deleted node and whether balancing is needed in the tree.\n */\n override delete(\n keyNodeOrEntry: K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n ignoreCount = false\n ): BinaryTreeDeleteResult<AVLTreeCounterNode<K, V>>[] {\n const deletedResult: BinaryTreeDeleteResult<AVLTreeCounterNode<K, V>>[] = [];\n if (!this.root) return deletedResult;\n\n const curr: AVLTreeCounterNode<K, V> | undefined = this.getNode(keyNodeOrEntry) ?? undefined;\n if (!curr) return deletedResult;\n\n const parent: AVLTreeCounterNode<K, V> | undefined = curr?.parent ? curr.parent : undefined;\n let needBalanced: AVLTreeCounterNode<K, V> | undefined = undefined,\n orgCurrent: AVLTreeCounterNode<K, V> | undefined = curr;\n\n if (curr.count > 1 && !ignoreCount) {\n curr.count--;\n this._count--;\n } else {\n if (!curr.left) {\n if (!parent) {\n if (curr.right !== undefined && curr.right !== null) this._setRoot(curr.right);\n } else {\n const { familyPosition: fp } = curr;\n if (fp === 'LEFT' || fp === 'ROOT_LEFT') {\n parent.left = curr.right;\n } else if (fp === 'RIGHT' || fp === 'ROOT_RIGHT') {\n parent.right = curr.right;\n }\n needBalanced = parent;\n }\n } else {\n const leftSubTreeRightMost = curr.left ? this.getRightMost(node => node, curr.left) : undefined;\n if (leftSubTreeRightMost) {\n const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;\n orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);\n if (parentOfLeftSubTreeMax) {\n if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost) {\n parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;\n } else {\n parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;\n }\n needBalanced = parentOfLeftSubTreeMax;\n }\n }\n }\n this._size = this._size - 1;\n // TODO How to handle when the count of target node is lesser than current node's count\n if (orgCurrent) this._count -= orgCurrent.count;\n }\n\n deletedResult.push({ deleted: orgCurrent, needBalanced });\n\n if (needBalanced) {\n this._balancePath(needBalanced);\n }\n\n return deletedResult;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The \"clear\" function overrides the parent class's \"clear\" function and also resets the count to\n * zero.\n */\n override clear() {\n super.clear();\n this._count = 0;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(log n)\n *\n * The `perfectlyBalance` function takes a sorted array of nodes and builds a balanced binary search\n * tree using either a recursive or iterative approach.\n * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that\n * specifies the type of iteration to use when building the balanced binary search tree. It has a\n * default value of `this.iterationType`, which means it will use the iteration type currently set in\n * the object.\n * @returns The function `perfectlyBalance` returns a boolean value. It returns `true` if the\n * balancing operation is successful, and `false` if there are no nodes to balance.\n */\n override perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {\n const sorted = this.dfs(node => node, 'IN'),\n n = sorted.length;\n if (sorted.length < 1) return false;\n\n this.clear();\n\n if (iterationType === 'RECURSIVE') {\n const buildBalanceBST = (l: number, r: number) => {\n if (l > r) return;\n const m = l + Math.floor((r - l) / 2);\n const midNode = sorted[m];\n if (this._isMapMode) this.add(midNode.key, undefined, midNode.count);\n else this.add(midNode.key, midNode.value, midNode.count);\n buildBalanceBST(l, m - 1);\n buildBalanceBST(m + 1, r);\n };\n\n buildBalanceBST(0, n - 1);\n return true;\n } else {\n const stack: [[number, number]] = [[0, n - 1]];\n while (stack.length > 0) {\n const popped = stack.pop();\n if (popped) {\n const [l, r] = popped;\n if (l <= r) {\n const m = l + Math.floor((r - l) / 2);\n const midNode = sorted[m];\n if (this._isMapMode) this.add(midNode.key, undefined, midNode.count);\n else this.add(midNode.key, midNode.value, midNode.count);\n stack.push([m + 1, r]);\n stack.push([l, m - 1]);\n }\n }\n }\n return true;\n }\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The function overrides the clone method to create a deep copy of a tree object.\n * @returns The `clone()` method is returning a cloned instance of the `TREE` object.\n */\n override clone() {\n const cloned = this.createTree();\n if (this._isMapMode) this.bfs(node => cloned.add(node.key, undefined, node.count));\n else this.bfs(node => cloned.add(node.key, node.value, node.count));\n if (this._isMapMode) cloned._store = this._store;\n return cloned;\n }\n\n /**\n * The `map` function in TypeScript overrides the default behavior to create a new AVLTreeCounter\n * with modified entries based on a provided callback.\n * @param callback - The `callback` parameter is a function that will be called for each entry in the\n * AVLTreeCounter. It takes four arguments:\n * @param [options] - The `options` parameter in the `override map` function is of type\n * `AVLTreeCounterOptions<MK, MV, MR>`. This parameter allows you to provide additional\n * configuration options when creating a new `AVLTreeCounter` instance within the `map` function.\n * These options\n * @param {any} [thisArg] - The `thisArg` parameter in the `override map` function is used to specify\n * the value of `this` when executing the `callback` function. It allows you to set the context\n * (value of `this`) for the callback function. This can be useful when you want to access properties\n * or\n * @returns The `map` method is returning a new `AVLTreeCounter` instance with the entries\n * transformed by the provided `callback` function. Each entry in the original tree is passed to the\n * `callback` function along with the index and the original tree itself. The transformed entries are\n * then added to the new `AVLTreeCounter` instance, which is returned at the end.\n */\n override map<MK, MV, MR>(\n callback: EntryCallback<K, V | undefined, [MK, MV]>,\n options?: AVLTreeCounterOptions<MK, MV, MR>,\n thisArg?: any\n ): AVLTreeCounter<MK, MV, MR> {\n const newTree = new AVLTreeCounter<MK, MV, MR>([], options);\n let index = 0;\n for (const [key, value] of this) {\n newTree.add(callback.call(thisArg, key, value, index++, this));\n }\n return newTree;\n }\n\n /**\n * The function `keyValueNodeEntryRawToNodeAndValue` converts a key, value, entry, or raw element into\n * a node object.\n * @param {K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The\n * `keyNodeOrEntry` parameter can be of type `R` or `K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`.\n * @param {V} [value] - The `value` parameter is an optional value that can be passed to the\n * `override` function. It represents the value associated with the key in the data structure. If no\n * value is provided, it will default to `undefined`.\n * @param [count=1] - The `count` parameter is an optional parameter that specifies the number of\n * times the key-value pair should be added to the data structure. If not provided, it defaults to 1.\n * @returns either a AVLTreeCounterNode<K, V> object or undefined.\n */\n protected override _keyValueNodeOrEntryToNodeAndValue(\n keyNodeOrEntry: K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V,\n count = 1\n ): [AVLTreeCounterNode<K, V> | undefined, V | undefined] {\n if (keyNodeOrEntry === undefined || keyNodeOrEntry === null) return [undefined, undefined];\n if (this.isNode(keyNodeOrEntry)) return [keyNodeOrEntry, value];\n\n if (this.isEntry(keyNodeOrEntry)) {\n const [key, entryValue] = keyNodeOrEntry;\n if (key === undefined || key === null) return [undefined, undefined];\n const finalValue = value ?? entryValue;\n return [this.createNode(key, finalValue, count), finalValue];\n }\n\n return [this.createNode(keyNodeOrEntry, value, count), value];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_swapProperties` function swaps the properties (key, value, count, height) between two nodes\n * in a binary search tree.\n * @param {BSTNOptKeyOrNode<K, AVLTreeCounterNode<K, V>>} srcNode - The `srcNode` parameter represents the source node\n * that will be swapped with the `destNode`.\n * @param {BSTNOptKeyOrNode<K, AVLTreeCounterNode<K, V>>} destNode - The `destNode` parameter represents the destination\n * node where the properties will be swapped with the source node.\n * @returns The method is returning the `destNode` after swapping its properties with the `srcNode`.\n * If either `srcNode` or `destNode` is undefined, it returns `undefined`.\n */\n protected override _swapProperties(\n srcNode: BSTNOptKeyOrNode<K, AVLTreeCounterNode<K, V>>,\n destNode: BSTNOptKeyOrNode<K, AVLTreeCounterNode<K, V>>\n ): AVLTreeCounterNode<K, V> | undefined {\n srcNode = this.ensureNode(srcNode);\n destNode = this.ensureNode(destNode);\n if (srcNode && destNode) {\n const { key, value, count, height } = destNode;\n const tempNode = this.createNode(key, value, count);\n if (tempNode) {\n tempNode.height = height;\n\n destNode.key = srcNode.key;\n if (!this._isMapMode) destNode.value = srcNode.value;\n destNode.count = srcNode.count;\n destNode.height = srcNode.height;\n\n srcNode.key = tempNode.key;\n if (!this._isMapMode) srcNode.value = tempNode.value;\n srcNode.count = tempNode.count;\n srcNode.height = tempNode.height;\n }\n\n return destNode;\n }\n return undefined;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function replaces an old node with a new node and updates the count property of the new node.\n * @param {AVLTreeCounterNode<K, V>} oldNode - The oldNode parameter represents the node that needs to be replaced in the\n * data structure. It is of type AVLTreeCounterNode<K, V>.\n * @param {AVLTreeCounterNode<K, V>} newNode - The `newNode` parameter is an instance of the `AVLTreeCounterNode<K, V>` class.\n * @returns The method is returning the result of calling the `_replaceNode` method from the\n * superclass, which is of type `AVLTreeCounterNode<K, V>`.\n */\n protected override _replaceNode(\n oldNode: AVLTreeCounterNode<K, V>,\n newNode: AVLTreeCounterNode<K, V>\n ): AVLTreeCounterNode<K, V> {\n newNode.count = oldNode.count + newNode.count;\n return super._replaceNode(oldNode, newNode);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Kirk Qi\n * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>\n * @license MIT License\n */\nimport type { Comparator, ElementCallback, PriorityQueueOptions } from '../../types';\nimport { Heap } from '../heap';\n\n/**\n * 1. Element Priority: In a PriorityQueue, elements are sorted according to their priority. Each dequeue (element removal) operation removes the element with the highest priority. The priority can be determined based on the natural ordering of the elements or through a provided comparator (Comparator).\n * 2. Heap-Based Implementation: PriorityQueue is typically implemented using a binary heap, allowing both insertion and removal operations to be completed in O(log n) time, where n is the number of elements in the queue.\n * 3. Task Scheduling: In systems where tasks need to be processed based on the urgency of tasks rather than the order of arrival.\n * 4. Dijkstra's Algorithm: In shortest path algorithms for graphs, used to select the next shortest edge to visit.\n * 5. Huffman Coding: Used to select the smallest node combination when constructing a Huffman tree.\n * 6. Kth Largest Element in a Data Stream: Used to maintain a min-heap of size K for quickly finding the Kth largest element in stream data\n */\nexport class PriorityQueue<E = any, R = any> extends Heap<E, R> {\n /**\n * The constructor initializes a priority queue with optional elements and options.\n * @param elements - The `elements` parameter is an iterable object that contains the initial\n * elements to be added to the priority queue. It is an optional parameter, and if not provided, the\n * priority queue will be initialized as empty.\n * @param [options] - The `options` parameter is an optional object that can be used to customize the\n * behavior of the priority queue. It can contain the following properties:\n */\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: PriorityQueueOptions<E, R>) {\n super(elements, options);\n }\n\n /**\n * The `clone` function returns a new instance of the `PriorityQueue` class with the same comparator\n * and toElementFn as the original instance.\n * @returns The method is returning a new instance of the `PriorityQueue` class with the same\n * elements and properties as the current instance.\n */\n override clone(): PriorityQueue<E, R> {\n return new PriorityQueue<E, R>(this, { comparator: this.comparator, toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new PriorityQueue object containing elements that pass a given callback\n * function.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: the current element, the index of the current element, and the\n * heap itself. The callback function should return a boolean value indicating whether the current\n * element should be included in the filtered list\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `PriorityQueue` object that contains the elements that pass\n * the filter condition specified by the `callback` function.\n */\n override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): PriorityQueue<E, R> {\n const filteredPriorityQueue = new PriorityQueue<E, R>([], {\n toElementFn: this.toElementFn,\n comparator: this.comparator\n });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredPriorityQueue.add(current);\n }\n index++;\n }\n return filteredPriorityQueue;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * The `map` function creates a new heap by applying a callback function to each element of the\n * original heap.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: `el` (the current element), `index` (the index of the current\n * element), and `this` (the heap itself). The callback function should return a value of\n * @param comparator - The `comparator` parameter is a function that defines the order of the\n * elements in the heap. It takes two elements `a` and `b` as arguments and returns a negative number\n * if `a` should be placed before `b`, a positive number if `a` should be placed after\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that converts the raw\n * element `RR` to the desired type `T`. It takes a single argument `rawElement` of type `RR` and\n * returns a value of type `T`. This function is used to transform the elements of the original\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `PriorityQueue` class with the mapped elements.\n */\n override map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n comparator: Comparator<EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): PriorityQueue<EM, RM> {\n const mappedPriorityQueue: PriorityQueue<EM, RM> = new PriorityQueue<EM, RM>([], { comparator, toElementFn });\n let index = 0;\n for (const el of this) {\n mappedPriorityQueue.add(callback.call(thisArg, el, index, this));\n index++;\n }\n return mappedPriorityQueue;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Kirk Qi\n * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>\n * @license MIT License\n */\nimport type { Comparator, ElementCallback, PriorityQueueOptions } from '../../types';\nimport { PriorityQueue } from './priority-queue';\n\n/**\n *\n */\nexport class MinPriorityQueue<E = any, R = any> extends PriorityQueue<E, R> {\n /**\n * The constructor initializes a PriorityQueue with optional elements and options, including a\n * comparator function.\n * @param elements - The `elements` parameter is an iterable object that contains the initial\n * elements to be added to the priority queue. It is optional and defaults to an empty array if not\n * provided.\n * @param options - The `options` parameter is an object that contains additional configuration\n * options for the priority queue. In this case, it has a property called `comparator,` which is a\n * function used to compare elements in the priority queue. The `comparator` function takes two\n * parameters `a` and `b`\n */\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: PriorityQueueOptions<E, R>) {\n super(elements, options);\n }\n\n /**\n * The `clone` function returns a new instance of the `MinPriorityQueue` class with the same\n * comparator and toElementFn as the original instance.\n * @returns The method is returning a new instance of the `MinPriorityQueue` class with the same\n * properties as the current instance.\n */\n override clone(): MinPriorityQueue<E, R> {\n return new MinPriorityQueue<E, R>(this, { comparator: this.comparator, toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new MinPriorityQueue object containing elements that pass a given callback\n * function.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: the current element, the index of the current element, and the\n * heap itself. The callback function should return a boolean value indicating whether the current\n * element should be included in the filtered list\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `MinPriorityQueue` object that contains the elements that pass\n * the filter condition specified by the `callback` function.\n */\n override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): MinPriorityQueue<E, R> {\n const filteredPriorityQueue = new MinPriorityQueue<E, R>([], {\n toElementFn: this.toElementFn,\n comparator: this.comparator\n });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredPriorityQueue.add(current);\n }\n index++;\n }\n return filteredPriorityQueue;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * The `map` function creates a new heap by applying a callback function to each element of the\n * original heap.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: `el` (the current element), `index` (the index of the current\n * element), and `this` (the heap itself). The callback function should return a value of\n * @param comparator - The `comparator` parameter is a function that defines the order of the\n * elements in the heap. It takes two elements `a` and `b` as arguments and returns a negative number\n * if `a` should be placed before `b`, a positive number if `a` should be placed after\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that converts the raw\n * element `RR` to the desired type `T`. It takes a single argument `rawElement` of type `RR` and\n * returns a value of type `T`. This function is used to transform the elements of the original\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `MinPriorityQueue` class with the mapped elements.\n */\n override map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n comparator: Comparator<EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): MinPriorityQueue<EM, RM> {\n const mappedPriorityQueue: MinPriorityQueue<EM, RM> = new MinPriorityQueue<EM, RM>([], { comparator, toElementFn });\n let index = 0;\n for (const el of this) {\n mappedPriorityQueue.add(callback.call(thisArg, el, index, this));\n index++;\n }\n return mappedPriorityQueue;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Kirk Qi\n * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>\n * @license MIT License\n */\nimport type { Comparator, ElementCallback, PriorityQueueOptions } from '../../types';\nimport { PriorityQueue } from './priority-queue';\n\n/**\n *\n */\nexport class MaxPriorityQueue<E = any, R = any> extends PriorityQueue<E, R> {\n /**\n * The constructor initializes a PriorityQueue with optional elements and options, including a\n * comparator function.\n * @param elements - The `elements` parameter is an iterable object that contains the initial\n * elements to be added to the priority queue. It is optional and defaults to an empty array if not\n * provided.\n * @param options - The `options` parameter is an object that contains additional configuration\n * options for the priority queue. In this case, it has a property called `comparator,` which is a\n * function used to compare elements in the priority queue.\n */\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: PriorityQueueOptions<E, R>) {\n super(elements, {\n comparator: (a: E, b: E): number => {\n if (typeof a === 'object' || typeof b === 'object') {\n throw TypeError(\n `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`\n );\n }\n if (a < b) return 1;\n if (a > b) return -1;\n return 0;\n },\n ...options\n });\n }\n\n /**\n * The `clone` function returns a new instance of the `MaxPriorityQueue` class with the same\n * comparator and toElementFn as the current instance.\n * @returns The method is returning a new instance of the MaxPriorityQueue class with the same\n * comparator and toElementFn as the current instance.\n */\n override clone(): MaxPriorityQueue<E, R> {\n return new MaxPriorityQueue<E, R>(this, { comparator: this.comparator, toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new MaxPriorityQueue object containing elements that pass a given callback\n * function.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: the current element, the index of the current element, and the\n * heap itself. The callback function should return a boolean value indicating whether the current\n * element should be included in the filtered list\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `MaxPriorityQueue` object that contains the elements that pass\n * the filter condition specified by the `callback` function.\n */\n override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): MaxPriorityQueue<E, R> {\n const filteredPriorityQueue = new MaxPriorityQueue<E, R>([], {\n toElementFn: this.toElementFn,\n comparator: this.comparator\n });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredPriorityQueue.add(current);\n }\n index++;\n }\n return filteredPriorityQueue;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * The `map` function creates a new heap by applying a callback function to each element of the\n * original heap.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: `el` (the current element), `index` (the index of the current\n * element), and `this` (the heap itself). The callback function should return a value of\n * @param comparator - The `comparator` parameter is a function that defines the order of the\n * elements in the heap. It takes two elements `a` and `b` as arguments and returns a negative number\n * if `a` should be placed before `b`, a positive number if `a` should be placed after\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that converts the raw\n * element `RR` to the desired type `T`. It takes a single argument `rawElement` of type `RR` and\n * returns a value of type `T`. This function is used to transform the elements of the original\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `MaxPriorityQueue` class with the mapped elements.\n */\n override map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n comparator: Comparator<EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): MaxPriorityQueue<EM, RM> {\n const mappedPriorityQueue = new MaxPriorityQueue<EM, RM>([], { comparator, toElementFn });\n let index = 0;\n for (const el of this) {\n mappedPriorityQueue.add(callback.call(thisArg, el, index, this));\n index++;\n }\n return mappedPriorityQueue;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { MatrixOptions } from '../../types';\n\n/**\n *\n */\nexport class Matrix {\n /**\n * The constructor function initializes a matrix object with the provided data and options, or with\n * default values if no options are provided.\n * @param {number[][]} data - A 2D array of numbers representing the data for the matrix.\n * @param [options] - The `options` parameter is an optional object that can contain the following\n * properties:\n */\n constructor(data: number[][], options?: MatrixOptions) {\n if (options) {\n const { rows, cols, addFn, subtractFn, multiplyFn } = options;\n if (typeof rows === 'number' && rows > 0) this._rows = rows;\n else this._rows = data.length;\n if (typeof cols === 'number' && cols > 0) this._cols = cols;\n else this._cols = data[0]?.length || 0;\n if (addFn) this._addFn = addFn;\n if (subtractFn) this._subtractFn = subtractFn;\n if (multiplyFn) this._multiplyFn = multiplyFn;\n } else {\n this._rows = data.length;\n this._cols = data[0]?.length ?? 0;\n }\n\n if (data.length > 0) {\n this._data = data;\n } else {\n this._data = [];\n for (let i = 0; i < this.rows; i++) {\n this._data[i] = new Array(this.cols).fill(0);\n }\n }\n }\n\n protected _rows: number = 0;\n\n /**\n * The function returns the number of rows.\n * @returns The number of rows.\n */\n get rows(): number {\n return this._rows;\n }\n\n protected _cols: number = 0;\n\n /**\n * The function returns the value of the protected variable _cols.\n * @returns The number of columns.\n */\n get cols(): number {\n return this._cols;\n }\n\n protected _data: number[][];\n\n /**\n * The function returns a two-dimensional array of numbers.\n * @returns The data property, which is a two-dimensional array of numbers.\n */\n get data(): number[][] {\n return this._data;\n }\n\n /**\n * The above function returns the value of the _addFn property.\n * @returns The value of the property `_addFn` is being returned.\n */\n get addFn() {\n return this._addFn;\n }\n\n /**\n * The function returns the value of the _subtractFn property.\n * @returns The `_subtractFn` property is being returned.\n */\n get subtractFn() {\n return this._subtractFn;\n }\n\n /**\n * The function returns the value of the _multiplyFn property.\n * @returns The `_multiplyFn` property is being returned.\n */\n get multiplyFn() {\n return this._multiplyFn;\n }\n\n /**\n * The `get` function returns the value at the specified row and column index if it is a valid index.\n * @param {number} row - The `row` parameter represents the row index of the element you want to\n * retrieve from the data array.\n * @param {number} col - The parameter \"col\" represents the column number of the element you want to\n * retrieve from the data array.\n * @returns The `get` function returns a number if the provided row and column indices are valid.\n * Otherwise, it returns `undefined`.\n */\n get(row: number, col: number): number | undefined {\n if (this.isValidIndex(row, col)) {\n return this.data[row][col];\n }\n }\n\n /**\n * The set function updates the value at a specified row and column in a two-dimensional array.\n * @param {number} row - The \"row\" parameter represents the row index of the element in a\n * two-dimensional array or matrix. It specifies the row where the value will be set.\n * @param {number} col - The \"col\" parameter represents the column index of the element in a\n * two-dimensional array.\n * @param {number} value - The value parameter represents the number that you want to set at the\n * specified row and column in the data array.\n * @returns a boolean value. It returns true if the index (row, col) is valid and the value is\n * successfully set in the data array. It returns false if the index is invalid and the value is not\n * set.\n */\n set(row: number, col: number, value: number): boolean {\n if (this.isValidIndex(row, col)) {\n this.data[row][col] = value;\n return true;\n }\n return false;\n }\n\n /**\n * The function checks if the dimensions of the given matrix match the dimensions of the current\n * matrix.\n * @param {Matrix} matrix - The parameter `matrix` is of type `Matrix`.\n * @returns a boolean value.\n */\n isMatchForCalculate(matrix: Matrix): boolean {\n return this.rows === matrix.rows && this.cols === matrix.cols;\n }\n\n /**\n * The `add` function adds two matrices together, returning a new matrix with the result.\n * @param {Matrix} matrix - The `matrix` parameter is an instance of the `Matrix` class.\n * @returns The `add` method returns a new `Matrix` object that represents the result of adding the\n * current matrix with the provided `matrix` parameter.\n */\n add(matrix: Matrix): Matrix | undefined {\n if (!this.isMatchForCalculate(matrix)) {\n throw new Error('Matrix dimensions must match for addition.');\n }\n\n const resultData: number[][] = [];\n for (let i = 0; i < this.rows; i++) {\n resultData[i] = [];\n for (let j = 0; j < this.cols; j++) {\n const a = this.get(i, j),\n b = matrix.get(i, j);\n if (a !== undefined && b !== undefined) {\n const added = this._addFn(a, b);\n if (added) {\n resultData[i][j] = added;\n }\n }\n }\n }\n\n return new Matrix(resultData, {\n rows: this.rows,\n cols: this.cols,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n }\n\n /**\n * The `subtract` function performs element-wise subtraction between two matrices and returns a new\n * matrix with the result.\n * @param {Matrix} matrix - The `matrix` parameter is an instance of the `Matrix` class. It\n * represents the matrix that you want to subtract from the current matrix.\n * @returns a new Matrix object with the result of the subtraction operation.\n */\n subtract(matrix: Matrix): Matrix | undefined {\n if (!this.isMatchForCalculate(matrix)) {\n throw new Error('Matrix dimensions must match for subtraction.');\n }\n\n const resultData: number[][] = [];\n for (let i = 0; i < this.rows; i++) {\n resultData[i] = [];\n for (let j = 0; j < this.cols; j++) {\n const a = this.get(i, j),\n b = matrix.get(i, j);\n if (a !== undefined && b !== undefined) {\n const subtracted = this._subtractFn(a, b);\n if (subtracted) {\n resultData[i][j] = subtracted;\n }\n }\n }\n }\n\n return new Matrix(resultData, {\n rows: this.rows,\n cols: this.cols,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n }\n\n /**\n * The `multiply` function performs matrix multiplication between two matrices and returns the result\n * as a new matrix.\n * @param {Matrix} matrix - The `matrix` parameter is an instance of the `Matrix` class.\n * @returns a new Matrix object.\n */\n multiply(matrix: Matrix): Matrix | undefined {\n if (this.cols !== matrix.rows) {\n throw new Error('Matrix dimensions must be compatible for multiplication (A.cols = B.rows).');\n }\n\n const resultData: number[][] = [];\n for (let i = 0; i < this.rows; i++) {\n resultData[i] = [];\n for (let j = 0; j < matrix.cols; j++) {\n let sum: number | undefined;\n for (let k = 0; k < this.cols; k++) {\n const a = this.get(i, k),\n b = matrix.get(k, j);\n if (a !== undefined && b !== undefined) {\n const multiplied = this.multiplyFn(a, b);\n if (multiplied !== undefined) {\n sum = this.addFn(sum, multiplied);\n }\n }\n }\n if (sum !== undefined) resultData[i][j] = sum;\n }\n }\n\n return new Matrix(resultData, {\n rows: this.rows,\n cols: matrix.cols,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n }\n\n /**\n * The transpose function takes a matrix and returns a new matrix that is the transpose of the\n * original matrix.\n * @returns The transpose() function returns a new Matrix object with the transposed data.\n */\n transpose(): Matrix {\n if (this.data.some(row => row.length !== this.rows)) {\n throw new Error('Matrix must be rectangular for transposition.');\n }\n\n const resultData: number[][] = [];\n\n for (let j = 0; j < this.cols; j++) {\n resultData[j] = [];\n for (let i = 0; i < this.rows; i++) {\n const trans = this.get(i, j);\n if (trans !== undefined) resultData[j][i] = trans;\n }\n }\n\n return new Matrix(resultData, {\n rows: this.cols,\n cols: this.rows,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n }\n\n /**\n * The `inverse` function calculates the inverse of a square matrix using Gaussian elimination.\n * @returns a Matrix object, which represents the inverse of the original matrix.\n */\n inverse(): Matrix | undefined {\n // Check if the matrix is square\n if (this.rows !== this.cols) {\n throw new Error('Matrix must be square for inversion.');\n }\n\n // Create an augmented matrix [this | I]\n const augmentedMatrixData: number[][] = [];\n for (let i = 0; i < this.rows; i++) {\n augmentedMatrixData[i] = this.data[i].slice(); // Copy the original matrix\n for (let j = 0; j < this.cols; j++) {\n augmentedMatrixData[i][this.cols + j] = i === j ? 1 : 0; // Append the identity matrix\n }\n }\n\n const augmentedMatrix = new Matrix(augmentedMatrixData, {\n rows: this.rows,\n cols: this.cols * 2,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n\n // Apply Gaussian elimination to transform the left half into the identity matrix\n for (let i = 0; i < this.rows; i++) {\n // Find pivot\n let pivotRow = i;\n while (pivotRow < this.rows && augmentedMatrix.get(pivotRow, i) === 0) {\n pivotRow++;\n }\n\n if (pivotRow === this.rows) {\n // Matrix is singular, and its inverse does not exist\n throw new Error('Matrix is singular, and its inverse does not exist.');\n }\n\n // Swap rows to make the pivot the current row\n augmentedMatrix._swapRows(i, pivotRow);\n\n // Scale the pivot row to make the pivot element 1\n const pivotElement = augmentedMatrix.get(i, i) ?? 1;\n\n if (pivotElement === 0) {\n // Handle division by zero\n throw new Error('Matrix is singular, and its inverse does not exist (division by zero).');\n }\n\n augmentedMatrix._scaleRow(i, 1 / pivotElement);\n\n // Eliminate other rows to make elements in the current column zero\n for (let j = 0; j < this.rows; j++) {\n if (j !== i) {\n let factor = augmentedMatrix.get(j, i);\n if (factor === undefined) factor = 0;\n\n augmentedMatrix._addScaledRow(j, i, -factor);\n }\n }\n }\n\n // Extract the right half of the augmented matrix as the inverse\n const inverseData: number[][] = [];\n for (let i = 0; i < this.rows; i++) {\n inverseData[i] = augmentedMatrix.data[i].slice(this.cols);\n }\n\n return new Matrix(inverseData, {\n rows: this.rows,\n cols: this.cols,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n }\n\n /**\n * The dot function calculates the dot product of two matrices and returns a new matrix.\n * @param {Matrix} matrix - The `matrix` parameter is an instance of the `Matrix` class.\n * @returns a new Matrix object.\n */\n dot(matrix: Matrix): Matrix | undefined {\n if (this.cols !== matrix.rows) {\n throw new Error(\n 'Number of columns in the first matrix must be equal to the number of rows in the second matrix for dot product.'\n );\n }\n\n const resultData: number[][] = [];\n for (let i = 0; i < this.rows; i++) {\n resultData[i] = [];\n for (let j = 0; j < matrix.cols; j++) {\n let sum: number | undefined;\n for (let k = 0; k < this.cols; k++) {\n const a = this.get(i, k),\n b = matrix.get(k, j);\n if (a !== undefined && b !== undefined) {\n const multiplied = this.multiplyFn(a, b);\n if (multiplied !== undefined) {\n sum = this.addFn(sum, multiplied);\n }\n }\n }\n if (sum !== undefined) resultData[i][j] = sum;\n }\n }\n\n return new Matrix(resultData, {\n rows: this.rows,\n cols: matrix.cols,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n }\n\n /**\n * The function checks if a given row and column index is valid within a specified range.\n * @param {number} row - The `row` parameter represents the row index of a two-dimensional array or\n * matrix. It is a number that indicates the specific row in the matrix.\n * @param {number} col - The \"col\" parameter represents the column index in a two-dimensional array\n * or grid. It is used to check if the given column index is valid within the bounds of the grid.\n * @returns A boolean value is being returned.\n */\n isValidIndex(row: number, col: number): boolean {\n return row >= 0 && row < this.rows && col >= 0 && col < this.cols;\n }\n\n /**\n * The `clone` function returns a new instance of the Matrix class with the same data and properties\n * as the original instance.\n * @returns The `clone()` method is returning a new instance of the `Matrix` class with the same data\n * and properties as the current instance.\n */\n clone(): Matrix {\n return new Matrix(this.data, {\n rows: this.rows,\n cols: this.cols,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n }\n\n protected _addFn(a: number | undefined, b: number): number | undefined {\n if (a === undefined) return b;\n return a + b;\n }\n\n protected _subtractFn(a: number, b: number) {\n return a - b;\n }\n\n protected _multiplyFn(a: number, b: number) {\n return a * b;\n }\n\n /**\n * The function `_swapRows` swaps the positions of two rows in an array.\n * @param {number} row1 - The `row1` parameter is the index of the first row that you want to swap.\n * @param {number} row2 - The `row2` parameter is the index of the second row that you want to swap\n * with the first row.\n */\n protected _swapRows(row1: number, row2: number): void {\n const temp = this.data[row1];\n this.data[row1] = this.data[row2];\n this.data[row2] = temp;\n }\n\n /**\n * The function scales a specific row in a matrix by a given scalar value.\n * @param {number} row - The `row` parameter represents the index of the row in the matrix that you\n * want to scale. It is a number that indicates the position of the row within the matrix.\n * @param {number} scalar - The scalar parameter is a number that is used to multiply each element in\n * a specific row of a matrix.\n */\n protected _scaleRow(row: number, scalar: number): void {\n for (let j = 0; j < this.cols; j++) {\n let multiplied = this.multiplyFn(this.data[row][j], scalar);\n if (multiplied === undefined) multiplied = 0;\n this.data[row][j] = multiplied;\n }\n }\n\n /**\n * The function `_addScaledRow` multiplies a row in a matrix by a scalar value and adds it to another\n * row.\n * @param {number} targetRow - The targetRow parameter represents the index of the row in which the\n * scaled values will be added.\n * @param {number} sourceRow - The sourceRow parameter represents the index of the row from which the\n * values will be scaled and added to the targetRow.\n * @param {number} scalar - The scalar parameter is a number that is used to scale the values in the\n * source row before adding them to the target row.\n */\n protected _addScaledRow(targetRow: number, sourceRow: number, scalar: number): void {\n for (let j = 0; j < this.cols; j++) {\n let multiplied = this.multiplyFn(this.data[sourceRow][j], scalar);\n if (multiplied === undefined) multiplied = 0;\n const scaledValue = multiplied;\n let added = this.addFn(this.data[targetRow][j], scaledValue);\n if (added === undefined) added = 0;\n this.data[targetRow][j] = added;\n }\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { Direction, NavigatorParams, Turning } from '../../types';\n\nexport class Character {\n direction: Direction;\n turn: () => Character;\n\n /**\n * The constructor function takes in a direction and turning object and sets the direction and turn properties of the\n * Character class.\n * @param {Direction} direction - The direction parameter is used to specify the current direction of the character. It\n * can be any value that represents a direction, such as \"north\", \"south\", \"east\", or \"west\".\n * @param {Turning} turning - The `turning` parameter is an object that maps each direction to the corresponding\n * turning direction. It is used to determine the new direction when the character turns.\n */\n constructor(direction: Direction, turning: Turning) {\n this.direction = direction;\n this.turn = () => new Character(turning[direction], turning);\n }\n}\n\n/**\n *\n */\nexport class Navigator<T = number> {\n onMove: (cur: [number, number]) => void;\n protected readonly _matrix: T[][];\n protected readonly _cur: [number, number];\n protected _character: Character;\n protected readonly _VISITED: T;\n\n /**\n * The constructor initializes the Navigator object with the given parameters and sets the current position as visited\n * in the matrix.\n * @param - - `matrix`: a 2D array representing the grid or map\n */\n constructor({ matrix, turning, onMove, init: { cur, charDir, VISITED } }: NavigatorParams<T>) {\n this._matrix = matrix;\n this._cur = cur;\n this._character = new Character(charDir, turning);\n this.onMove = onMove;\n if (this.onMove) this.onMove(this._cur);\n this._VISITED = VISITED;\n this._matrix[this._cur[0]][this._cur[1]] = this._VISITED;\n }\n\n /**\n * The \"start\" function moves the character in its current direction until it encounters an obstacle, then it turns the\n * character and repeats the process.\n */\n start() {\n while (this.check(this._character.direction) || this.check(this._character.turn().direction)) {\n const { direction } = this._character;\n if (this.check(direction)) {\n this.move(direction);\n } else if (this.check(this._character.turn().direction)) {\n this._character = this._character.turn();\n }\n }\n }\n\n /**\n * The function checks if there is a valid move in the specified direction in a matrix.\n * @param {Direction} direction - The direction parameter is a string that represents the direction in which to check.\n * It can be one of the following values: 'up', 'right', 'down', or 'left'.\n * @returns a boolean value.\n */\n check(direction: Direction) {\n let forward: T | undefined, row: T[] | undefined;\n const matrix = this._matrix;\n const [i, j] = this._cur;\n switch (direction) {\n case 'up':\n row = matrix[i - 1];\n if (!row) return false;\n forward = row[j];\n break;\n case 'right':\n forward = matrix[i][j + 1];\n break;\n case 'down':\n row = matrix[i + 1];\n if (!row) return false;\n forward = row[j];\n break;\n case 'left':\n forward = matrix[i][j - 1];\n break;\n }\n return forward !== undefined && forward !== this._VISITED;\n }\n\n /**\n * The `move` function updates the current position based on the given direction and updates the matrix accordingly.\n * @param {Direction} direction - The `direction` parameter is a string that represents the direction in which to move.\n * It can have one of the following values: 'up', 'right', 'down', or 'left'.\n */\n move(direction: Direction) {\n switch (direction) {\n case 'up':\n this._cur[0]--;\n break;\n case 'right':\n this._cur[1]++;\n break;\n case 'down':\n this._cur[0]++;\n break;\n case 'left':\n this._cur[1]--;\n break;\n }\n\n const [i, j] = this._cur;\n this._matrix[i][j] = this._VISITED;\n if (this.onMove) this.onMove(this._cur);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { ElementCallback, TrieOptions } from '../../types';\nimport { IterableElementBase } from '../base';\n\nexport class TrieNode {\n constructor(key: string) {\n this._key = key;\n this._isEnd = false;\n this._children = new Map<string, TrieNode>();\n }\n\n protected _key: string;\n\n /**\n * The function returns the value of the protected variable _key.\n * @returns The value of the `_key` property, which is a string.\n */\n get key(): string {\n return this._key;\n }\n\n /**\n * The above function sets the value of a protected variable called \"key\".\n * @param {string} value - The value parameter is a string that represents the value to be assigned\n * to the key.\n */\n set key(value: string) {\n this._key = value;\n }\n\n protected _children: Map<string, TrieNode>;\n\n /**\n * The function returns the children of a TrieNode as a Map.\n * @returns The `children` property of the TrieNode object, which is a Map containing string keys and\n * TrieNode values.\n */\n get children(): Map<string, TrieNode> {\n return this._children;\n }\n\n /**\n * The function sets the value of the `_children` property of a TrieNode object.\n * @param value - The value parameter is a Map object that represents the children of a TrieNode. The\n * keys of the map are strings, which represent the characters that are associated with each child\n * TrieNode. The values of the map are TrieNode objects, which represent the child nodes of the\n * current TrieNode.\n */\n set children(value: Map<string, TrieNode>) {\n this._children = value;\n }\n\n protected _isEnd: boolean;\n\n /**\n * The function returns a boolean value indicating whether a certain condition is met.\n * @returns The method is returning a boolean value, specifically the value of the variable `_isEnd`.\n */\n get isEnd(): boolean {\n return this._isEnd;\n }\n\n /**\n * The function sets the value of the \"_isEnd\" property.\n * @param {boolean} value - The value parameter is a boolean value that indicates whether the current\n * state is the end state or not.\n */\n set isEnd(value: boolean) {\n this._isEnd = value;\n }\n}\n\n/**\n * 1. Node Structure: Each node in a Trie represents a string (or a part of a string). The root node typically represents an empty string.\n * 2. Child Node Relationship: Each node's children represent the strings that can be formed by adding one character to the string at the current node. For example, if a node represents the string 'ca', one of its children might represent 'cat'.\n * 3. Fast Retrieval: Trie allows retrieval in O(m) time complexity, where m is the length of the string to be searched.\n * 4. Space Efficiency: Trie can store a large number of strings very space-efficiently, especially when these strings share common prefixes.\n * 5. Autocomplete and Prediction: Trie can be used for implementing autocomplete and word prediction features, as it can quickly find all strings with a common prefix.\n * 6. Sorting: Trie can be used to sort a set of strings in alphabetical order.\n * 7. String Retrieval: For example, searching for a specific string in a large set of strings.\n * 8. Autocomplete: Providing recommended words or phrases as a user types.\n * 9. Spell Check: Checking the spelling of words.\n * 10. IP Routing: Used in certain types of IP routing algorithms.\n * 11. Text Word Frequency Count: Counting and storing the frequency of words in a large amount of text data.\n * @example\n * // Autocomplete: Prefix validation and checking\n * const autocomplete = new Trie<string>(['gmail.com', 'gmail.co.nz', 'gmail.co.jp', 'yahoo.com', 'outlook.com']);\n *\n * // Get all completions for a prefix\n * const gmailCompletions = autocomplete.getWords('gmail');\n * console.log(gmailCompletions); // ['gmail.com', 'gmail.co.nz', 'gmail.co.jp']\n * @example\n * // File System Path Operations\n * const fileSystem = new Trie<string>([\n * '/home/user/documents/file1.txt',\n * '/home/user/documents/file2.txt',\n * '/home/user/pictures/photo.jpg',\n * '/home/user/pictures/vacation/',\n * '/home/user/downloads'\n * ]);\n *\n * // Find common directory prefix\n * console.log(fileSystem.getLongestCommonPrefix()); // '/home/user/'\n *\n * // List all files in a directory\n * const documentsFiles = fileSystem.getWords('/home/user/documents/');\n * console.log(documentsFiles); // ['/home/user/documents/file1.txt', '/home/user/documents/file2.txt']\n * @example\n * // Autocomplete: Basic word suggestions\n * // Create a trie for autocomplete\n * const autocomplete = new Trie<string>([\n * 'function',\n * 'functional',\n * 'functions',\n * 'class',\n * 'classes',\n * 'classical',\n * 'closure',\n * 'const',\n * 'constructor'\n * ]);\n *\n * // Test autocomplete with different prefixes\n * console.log(autocomplete.getWords('fun')); // ['functional', 'functions', 'function']\n * console.log(autocomplete.getWords('cla')); // ['classes', 'classical', 'class']\n * console.log(autocomplete.getWords('con')); // ['constructor', 'const']\n *\n * // Test with non-matching prefix\n * console.log(autocomplete.getWords('xyz')); // []\n * @example\n * // Dictionary: Case-insensitive word lookup\n * // Create a case-insensitive dictionary\n * const dictionary = new Trie<string>([], { caseSensitive: false });\n *\n * // Add words with mixed casing\n * dictionary.add('Hello');\n * dictionary.add('WORLD');\n * dictionary.add('JavaScript');\n *\n * // Test lookups with different casings\n * console.log(dictionary.has('hello')); // true\n * console.log(dictionary.has('HELLO')); // true\n * console.log(dictionary.has('Hello')); // true\n * console.log(dictionary.has('javascript')); // true\n * console.log(dictionary.has('JAVASCRIPT')); // true\n * @example\n * // IP Address Routing Table\n * // Add IP address prefixes and their corresponding routes\n * const routes = {\n * '192.168.1': 'LAN_SUBNET_1',\n * '192.168.2': 'LAN_SUBNET_2',\n * '10.0.0': 'PRIVATE_NETWORK_1',\n * '10.0.1': 'PRIVATE_NETWORK_2'\n * };\n *\n * const ipRoutingTable = new Trie<string>(Object.keys(routes));\n *\n * // Check IP address prefix matching\n * console.log(ipRoutingTable.hasPrefix('192.168.1')); // true\n * console.log(ipRoutingTable.hasPrefix('192.168.2')); // true\n *\n * // Validate IP address belongs to subnet\n * const ip = '192.168.1.100';\n * const subnet = ip.split('.').slice(0, 3).join('.');\n * console.log(ipRoutingTable.hasPrefix(subnet)); // true\n */\nexport class Trie<R = any> extends IterableElementBase<string, R> {\n /**\n * The constructor initializes a Trie data structure with optional options and words provided as\n * input.\n * @param {Iterable<string> | Iterable<R>} words - The `words` parameter in the constructor is an\n * iterable containing either strings or elements of type `R`. It is used to initialize the Trie with\n * a list of words or elements. If no `words` are provided, an empty iterable is used as the default\n * value.\n * @param [options] - The `options` parameter in the constructor is an optional object that can\n * contain configuration options for the Trie data structure. One of the options it can have is\n * `caseSensitive`, which is a boolean value indicating whether the Trie should be case-sensitive or\n * not. If `caseSensitive` is set to `\n */\n constructor(words: Iterable<string> | Iterable<R> = [], options?: TrieOptions<R>) {\n super(options);\n if (options) {\n const { caseSensitive } = options;\n if (caseSensitive !== undefined) this._caseSensitive = caseSensitive;\n }\n if (words) {\n this.addMany(words);\n }\n }\n\n protected _size: number = 0;\n\n /**\n * The size function returns the size of the stack.\n * @return The number of elements in the list\n */\n get size(): number {\n return this._size;\n }\n\n protected _caseSensitive: boolean = true;\n\n /**\n * The caseSensitive function is a getter that returns the value of the protected _caseSensitive property.\n * @return The value of the _caseSensitive protected variable\n */\n get caseSensitive(): boolean {\n return this._caseSensitive;\n }\n\n protected _root: TrieNode = new TrieNode('');\n\n /**\n * The root function returns the root node of the tree.\n * @return The root node\n */\n get root() {\n return this._root;\n }\n\n /**\n * Time Complexity: O(l), where l is the length of the word being added.\n * Space Complexity: O(l) - Each character in the word adds a TrieNode.\n *\n * Add a word to the Trie structure.\n * @param {string} word - The word to add.\n * @returns {boolean} True if the word was successfully added.\n */\n add(word: string): boolean {\n word = this._caseProcess(word);\n let cur = this.root;\n let isNewWord = false;\n for (const c of word) {\n let nodeC = cur.children.get(c);\n if (!nodeC) {\n nodeC = new TrieNode(c);\n cur.children.set(c, nodeC);\n }\n cur = nodeC;\n }\n if (!cur.isEnd) {\n isNewWord = true;\n cur.isEnd = true;\n this._size++;\n }\n return isNewWord;\n }\n\n /**\n * Time Complexity: O(n * l)\n * Space Complexity: O(1)\n *\n * The `addMany` function in TypeScript takes an iterable of strings or elements of type R, converts\n * them using a provided function if available, and adds them to a data structure while returning an\n * array of boolean values indicating success.\n * @param {Iterable<string> | Iterable<R>} words - The `words` parameter in the `addMany` function is\n * an iterable that contains either strings or elements of type `R`.\n * @returns The `addMany` method returns an array of boolean values indicating whether each word in\n * the input iterable was successfully added to the data structure.\n */\n addMany(words: Iterable<string> | Iterable<R>): boolean[] {\n const ans: boolean[] = [];\n for (const word of words) {\n if (this.toElementFn) {\n ans.push(this.add(this.toElementFn(word as R)));\n } else {\n ans.push(this.add(word as string));\n }\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(l), where l is the length of the input word.\n * Space Complexity: O(1) - Constant space.\n *\n * Check if the Trie contains a given word.\n * @param {string} word - The word to check for.\n * @returns {boolean} True if the word is present in the Trie.\n */\n override has(word: string): boolean {\n word = this._caseProcess(word);\n let cur = this.root;\n for (const c of word) {\n const nodeC = cur.children.get(c);\n if (!nodeC) return false;\n cur = nodeC;\n }\n return cur.isEnd;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The isEmpty function checks if the size of the queue is 0.\n * @return True if the size of the queue is 0\n */\n isEmpty(): boolean {\n return this._size === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear function resets the size of the Trie to 0 and creates a new root TrieNode.\n */\n clear(): void {\n this._size = 0;\n this._root = new TrieNode('');\n }\n\n /**\n * Time Complexity: O(l), where l is the length of the word being deleted.\n * Space Complexity: O(n) - Due to the recursive DFS approach.\n *\n * Remove a word from the Trie structure.\n * @param{string} word - The word to delete.\n * @returns {boolean} True if the word was successfully removed.\n */\n delete(word: string): boolean {\n word = this._caseProcess(word);\n let isDeleted = false;\n const dfs = (cur: TrieNode, i: number): boolean => {\n const char = word[i];\n const child = cur.children.get(char);\n if (child) {\n if (i === word.length - 1) {\n if (child.isEnd) {\n if (child.children.size > 0) {\n child.isEnd = false;\n } else {\n cur.children.delete(char);\n }\n isDeleted = true;\n return true;\n }\n return false;\n }\n const res = dfs(child, i + 1);\n if (res && !cur.isEnd && child.children.size === 0) {\n cur.children.delete(char);\n return true;\n }\n return false;\n }\n return false;\n };\n\n dfs(this.root, 0);\n if (isDeleted) {\n this._size--;\n }\n return isDeleted;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `getHeight` calculates the height of a trie data structure starting from the root\n * node.\n * @returns The `getHeight` method returns the maximum depth or height of the trie tree starting from\n * the root node. It calculates the depth using a breadth-first search (BFS) traversal of the trie\n * tree and returns the maximum depth found.\n */\n getHeight(): number {\n const startNode = this.root;\n let maxDepth = 0;\n if (startNode) {\n const bfs = (node: TrieNode, level: number) => {\n if (level > maxDepth) {\n maxDepth = level;\n }\n const { children } = node;\n if (children) {\n for (const child of children.entries()) {\n bfs(child[1], level + 1);\n }\n }\n };\n bfs(startNode, 0);\n }\n return maxDepth;\n }\n\n /**\n * Time Complexity: O(l), where l is the length of the input prefix.\n * Space Complexity: O(1) - Constant space.\n *\n * Check if a given input string has an absolute prefix in the Trie, meaning it's not a complete word.\n * @param {string} input - The input string to check.\n * @returns {boolean} True if it's an absolute prefix in the Trie.\n */\n hasPurePrefix(input: string): boolean {\n input = this._caseProcess(input);\n let cur = this.root;\n for (const c of input) {\n const nodeC = cur.children.get(c);\n if (!nodeC) return false;\n cur = nodeC;\n }\n return !cur.isEnd;\n }\n\n /**\n * Time Complexity: O(l), where l is the length of the input prefix.\n * Space Complexity: O(1) - Constant space.\n *\n * Check if a given input string is a prefix of any existing word in the Trie, whether as an absolute prefix or a complete word.\n * @param {string} input - The input string representing the prefix to check.\n * @returns {boolean} True if it's a prefix in the Trie.\n */\n hasPrefix(input: string): boolean {\n input = this._caseProcess(input);\n let cur = this.root;\n for (const c of input) {\n const nodeC = cur.children.get(c);\n if (!nodeC) return false;\n cur = nodeC;\n }\n return true;\n }\n\n /**\n * Time Complexity: O(n), where n is the total number of nodes in the trie.\n * Space Complexity: O(l), where l is the length of the input prefix.\n *\n * Check if the input string is a common prefix in the Trie, meaning it's a prefix shared by all words in the Trie.\n * @param {string} input - The input string representing the common prefix to check for.\n * @returns {boolean} True if it's a common prefix in the Trie.\n */\n hasCommonPrefix(input: string): boolean {\n input = this._caseProcess(input);\n let commonPre = '';\n const dfs = (cur: TrieNode) => {\n commonPre += cur.key;\n if (commonPre === input) return;\n if (cur.isEnd) return;\n if (cur && cur.children && cur.children.size === 1) dfs(Array.from(cur.children.values())[0]);\n else return;\n };\n dfs(this.root);\n return commonPre === input;\n }\n\n /**\n * Time Complexity: O(n), where n is the total number of nodes in the trie.\n * Space Complexity: O(l), where l is the length of the longest common prefix.\n *\n * Get the longest common prefix among all the words stored in the Trie.\n * @returns {string} The longest common prefix found in the Trie.\n */\n getLongestCommonPrefix(): string {\n let commonPre = '';\n const dfs = (cur: TrieNode) => {\n commonPre += cur.key;\n if (cur.isEnd) return;\n if (cur && cur.children && cur.children.size === 1) dfs(Array.from(cur.children.values())[0]);\n else return;\n };\n dfs(this.root);\n return commonPre;\n }\n\n /**\n * Time Complexity: O(w * l), where w is the number of words retrieved, and l is the average length of the words.\n * Space Complexity: O(w * l) - The space required for the output array.\n *\n * The `getAll` function returns an array of all words in a Trie data structure that start with a given prefix.\n * @param {string} prefix - The `prefix` parameter is a string that represents the prefix that we want to search for in the\n * trie. It is an optional parameter, so if no prefix is provided, it will default to an empty string.\n * @param {number} max - The max count of words will be found\n * @param isAllWhenEmptyPrefix - If true, when the prefix provided as '', returns all the words in the trie.\n * @returns {string[]} an array of strings.\n */\n getWords(prefix = '', max = Number.MAX_SAFE_INTEGER, isAllWhenEmptyPrefix = false): string[] {\n prefix = this._caseProcess(prefix);\n const words: string[] = [];\n let found = 0;\n\n function dfs(node: TrieNode, word: string) {\n for (const char of node.children.keys()) {\n const charNode = node.children.get(char);\n if (charNode !== undefined) {\n dfs(charNode, word.concat(char));\n }\n }\n if (node.isEnd) {\n if (found > max - 1) return;\n words.push(word);\n found++;\n }\n }\n\n let startNode = this.root;\n\n if (prefix) {\n for (const c of prefix) {\n const nodeC = startNode.children.get(c);\n if (nodeC) {\n startNode = nodeC;\n } else {\n // Early return if the whole prefix is not found\n return [];\n }\n }\n }\n\n if (isAllWhenEmptyPrefix || startNode !== this.root) dfs(startNode, prefix);\n\n return words;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `clone` function returns a new instance of the Trie class with the same values and case\n * sensitivity as the original Trie.\n * @returns A new instance of the Trie class is being returned.\n */\n clone(): Trie<R> {\n return new Trie<R>(this, { caseSensitive: this.caseSensitive, toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function takes a predicate function and returns a new array containing all the\n * elements for which the predicate function returns true.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * `word`, `index`, and `this`. It should return a boolean value indicating whether the current\n * element should be included in the filtered results or not.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the `predicate` function. It is used when you want to bind a\n * specific object as the context for the `predicate` function. If `thisArg` is provided, it will be\n * @returns The `filter` method is returning an array of strings (`string[]`).\n */\n filter(predicate: ElementCallback<string, R, boolean>, thisArg?: any): Trie<R> {\n const results = new Trie<R>([], { toElementFn: this.toElementFn, caseSensitive: this.caseSensitive });\n let index = 0;\n for (const word of this) {\n if (predicate.call(thisArg, word, index, this)) {\n results.add(word);\n }\n index++;\n }\n return results;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function creates a new Trie by applying a callback function to each element in the\n * current Trie.\n * @param callback - The callback parameter is a function that will be called for each element in the\n * Trie. It takes four arguments:\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to\n * convert the raw element (`RM`) into a string representation. This can be useful if the raw element\n * is not already a string or if you want to customize how the element is converted into a string. If\n * this parameter is\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new Trie object.\n */\n map<RM>(\n callback: ElementCallback<string, R, string>,\n toElementFn?: (rawElement: RM) => string,\n thisArg?: any\n ): Trie<RM> {\n const newTrie = new Trie<RM>([], { toElementFn, caseSensitive: this.caseSensitive });\n let index = 0;\n for (const word of this) {\n newTrie.add(callback.call(thisArg, word, index, this));\n index++;\n }\n return newTrie;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `_getIterator` returns an iterable iterator that performs a depth-first search on a\n * trie data structure and yields all the paths to the end nodes.\n */\n protected *_getIterator(): IterableIterator<string> {\n function* _dfs(node: TrieNode, path: string): IterableIterator<string> {\n if (node.isEnd) {\n yield path;\n }\n for (const [char, childNode] of node.children) {\n yield* _dfs(childNode, path + char);\n }\n }\n\n yield* _dfs(this.root, '');\n }\n\n protected get _total() {\n return this._size;\n }\n\n /**\n * Time Complexity: O(l), where l is the length of the input string.\n * Space Complexity: O(1) - Constant space.\n *\n * @param str\n * @protected\n */\n protected _caseProcess(str: string) {\n if (!this._caseSensitive) {\n str = str.toLowerCase(); // Convert str to lowercase if case-insensitive\n }\n return str;\n }\n}\n","export class TreeNode<V = any> {\n /**\n * The constructor function initializes a TreeNode object with a key, optional value, and optional\n * children.\n * @param {string} key - A string representing the key of the tree node.\n * @param {V} [value] - The `value` parameter is an optional parameter of type `V`. It represents the\n * value associated with the node. If no value is provided, it defaults to `undefined`.\n * @param {TreeNode<V>[]} [children] - The `children` parameter is an optional array of `TreeNode<V>`\n * objects. It represents the child nodes of the current node. If no children are provided, the\n * default value is an empty array.\n */\n constructor(key: string, value?: V, children?: TreeNode<V>[]) {\n this._key = key;\n this._value = value || undefined;\n if (children) this._children = children;\n }\n\n protected _key: string;\n\n /**\n * The function returns the value of the protected variable _key.\n * @returns The value of the `_key` property, which is a string.\n */\n get key(): string {\n return this._key;\n }\n\n /**\n * The above function sets the value of a protected variable called \"key\".\n * @param {string} value - The value parameter is a string that represents the value to be assigned\n * to the key.\n */\n set key(value: string) {\n this._key = value;\n }\n\n protected _value?: V | undefined;\n\n /**\n * The function returns the value stored in a variable, or undefined if the variable is empty.\n * @returns The value of the variable `_value` is being returned.\n */\n get value(): V | undefined {\n return this._value;\n }\n\n /**\n * The function sets the value of a variable.\n * @param {V | undefined} value - The parameter \"value\" is of type \"V | undefined\", which means it\n * can accept a value of type \"V\" or it can be undefined.\n */\n set value(value: V | undefined) {\n this._value = value;\n }\n\n protected _children?: TreeNode<V>[] | undefined;\n\n /**\n * The function returns an array of TreeNode objects or undefined.\n * @returns The `children` property is being returned. It is of type `TreeNode<V>[] | undefined`,\n * which means it can either be an array of `TreeNode<V>` objects or `undefined`.\n */\n get children(): TreeNode<V>[] | undefined {\n return this._children;\n }\n\n /**\n * The function sets the value of the children property of a TreeNode object.\n * @param {TreeNode<V>[] | undefined} value - The value parameter is of type TreeNode<V>[] |\n * undefined. This means that it can accept an array of TreeNode objects or undefined.\n */\n set children(value: TreeNode<V>[] | undefined) {\n this._children = value;\n }\n\n /**\n * The function `addChildren` adds one or more child nodes to the current node.\n * @param {TreeNode<V> | TreeNode<V>[]} children - The `children` parameter can be either a single\n * `TreeNode<V>` object or an array of `TreeNode<V>` objects.\n */\n addChildren(children: TreeNode<V> | TreeNode<V>[]) {\n if (!this._children) {\n this._children = [];\n }\n if (children instanceof TreeNode) {\n this._children.push(children);\n } else {\n this._children = this._children.concat(children);\n }\n }\n\n /**\n * The function `getHeight()` calculates the maximum depth of a tree structure by performing a\n * breadth-first search.\n * @returns the maximum depth or height of the tree.\n */\n getHeight() {\n let maxDepth = 0;\n if (this) {\n const bfs = (node: TreeNode<V>, level: number) => {\n if (level > maxDepth) {\n maxDepth = level;\n }\n const { _children } = node;\n if (_children) {\n for (let i = 0, len = _children.length; i < len; i++) {\n bfs(_children[i], level + 1);\n }\n }\n };\n bfs(this, 0);\n }\n return maxDepth;\n }\n}\n"],"mappings":"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","names":["src_exports","__export","AVLTree","AVLTreeCounter","AVLTreeCounterNode","AVLTreeMultiMap","AVLTreeMultiMapNode","AVLTreeNode","AbstractEdge","AbstractGraph","AbstractVertex","BST","BSTNode","BinaryIndexedTree","BinaryTree","BinaryTreeNode","Character","DFSOperation","Deque","DirectedEdge","DirectedGraph","DirectedVertex","DoublyLinkedList","DoublyLinkedListNode","FibonacciHeap","FibonacciHeapNode","HashMap","Heap","IterableElementBase","IterableEntryBase","LinkedHashMap","LinkedListQueue","MapEdge","MapGraph","MapVertex","Matrix","MaxHeap","MaxPriorityQueue","MinHeap","MinPriorityQueue","Navigator","PriorityQueue","Queue","Range","RedBlackTree","RedBlackTreeNode","SegmentTree","SegmentTreeNode","SinglyLinkedList","SinglyLinkedListNode","SkipList","SkipListNode","Stack","THUNK_SYMBOL","TreeCounter","TreeCounterNode","TreeMultiMap","TreeMultiMapNode","TreeNode","Trie","TrieNode","UndirectedEdge","UndirectedGraph","UndirectedVertex","arrayRemove","calcMinUnitsRequired","getMSB","isComparable","isThunk","isWeakKey","rangeCheck","roundFixed","throwRangeError","toBinaryString","toThunk","trampoline","trampolineAsync","uuidV4","IterableEntryBase","args","__yieldStar","item","predicate","thisArg","index","callbackfn","key","value","itemKey","elementValue","initialValue","accumulator","IterableElementBase","options","__publicField","toElementFn","args","__yieldStar","item","predicate","thisArg","index","callbackfn","element","ele","initialValue","accumulator","uuidV4","c","arrayRemove","array","predicate","i","len","result","value","THUNK_SYMBOL","isThunk","fnOrValue","toThunk","fn","thunk","trampoline","args","trampolineAsync","__async","getMSB","rangeCheck","index","min","max","message","throwRangeError","isWeakKey","input","inputType","calcMinUnitsRequired","totalQuantity","unitSize","roundFixed","num","digit","multiplier","isPrimitiveComparable","valueType","tryObjectToPrimitive","obj","valueOfResult","stringResult","isComparable","isForceObjectComparable","comparableValue","toBinaryString","num","digit","binaryString","HashMap","_HashMap","IterableEntryBase","entryOrRawElements","options","__publicField","key","hashFn","toEntryFn","rawElement","value","strKey","results","rawEle","item","_a","callbackfn","thisArg","resultMap","index","predicate","filteredMap","node","keyType","LinkedHashMap","_LinkedHashMap","objHashFn","isNewKey","isWeakKey","hash","rangeCheck","cloned","entry","callback","mappedMap","newKey","newValue","prev","next","LinkedListNode","value","__publicField","LinearBase","_LinearBase","IterableElementBase","options","maxLen","searchElement","fromIndex","i","predicate","thisArg","item","items","newList","compareFn","arr","start","deleteCount","removedList","removed","separator","array","callbackfn","initialValue","accumulator","end","LinearLinkedBase","iterator","current","index","c","currentIndex","currentNode","previousNode","node","nextNode","SinglyLinkedListNode","LinkedListNode","value","__publicField","SinglyLinkedList","_SinglyLinkedList","LinearLinkedBase","elements","options","_a","data","singlyLinkedList","item","elementOrNode","newNode","current","removedNode","ans","el","elementNodeOrPredicate","predicate","index","i","deleted","targetNode","prevNode","node","newElementOrNode","prev","next","existingElementOrNode","existingNode","start","deleteCount","items","removedList","nextNode","lastInsertedNode","count","callback","thisArg","filteredList","toElementFn","mappedList","reversedArr","DoublyLinkedListNode","LinkedListNode","value","__publicField","DoublyLinkedList","_DoublyLinkedList","LinearLinkedBase","elements","options","maxLen","_a","data","elementNodeOrPredicate","elementOrNode","newNode","removedNode","ans","el","index","current","i","predicate","newElementOrNode","prevNode","nextNode","existingElementOrNode","existingNode","node","deleted","next","callback","thisArg","filteredList","toElementFn","mappedList","count","SkipListNode","key","value","level","__publicField","SkipList","elements","options","maxLevel","probability","firstNode","current","i","newNode","update","nextNode","lastLess","Stack","_Stack","IterableElementBase","elements","options","__publicField","element","ans","el","index","predicate","thisArg","newStack","callback","toElementFn","i","Queue","_Queue","LinearBase","elements","options","__publicField","autoCompactRatio","v","element","ans","el","first","index","deleted","newElement","start","deleteCount","items","removedQueue","globalStartIndex","removedElements","predicate","thisArg","newDeque","callback","toElementFn","item","i","cur","LinkedListQueue","_LinkedListQueue","SinglyLinkedList","Deque","_Deque","LinearBase","elements","options","__publicField","bucketSize","_size","calcMinUnitsRequired","i","needBucketNum","element","ans","el","pos","rangeCheck","bucketIndex","indexInBucket","num","length","arr","isCutSelf","newDeque","start","deleteCount","items","deletedElements","elementsAfter","item","deleted","targetBucket","targetPointer","curBucket","curPointer","nextBucket","nextPointer","size","index","oldElement","bucket","_bucketFirst","_bucketLast","_firstInBucket","_lastInBucket","prev","cur","newBuckets","predicate","thisArg","callback","toElementFn","addBucketNum","overallIndex","Heap","_Heap","IterableElementBase","elements","options","__publicField","a","b","comparator","_a","element","ans","el","value","last","index","order","result","_dfs","left","right","visitedNode","cloned","top","results","i","callback","thisArg","filteredList","current","toElementFn","mappedHeap","parent","parentItem","halfLength","minItem","FibonacciHeapNode","degree","FibonacciHeap","node","head","flag","z","heapToMerge","thisRoot","otherRoot","thisRootRight","otherRootLeft","y","x","A","d","t","MaxHeap","_MaxHeap","Heap","elements","options","__spreadValues","a","b","callback","thisArg","filteredList","index","current","comparator","toElementFn","mappedHeap","el","MinHeap","_MinHeap","Heap","elements","options","callback","thisArg","filteredList","index","current","comparator","toElementFn","mappedHeap","el","AbstractVertex","key","value","__publicField","AbstractEdge","weight","uuidV4","AbstractGraph","IterableEntryBase","v","vertexKey","vertexOrKey","keyOrVertex","newVertex","potentialKey","potentialKeyType","vertexMap","removed","v1","v2","srcOrEdge","dest","newEdge","srcOrKey","destOrKey","edge","limit","paths","vertex1","vertex2","stack","vertex","path","neighbors","neighbor","newPath","_a","sum","isWeight","allPaths","min","visited","queue","Queue","cost","i","cur","isDFS","_b","minIndex","index","pathSumWeight","minPath","dfs","visiting","src","getMinDist","genPaths","minDist","minDest","distMap","seen","preMap","srcVertex","destVertex","getMinOfNoSeen","minV","getPaths","parent","reversed","curFromMap","neighborFromMap","d","heap","Heap","a","b","curHeapNode","dist","distSrcToNeighbor","scanNegativeCycle","getMin","genPath","hasNegativeCycle","numOfVertices","edgeMap","numOfEdges","j","ends","s","sWeight","dWeight","idAndVertices","n","costs","predecessor","k","isInclude2Cycle","cycles","currentPath","uniqueCycles","cycle","sorted","cycleString","predicate","thisArg","filtered","callback","mapped","DirectedVertex","AbstractVertex","key","value","DirectedEdge","AbstractEdge","src","dest","weight","__publicField","DirectedGraph","_DirectedGraph","AbstractGraph","v","srcOrKey","destOrKey","edgeMap","srcOutEdges","edge","removed","arrayRemove","destInEdges","edgeOrSrcVertexKey","destVertexKey","vertexOrKey","vertexKey","vertex","neighbors","neighbor","v1","v2","v1ToV2","v2ToV1","target","destinations","outgoingEdges","outEdge","child","propertyName","statusMap","entry","sorted","hasCycle","dfs","cur","children","childStatus","outEdges","cloned","dfnMap","lowMap","SCCs","time","stack","inStack","SCC","poppedVertex","srcVertex","destVertex","UndirectedVertex","AbstractVertex","key","value","UndirectedEdge","AbstractEdge","v1","v2","weight","__publicField","UndirectedGraph","_UndirectedGraph","AbstractGraph","v","_a","edgeMap","vertex1","vertex2","e","v1Edges","removed","arrayRemove","v2Edges","edgeOrOneSideVertexKey","otherSideVertexKey","oneSide","otherSide","vertexOrKey","vertexKey","vertex","neighbors","neighbor","neighborEdges","restEdges","edge","edgeSet","cloned","dfnMap","lowMap","bridges","cutVertices","time","dfs","parent","childCount","end","endVertex","MapVertex","DirectedVertex","key","value","lat","long","__publicField","MapEdge","DirectedEdge","src","dest","weight","MapGraph","_MapGraph","DirectedGraph","originCoord","bottomRight","cloned","DFSOperation","Range","low","high","includeLow","includeHigh","isComparable","key","comparator","lowCheck","highCheck","BinaryTreeNode","key","value","__publicField","v","BinaryTree","_BinaryTree","IterableEntryBase","keysNodesEntriesOrRaws","options","node","iterationType","toEntryFn","isMapMode","isDuplicate","__spreadValues","keyNodeOrEntry","keyNodeEntryOrRaw","keyNodeEntryOrPredicate","Range","isComparable","newNode","newValue","queue","Queue","potentialParent","cur","values","inserted","valuesIterator","valueResult","anotherTree","deletedResult","curr","parent","needBalanced","orgCurrent","leftSubTreeRightMost","parentOfLeftSubTreeMax","fp","onlyOne","callback","startNode","predicate","ans","dfs","stack","_a","min","max","numKey","isStandardBST","isInverseBST","checkBST","checkMax","prev","dist","distEnsured","beginRootEnsured","depth","_getMaxHeight","leftHeight","rightHeight","maxHeight","_getMinHeight","leftMinHeight","rightMinHeight","last","depths","beginNode","isReverse","result","beginNodeEnsured","trampoline","predecessor","x","y","pattern","includeNull","level","current","levelSize","i","leaves","levelsNodes","_recursive","head","_reverseEdge","pre","next","_printEdge","tail","cloned","thisArg","newTree","index","opts","output","root","lines","paragraph","line","entryValue","finalValue","shouldVisitLeft","shouldVisitRight","shouldVisitRoot","shouldProcessRoot","visitLeft","visitRight","pushLeft","pushRight","pushRoot","__yieldStar","isShowNull","isShowUndefined","isShowRedBlackNIL","emptyDisplayLayout","width","_buildNodeDisplay","left","right","leftLines","leftWidth","leftMiddle","rightLines","rightWidth","rightMiddle","firstLine","secondLine","mergedLines","leftLine","rightLine","srcNode","destNode","tempNode","oldNode","p","BSTNode","BinaryTreeNode","key","value","__publicField","v","BST","_BST","BinaryTree","keysNodesEntriesOrRaws","options","a","b","isComparable","specifyComparable","isReverse","__spreadValues","keyNodeOrEntry","iterationType","_a","newNode","newValue","current","values","isBalanceAdd","inserted","valuesIterator","kve","realBTNExemplars","i","sorted","keyA","keyB","_dfs","arr","mid","orgIndex","entry","stack","popped","l","r","m","keyNodeEntryOrPredicate","onlyOne","callback","startNode","predicate","isRange","node","shouldVisitLeft","cur","range","leftS","leftI","benchmarkKey","shouldVisitRight","rightS","rightI","searchRange","Range","pattern","lesserOrGreater","targetNode","targetNodeEnsured","ans","targetKey","dfs","compared","queue","Queue","buildBalanceBST","midNode","balanced","_height","leftHeight","rightHeight","last","depths","left","right","thisArg","newTree","index","cloned","entryValue","BinaryIndexedTree","frequency","max","__publicField","getMSB","index","position","change","freqCur","freq","count","sum","x","y","i","delta","z","freqNew","before","left","right","sumT","middle","sumM","SegmentTreeNode","start","end","sum","value","__publicField","SegmentTree","values","mid","left","right","cur","index","root","dfs","indexA","indexB","i","j","leftSum","rightSum","AVLTreeNode","BSTNode","key","value","__publicField","v","AVLTree","_AVLTree","BST","keysNodesEntriesOrRaws","options","__spreadValues","keyNodeOrEntry","inserted","deletedResults","needBalanced","callback","thisArg","newTree","index","cloned","srcNode","destNode","srcNodeEnsured","destNodeEnsured","height","tempNode","node","rightHeight","A","parentOfA","B","C","path","i","oldNode","newNode","RedBlackTreeNode","BSTNode","key","value","color","__publicField","v","RedBlackTree","_RedBlackTree","BST","keysNodesEntriesOrRaws","options","__spreadValues","keyNodeOrEntry","newNode","newValue","insertStatus","results","nodeToDelete","originalColor","replacementNode","successor","node","callback","thisArg","newTree","index","cloned","oldNode","_a","_b","current","parent","compared","u","z","_c","_d","_e","y","sibling","x","AVLTreeMultiMapNode","AVLTreeNode","key","value","__publicField","v","AVLTreeMultiMap","_AVLTreeMultiMap","AVLTree","keysNodesEntriesOrRaws","options","__spreadProps","__spreadValues","keyNodeOrEntry","_commonAdd","values","_addToValues","existingValues","_addByNode","existingNode","index","cloned","TreeMultiMapNode","RedBlackTreeNode","key","value","__publicField","v","TreeMultiMap","_TreeMultiMap","RedBlackTree","keysNodesEntriesOrRaws","options","__spreadValues","keyNodeOrEntry","_commonAdd","values","_addToValues","existingValues","_addByNode","existingNode","index","cloned","TreeCounterNode","RedBlackTreeNode","key","value","count","color","__publicField","v","TreeCounter","_TreeCounter","RedBlackTree","keysNodesEntriesOrRaws","options","sum","node","__spreadValues","keyNodeOrEntry","newNode","newValue","orgCount","ignoreCount","results","nodeToDelete","originalColor","replacementNode","successor","iterationType","sorted","buildBalanceBST","l","r","m","midNode","stack","popped","cloned","callback","thisArg","newTree","index","entryValue","finalValue","srcNode","destNode","tempNode","oldNode","AVLTreeCounterNode","AVLTreeNode","key","value","count","__publicField","v","AVLTreeCounter","_AVLTreeCounter","AVLTree","keysNodesEntriesOrRaws","options","sum","node","__spreadValues","keyNodeOrEntry","newNode","newValue","orgNodeCount","ignoreCount","_a","deletedResult","curr","parent","needBalanced","orgCurrent","leftSubTreeRightMost","parentOfLeftSubTreeMax","fp","iterationType","sorted","buildBalanceBST","l","r","m","midNode","stack","popped","cloned","callback","thisArg","newTree","index","entryValue","finalValue","srcNode","destNode","height","tempNode","oldNode","PriorityQueue","_PriorityQueue","Heap","elements","options","callback","thisArg","filteredPriorityQueue","index","current","comparator","toElementFn","mappedPriorityQueue","el","MinPriorityQueue","_MinPriorityQueue","PriorityQueue","elements","options","callback","thisArg","filteredPriorityQueue","index","current","comparator","toElementFn","mappedPriorityQueue","el","MaxPriorityQueue","_MaxPriorityQueue","PriorityQueue","elements","options","__spreadValues","a","b","callback","thisArg","filteredPriorityQueue","index","current","comparator","toElementFn","mappedPriorityQueue","el","Matrix","_Matrix","data","options","__publicField","_a","_b","_c","rows","cols","addFn","subtractFn","multiplyFn","i","row","col","value","matrix","resultData","j","a","b","added","subtracted","sum","k","multiplied","trans","augmentedMatrixData","augmentedMatrix","pivotRow","pivotElement","factor","inverseData","row1","row2","temp","scalar","targetRow","sourceRow","scaledValue","Character","_Character","direction","turning","__publicField","Navigator","matrix","onMove","cur","charDir","VISITED","forward","row","j","i","TrieNode","key","__publicField","value","Trie","_Trie","IterableElementBase","words","options","caseSensitive","word","cur","isNewWord","c","nodeC","ans","isDeleted","dfs","i","char","child","startNode","maxDepth","bfs","node","level","children","input","commonPre","prefix","max","isAllWhenEmptyPrefix","found","charNode","predicate","thisArg","results","index","callback","toElementFn","newTrie","_dfs","path","childNode","__yieldStar","str","TreeNode","_TreeNode","key","value","children","__publicField","maxDepth","bfs","node","level","_children","i","len"]}
1
+ {"version":3,"sources":["../../src/index.ts","../../src/data-structures/base/iterable-entry-base.ts","../../src/data-structures/base/iterable-element-base.ts","../../src/utils/utils.ts","../../src/utils/number.ts","../../src/data-structures/hash/hash-map.ts","../../src/data-structures/base/linear-base.ts","../../src/data-structures/linked-list/singly-linked-list.ts","../../src/data-structures/linked-list/doubly-linked-list.ts","../../src/data-structures/linked-list/skip-linked-list.ts","../../src/data-structures/stack/stack.ts","../../src/data-structures/queue/queue.ts","../../src/data-structures/queue/deque.ts","../../src/data-structures/heap/heap.ts","../../src/data-structures/heap/max-heap.ts","../../src/data-structures/heap/min-heap.ts","../../src/data-structures/graph/abstract-graph.ts","../../src/data-structures/graph/directed-graph.ts","../../src/data-structures/graph/undirected-graph.ts","../../src/data-structures/graph/map-graph.ts","../../src/common/index.ts","../../src/data-structures/binary-tree/binary-tree.ts","../../src/data-structures/binary-tree/bst.ts","../../src/data-structures/binary-tree/binary-indexed-tree.ts","../../src/data-structures/binary-tree/segment-tree.ts","../../src/data-structures/binary-tree/avl-tree.ts","../../src/data-structures/binary-tree/red-black-tree.ts","../../src/data-structures/binary-tree/avl-tree-multi-map.ts","../../src/data-structures/binary-tree/tree-multi-map.ts","../../src/data-structures/binary-tree/tree-counter.ts","../../src/data-structures/binary-tree/avl-tree-counter.ts","../../src/data-structures/priority-queue/priority-queue.ts","../../src/data-structures/priority-queue/min-priority-queue.ts","../../src/data-structures/priority-queue/max-priority-queue.ts","../../src/data-structures/matrix/matrix.ts","../../src/data-structures/matrix/navigator.ts","../../src/data-structures/trie/trie.ts","../../src/data-structures/tree/tree.ts"],"sourcesContent":["export * from './data-structures';\nexport * from './utils';\nexport * from './interfaces';\nexport * from './types';\nexport * from './common';\n","import { EntryCallback, ReduceEntryCallback } from '../../types';\n\nexport abstract class IterableEntryBase<K = any, V = any> {\n abstract get size(): number;\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function is an implementation of the Symbol.iterator method that returns an iterable iterator.\n * @param {any[]} args - The `args` parameter in the code snippet represents a rest parameter. It\n * allows the function to accept any number of arguments as an array. In this case, the `args`\n * parameter is used to pass any additional arguments to the `_getIterator` method.\n */\n *[Symbol.iterator](...args: any[]): IterableIterator<[K, V]> {\n yield* this._getIterator(...args);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function returns an iterator that yields key-value pairs from the object, where the value can\n * be undefined.\n */\n *entries(): IterableIterator<[K, V | undefined]> {\n for (const item of this) {\n yield item;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function returns an iterator that yields the keys of a data structure.\n */\n *keys(): IterableIterator<K> {\n for (const item of this) {\n yield item[0];\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function returns an iterator that yields the values of a collection.\n */\n *values(): IterableIterator<V> {\n for (const item of this) {\n yield item[1];\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `every` function checks if every element in a collection satisfies a given condition.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * `value`, `key`, and `index`. It should return a boolean value indicating whether the condition is\n * met for the current element in the iteration.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be\n * passed as the first argument to the `predicate` function. If `thisArg` is not provided\n * @returns The `every` method is returning a boolean value. It returns `true` if every element in\n * the collection satisfies the provided predicate function, and `false` otherwise.\n */\n every(predicate: EntryCallback<K, V, boolean>, thisArg?: any): boolean {\n let index = 0;\n for (const item of this) {\n if (!predicate.call(thisArg, item[0], item[1], index++, this)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The \"some\" function iterates over a collection and returns true if at least one element satisfies\n * a given predicate.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * `value`, `key`, and `index`. It should return a boolean value indicating whether the condition is\n * met for the current element in the iteration.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as the `this` value when executing the `predicate` function. If `thisArg` is provided,\n * it will be passed as the first argument to the `predicate` function. If `thisArg` is\n * @returns a boolean value. It returns true if the predicate function returns true for any pair in\n * the collection, and false otherwise.\n */\n some(predicate: EntryCallback<K, V, boolean>, thisArg?: any): boolean {\n let index = 0;\n for (const item of this) {\n if (predicate.call(thisArg, item[0], item[1], index++, this)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `forEach` function iterates over each key-value pair in a collection and executes a callback\n * function for each pair.\n * @param callbackfn - The callback function that will be called for each element in the collection.\n * It takes four parameters: the value of the current element, the key of the current element, the\n * index of the current element, and the collection itself.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. If `thisArg` is provided, it will be\n * used as the `this` value when calling the callback function. If `thisArg` is not provided, `\n */\n forEach(callbackfn: EntryCallback<K, V, void>, thisArg?: any): void {\n let index = 0;\n for (const item of this) {\n const [key, value] = item;\n callbackfn.call(thisArg, key, value, index++, this);\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `find` function iterates over the entries of a collection and returns the first value for\n * which the callback function returns true.\n * @param callbackfn - The callback function that will be called for each entry in the collection. It\n * takes three arguments: the value of the entry, the key of the entry, and the index of the entry in\n * the collection. It should return a boolean value indicating whether the current entry matches the\n * desired condition.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will\n * be passed as the `this` value to the `callbackfn` function. If `thisArg\n * @returns The method `find` returns the value of the first element in the iterable that satisfies\n * the provided callback function. If no element satisfies the callback function, `undefined` is\n * returned.\n */\n find(callbackfn: EntryCallback<K, V, boolean>, thisArg?: any): [K, V] | undefined {\n let index = 0;\n for (const item of this) {\n const [key, value] = item;\n if (callbackfn.call(thisArg, key, value, index++, this)) return item;\n }\n return;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function checks if a given key exists in a collection.\n * @param {K} key - The parameter \"key\" is of type K, which means it can be any type. It represents\n * the key that we want to check for existence in the data structure.\n * @returns a boolean value. It returns true if the key is found in the collection, and false\n * otherwise.\n */\n has(key: K): boolean {\n for (const item of this) {\n const [itemKey] = item;\n if (itemKey === key) return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function checks if a given value exists in a collection.\n * @param {V} value - The parameter \"value\" is the value that we want to check if it exists in the\n * collection.\n * @returns a boolean value, either true or false.\n */\n hasValue(value: V): boolean {\n for (const [, elementValue] of this) {\n if (elementValue === value) return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `get` function retrieves the value associated with a given key from a collection.\n * @param {K} key - K (the type of the key) - This parameter represents the key that is being\n * searched for in the collection.\n * @returns The `get` method returns the value associated with the specified key if it exists in the\n * collection, otherwise it returns `undefined`.\n */\n get(key: K): V | undefined {\n for (const item of this) {\n const [itemKey, value] = item;\n if (itemKey === key) return value;\n }\n return;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `reduce` function iterates over key-value pairs and applies a callback function to each pair,\n * accumulating a single value.\n * @param callbackfn - The callback function that will be called for each element in the collection.\n * It takes four arguments: the current accumulator value, the current value of the element, the key\n * of the element, and the index of the element in the collection. It should return the updated\n * accumulator value.\n * @param {U} initialValue - The `initialValue` parameter is the initial value of the accumulator. It\n * is the value that will be used as the first argument to the `callbackfn` function when reducing\n * the elements of the collection.\n * @returns The `reduce` method is returning the final value of the accumulator after iterating over\n * all the elements in the collection.\n */\n reduce<U>(callbackfn: ReduceEntryCallback<K, V, U>, initialValue: U): U {\n let accumulator = initialValue;\n let index = 0;\n for (const item of this) {\n const [key, value] = item;\n accumulator = callbackfn(accumulator, value, key, index++, this);\n }\n return accumulator;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The print function logs the elements of an array to the console.\n */\n toVisual(): [K, V][] | string {\n return [...this];\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The print function logs the elements of an array to the console.\n */\n print(): void {\n console.log(this.toVisual());\n }\n\n abstract isEmpty(): boolean;\n\n abstract clear(): void;\n\n abstract clone(): any;\n\n abstract map(...args: any[]): any;\n\n abstract filter(...args: any[]): any;\n\n protected abstract _getIterator(...args: any[]): IterableIterator<[K, V]>;\n}\n","import { ElementCallback, IterableElementBaseOptions, ReduceElementCallback } from '../../types';\n\nexport abstract class IterableElementBase<E, R> {\n /**\n * The protected constructor initializes the options for the IterableElementBase class, including the\n * toElementFn function.\n * @param [options] - An optional object that contains the following properties:\n */\n protected constructor(options?: IterableElementBaseOptions<E, R>) {\n if (options) {\n const { toElementFn } = options;\n if (typeof toElementFn === 'function') this._toElementFn = toElementFn;\n else if (toElementFn) throw new TypeError('toElementFn must be a function type');\n }\n }\n\n protected _toElementFn?: (rawElement: R) => E;\n\n get toElementFn(): ((rawElement: R) => E) | undefined {\n return this._toElementFn;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function is an implementation of the Symbol.iterator method that returns an IterableIterator.\n * @param {any[]} args - The `args` parameter in the code snippet represents a rest parameter. It\n * allows the function to accept any number of arguments as an array. In this case, the `args`\n * parameter is used to pass any number of arguments to the `_getIterator` method.\n */\n *[Symbol.iterator](...args: any[]): IterableIterator<E> {\n yield* this._getIterator(...args);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function returns an iterator that yields all the values in the object.\n */\n *values(): IterableIterator<E> {\n for (const item of this) {\n yield item;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `every` function checks if every element in the array satisfies a given predicate.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * the current element being processed, its index, and the array it belongs to. It should return a\n * boolean value indicating whether the element satisfies a certain condition or not.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `predicate` function. If `thisArg` is\n * @returns The `every` method is returning a boolean value. It returns `true` if every element in\n * the array satisfies the provided predicate function, and `false` otherwise.\n */\n every(predicate: ElementCallback<E, R, boolean>, thisArg?: any): boolean {\n let index = 0;\n for (const item of this) {\n if (!predicate.call(thisArg, item, index++, this)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The \"some\" function checks if at least one element in a collection satisfies a given predicate.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * `value`, `index`, and `array`. It should return a boolean value indicating whether the current\n * element satisfies the condition.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as the `this` value when executing the `predicate` function. If `thisArg` is provided,\n * it will be passed as the `this` value to the `predicate` function. If `thisArg\n * @returns a boolean value. It returns true if the predicate function returns true for any element\n * in the collection, and false otherwise.\n */\n some(predicate: ElementCallback<E, R, boolean>, thisArg?: any): boolean {\n let index = 0;\n for (const item of this) {\n if (predicate.call(thisArg, item, index++, this)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `forEach` function iterates over each element in an array-like object and calls a callback\n * function for each element.\n * @param callbackfn - The callbackfn parameter is a function that will be called for each element in\n * the array. It takes three arguments: the current element being processed, the index of the current\n * element, and the array that forEach was called upon.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will\n * be passed as the `this` value to the `callbackfn` function. If `thisArg\n */\n forEach(callbackfn: ElementCallback<E, R, void>, thisArg?: any): void {\n let index = 0;\n for (const item of this) {\n callbackfn.call(thisArg, item, index++, this);\n }\n }\n\n find<S extends E>(predicate: ElementCallback<E, R, S>, thisArg?: any): S | undefined;\n find(predicate: ElementCallback<E, R, unknown>, thisArg?: any): E | undefined;\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `find` function iterates over the elements of an array-like object and returns the first\n * element that satisfies the provided callback function.\n * @param predicate - The predicate parameter is a function that will be called for each element in\n * the array. It takes three arguments: the current element being processed, the index of the current\n * element, and the array itself. The function should return a boolean value indicating whether the\n * current element matches the desired condition.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will\n * be passed as the `this` value to the `callbackfn` function. If `thisArg\n * @returns The `find` method returns the first element in the array that satisfies the provided\n * callback function. If no element satisfies the callback function, `undefined` is returned.\n */\n find(predicate: ElementCallback<E, R, boolean>, thisArg?: any): E | undefined {\n let index = 0;\n for (const item of this) {\n if (predicate.call(thisArg, item, index++, this)) return item;\n }\n\n return;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function checks if a given element exists in a collection.\n * @param {E} element - The parameter \"element\" is of type E, which means it can be any type. It\n * represents the element that we want to check for existence in the collection.\n * @returns a boolean value. It returns true if the element is found in the collection, and false\n * otherwise.\n */\n has(element: E): boolean {\n for (const ele of this) {\n if (ele === element) return true;\n }\n return false;\n }\n\n reduce(callbackfn: ReduceElementCallback<E, R>): E;\n reduce(callbackfn: ReduceElementCallback<E, R>, initialValue: E): E;\n reduce<U>(callbackfn: ReduceElementCallback<E, R, U>, initialValue: U): U;\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `reduce` function iterates over the elements of an array-like object and applies a callback\n * function to reduce them into a single value.\n * @param callbackfn - The callbackfn parameter is a function that will be called for each element in\n * the array. It takes four arguments:\n * @param {U} initialValue - The initialValue parameter is the initial value of the accumulator. It\n * is the value that the accumulator starts with before the reduction operation begins.\n * @returns The `reduce` method is returning the final value of the accumulator after iterating over\n * all the elements in the array and applying the callback function to each element.\n */\n reduce<U>(callbackfn: ReduceElementCallback<E, R, U>, initialValue?: U): U {\n let accumulator = initialValue ?? (0 as U);\n let index = 0;\n for (const item of this) {\n accumulator = callbackfn(accumulator, item, index++, this);\n }\n return accumulator;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `toArray` function converts a linked list into an array.\n * @returns The `toArray()` method is returning an array of type `E[]`.\n */\n toArray(): E[] {\n return [...this];\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The print function logs the elements of an array to the console.\n */\n toVisual(): E[] {\n return [...this];\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The print function logs the elements of an array to the console.\n */\n print(): void {\n console.log(this.toVisual());\n }\n\n abstract isEmpty(): boolean;\n\n abstract clear(): void;\n\n abstract clone(): IterableElementBase<E, R>;\n\n abstract map(...args: any[]): any;\n\n abstract filter(...args: any[]): any;\n\n protected abstract _getIterator(...args: any[]): IterableIterator<E>;\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { Comparable, ComparablePrimitive, Thunk } from '../types';\n\n/**\n * The function generates a random UUID (Universally Unique Identifier) in TypeScript.\n * @returns A randomly generated UUID (Universally Unique Identifier) in the format\n * 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' where each 'x' is replaced with a random hexadecimal\n * character.\n */\nexport const uuidV4 = function () {\n return 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, function (c) {\n const r = (Math.random() * 16) | 0,\n v = c == 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n\n/**\n * The `arrayRemove` function removes elements from an array based on a specified predicate function\n * and returns the removed elements.\n * @param {T[]} array - An array of elements that you want to filter based on the provided predicate\n * function.\n * @param predicate - The `predicate` parameter is a function that takes three arguments:\n * @returns The `arrayRemove` function returns an array containing the elements that satisfy the given\n * `predicate` function.\n */\nexport const arrayRemove = function <T>(array: T[], predicate: (item: T, index: number, array: T[]) => boolean): T[] {\n let i = -1,\n len = array ? array.length : 0;\n const result = [];\n\n while (++i < len) {\n const value = array[i];\n if (predicate(value, i, array)) {\n result.push(value);\n Array.prototype.splice.call(array, i--, 1);\n len--;\n }\n }\n\n return result;\n};\n\n\nexport function isThunk<T>(result: T | Thunk<T>): result is Thunk<T> {\n return typeof result === 'function';\n}\n\nexport function trampoline<T>(thunk: Thunk<T>): T {\n let result: T | Thunk<T> = thunk;\n while (isThunk(result)) {\n result = result();\n }\n return result;\n}\n\n/**\n * The function `getMSB` returns the most significant bit of a given number.\n * @param {number} value - The `value` parameter is a number for which we want to find the position of\n * the Most Significant Bit (MSB). The function `getMSB` takes this number as input and calculates the\n * position of the MSB in its binary representation.\n * @returns The function `getMSB` returns the most significant bit (MSB) of the input `value`. If the\n * input value is less than or equal to 0, it returns 0. Otherwise, it calculates the position of the\n * MSB using the `Math.clz32` function and bitwise left shifts 1 to that position.\n */\nexport const getMSB = (value: number): number => {\n if (value <= 0) {\n return 0;\n }\n return 1 << (31 - Math.clz32(value));\n};\n\n/**\n * The `rangeCheck` function in TypeScript is used to validate if an index is within a specified range\n * and throws a `RangeError` with a custom message if it is out of bounds.\n * @param {number} index - The `index` parameter represents the value that you want to check if it\n * falls within a specified range.\n * @param {number} min - The `min` parameter represents the minimum value that the `index` should be\n * compared against in the `rangeCheck` function.\n * @param {number} max - The `max` parameter in the `rangeCheck` function represents the maximum value\n * that the `index` parameter is allowed to have. If the `index` is greater than this `max` value, a\n * `RangeError` will be thrown.\n * @param [message=Index out of bounds.] - The `message` parameter is a string that represents the\n * error message to be thrown if the index is out of bounds. By default, if no message is provided when\n * calling the `rangeCheck` function, the message \"Index out of bounds.\" will be used.\n */\nexport const rangeCheck = (index: number, min: number, max: number, message = 'Index out of bounds.'): void => {\n if (index < min || index > max) throw new RangeError(message);\n};\n\n/**\n * The function `throwRangeError` throws a RangeError with a custom message if called.\n * @param [message=The value is off-limits.] - The `message` parameter is a string that represents the\n * error message to be displayed when a `RangeError` is thrown. If no message is provided, the default\n * message is 'The value is off-limits.'.\n */\nexport const throwRangeError = (message = 'The value is off-limits.'): void => {\n throw new RangeError(message);\n};\n\n/**\n * The function `isWeakKey` checks if the input is an object or a function in TypeScript.\n * @param {unknown} input - The `input` parameter in the `isWeakKey` function is of type `unknown`,\n * which means it can be any type. The function checks if the `input` is an object (excluding `null`)\n * or a function, and returns a boolean indicating whether the `input` is a weak\n * @returns The function `isWeakKey` returns a boolean value indicating whether the input is an object\n * or a function.\n */\nexport const isWeakKey = (input: unknown): input is object => {\n const inputType = typeof input;\n return (inputType === 'object' && input !== null) || inputType === 'function';\n};\n\n/**\n * The function `calcMinUnitsRequired` calculates the minimum number of units required to accommodate a\n * given total quantity based on a specified unit size.\n * @param {number} totalQuantity - The `totalQuantity` parameter represents the total quantity of items\n * that need to be processed or handled.\n * @param {number} unitSize - The `unitSize` parameter represents the size of each unit or package. It\n * is used in the `calcMinUnitsRequired` function to calculate the minimum number of units required to\n * accommodate a total quantity of items.\n */\nexport const calcMinUnitsRequired = (totalQuantity: number, unitSize: number) =>\n Math.floor((totalQuantity + unitSize - 1) / unitSize);\n\n/**\n * The `roundFixed` function in TypeScript rounds a number to a specified number of decimal places.\n * @param {number} num - The `num` parameter is a number that you want to round to a certain number of\n * decimal places.\n * @param {number} [digit=10] - The `digit` parameter in the `roundFixed` function specifies the number\n * of decimal places to round the number to. By default, it is set to 10 if not provided explicitly.\n * @returns The function `roundFixed` returns a number that is rounded to the specified number of\n * decimal places (default is 10 decimal places).\n */\nexport const roundFixed = (num: number, digit: number = 10) => {\n const multiplier = Math.pow(10, digit);\n return Math.round(num * multiplier) / multiplier;\n};\n\n/**\n * The function `isPrimitiveComparable` checks if a value is a primitive type that can be compared.\n * @param {unknown} value - The `value` parameter in the `isPrimitiveComparable` function is of type\n * `unknown`, which means it can be any type. The function checks if the `value` is a primitive type\n * that can be compared, such as number, bigint, string, or boolean.\n * @returns The function `isPrimitiveComparable` returns a boolean value indicating whether the input\n * `value` is a primitive value that can be compared using standard comparison operators (<, >, <=,\n * >=).\n */\nfunction isPrimitiveComparable(value: unknown): value is ComparablePrimitive {\n const valueType = typeof value;\n if (valueType === 'number') return true;\n // if (valueType === 'number') return !Number.isNaN(value);\n return valueType === 'bigint' || valueType === 'string' || valueType === 'boolean';\n}\n\n/**\n * The function `tryObjectToPrimitive` attempts to convert an object to a comparable primitive value by\n * first checking the `valueOf` method and then the `toString` method.\n * @param {object} obj - The `obj` parameter in the `tryObjectToPrimitive` function is an object that\n * you want to convert to a primitive value. The function attempts to convert the object to a primitive\n * value by first checking if the object has a `valueOf` method. If the `valueOf` method exists, it\n * @returns The function `tryObjectToPrimitive` returns a value of type `ComparablePrimitive` if a\n * primitive comparable value is found within the object, or a string value if the object has a custom\n * `toString` method that does not return `'[object Object]'`. If neither condition is met, the\n * function returns `null`.\n */\nfunction tryObjectToPrimitive(obj: object): ComparablePrimitive | null {\n if (typeof obj.valueOf === 'function') {\n const valueOfResult = obj.valueOf();\n if (valueOfResult !== obj) {\n if (isPrimitiveComparable(valueOfResult)) return valueOfResult;\n if (typeof valueOfResult === 'object' && valueOfResult !== null) return tryObjectToPrimitive(valueOfResult);\n }\n }\n if (typeof obj.toString === 'function') {\n const stringResult = obj.toString();\n if (stringResult !== '[object Object]') return stringResult;\n }\n return null;\n}\n\n/**\n * The function `isComparable` in TypeScript checks if a value is comparable, handling primitive values\n * and objects with optional force comparison.\n * @param {unknown} value - The `value` parameter in the `isComparable` function represents the value\n * that you want to check if it is comparable. It can be of any type (`unknown`), and the function will\n * determine if it is comparable based on certain conditions.\n * @param [isForceObjectComparable=false] - The `isForceObjectComparable` parameter in the\n * `isComparable` function is a boolean flag that determines whether to treat non-primitive values as\n * comparable objects. When set to `true`, it forces the function to consider non-primitive values as\n * comparable objects, regardless of their type.\n * @returns The function `isComparable` returns a boolean value indicating whether the `value` is\n * considered comparable or not.\n */\nexport function isComparable(value: unknown, isForceObjectComparable = false): value is Comparable {\n if (value === null || value === undefined) return false;\n if (isPrimitiveComparable(value)) return true;\n\n if (typeof value !== 'object') return false;\n if (value instanceof Date) return true;\n // if (value instanceof Date) return !Number.isNaN(value.getTime());\n if (isForceObjectComparable) return true;\n const comparableValue = tryObjectToPrimitive(value);\n if (comparableValue === null || comparableValue === undefined) return false;\n return isPrimitiveComparable(comparableValue);\n}\n","/**\n * The function `toBinaryString` converts a number to a binary string representation with a specified\n * number of digits.\n * @param {number} num - The `num` parameter in the `toBinaryString` function represents the number\n * that you want to convert to a binary string.\n * @param [digit=32] - The `digit` parameter in the `toBinaryString` function represents the number of\n * digits the binary string should have. By default, it is set to 32, meaning that the binary string\n * will be padded with zeros at the beginning to ensure it is 32 bits long. You can provide a\n * @returns The function `toBinaryString` takes a number as input and converts it to a binary string\n * representation with a specified number of digits (default is 32). The binary string is padded with\n * zeros at the beginning to ensure it has the specified number of digits. The function returns the\n * binary string representation of the input number.\n */\nexport function toBinaryString(num: number, digit = 32) {\n // Convert number to binary string\n let binaryString = (num >>> 0).toString(2); // Use the unsigned right shift operator to ensure you get a binary representation of a 32-bit unsigned integer\n\n // Use pad Start to ensure the string length is 32 bits\n binaryString = binaryString.padStart(digit, '0');\n\n return binaryString;\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type {\n EntryCallback,\n HashMapLinkedNode,\n HashMapOptions,\n HashMapStoreItem,\n LinkedHashMapOptions\n} from '../../types';\nimport { IterableEntryBase } from '../base';\nimport { isWeakKey, rangeCheck } from '../../utils';\n\n/**\n * 1. Key-Value Pair Storage: HashMap stores key-value pairs. Each key map to a value.\n * 2. Fast Lookup: It's used when you need to quickly find, insert, or delete entries based on a key.\n * 3. Unique Keys: Keys are unique.\n * If you try to insert another entry with the same key, the new one will replace the old entry.\n * 4. Unordered Collection: HashMap does not guarantee the order of entries, and the order may change over time.\n * @example\n * // should maintain insertion order\n * const linkedHashMap = new LinkedHashMap<number, string>();\n * linkedHashMap.set(1, 'A');\n * linkedHashMap.set(2, 'B');\n * linkedHashMap.set(3, 'C');\n *\n * const result = Array.from(linkedHashMap);\n * console.log(result); // [\n * // [1, 'A'],\n * // [2, 'B'],\n * // [3, 'C']\n * // ]\n * @example\n * // fast lookup of values by key\n * const hashMap = new HashMap<number, string>();\n * hashMap.set(1, 'A');\n * hashMap.set(2, 'B');\n * hashMap.set(3, 'C');\n *\n * console.log(hashMap.get(1)); // 'A'\n * console.log(hashMap.get(2)); // 'B'\n * console.log(hashMap.get(3)); // 'C'\n * console.log(hashMap.get(99)); // undefined\n * @example\n * // remove duplicates when adding multiple entries\n * const hashMap = new HashMap<number, string>();\n * hashMap.set(1, 'A');\n * hashMap.set(2, 'B');\n * hashMap.set(1, 'C'); // Update value for key 1\n *\n * console.log(hashMap.size); // 2\n * console.log(hashMap.get(1)); // 'C'\n * console.log(hashMap.get(2)); // 'B'\n * @example\n * // count occurrences of keys\n * const data = [1, 2, 1, 3, 2, 1];\n *\n * const countMap = new HashMap<number, number>();\n * for (const key of data) {\n * countMap.set(key, (countMap.get(key) || 0) + 1);\n * }\n *\n * console.log(countMap.get(1)); // 3\n * console.log(countMap.get(2)); // 2\n * console.log(countMap.get(3)); // 1\n */\nexport class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K, V> {\n /**\n * The constructor function initializes a HashMap object with an optional initial collection and\n * options.\n * @param entryOrRawElements - The `entryOrRawElements` parameter is an iterable collection of elements of a type\n * `T`. It is an optional parameter and its default value is an empty array `[]`.\n * @param [options] - The `options` parameter is an optional object that can contain two properties:\n */\n constructor(entryOrRawElements: Iterable<R | [K, V]> = [], options?: HashMapOptions<K, V, R>) {\n super();\n if (options) {\n const { hashFn, toEntryFn } = options;\n if (hashFn) this._hashFn = hashFn;\n if (toEntryFn) this._toEntryFn = toEntryFn;\n }\n if (entryOrRawElements) {\n this.setMany(entryOrRawElements);\n }\n }\n\n protected _store: { [key: string]: HashMapStoreItem<K, V> } = {};\n\n /**\n * The function returns the store object, which is a dictionary of HashMapStoreItem objects.\n * @returns The store property is being returned. It is a dictionary-like object with string keys and\n * values of type HashMapStoreItem<K, V>.\n */\n get store(): { [p: string]: HashMapStoreItem<K, V> } {\n return this._store;\n }\n\n protected _objMap: Map<object, V> = new Map();\n\n /**\n * The function returns the object map.\n * @returns The `objMap` property is being returned, which is a `Map` object with keys of type\n * `object` and values of type `V`.\n */\n get objMap(): Map<object, V> {\n return this._objMap;\n }\n\n protected _toEntryFn?: (rawElement: R) => [K, V];\n\n /**\n * The function returns the value of the _toEntryFn property.\n * @returns The function being returned is `this._toEntryFn`.\n */\n get toEntryFn() {\n return this._toEntryFn;\n }\n\n protected _size = 0;\n\n /**\n * The function returns the size of an object.\n * @returns The size of the object, which is a number.\n */\n get size(): number {\n return this._size;\n }\n\n protected _hashFn: (key: K) => string = (key: K) => String(key);\n\n /**\n * The hasFn function is a function that takes in an item and returns a boolean\n * indicating whether the item is contained within the hash table.\n *\n * @return The hash function\n */\n get hashFn() {\n return this._hashFn;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if a given element is an array with exactly two elements.\n * @param {any} rawElement - The `rawElement` parameter is of type `any`, which means it can be any\n * data type.\n * @returns a boolean value.\n */\n isEntry(rawElement: any): rawElement is [K, V] {\n return Array.isArray(rawElement) && rawElement.length === 2;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if the size of an object is equal to zero and returns a boolean value.\n * @returns A boolean value indicating whether the size of the object is 0 or not.\n */\n isEmpty(): boolean {\n return this._size === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear() function resets the state of an object by clearing its internal store, object map, and\n * size.\n */\n clear() {\n this._store = {};\n this._objMap.clear();\n this._size = 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `set` function adds a key-value pair to a map-like data structure, incrementing the size if\n * the key is not already present.\n * @param {K} key - The key parameter is the key used to identify the value in the data structure. It\n * can be of any type, but if it is an object, it will be stored in a Map, otherwise it will be\n * stored in a regular JavaScript object.\n * @param {V} value - The value parameter represents the value that you want to associate with the\n * key in the data structure.\n */\n set(key: K, value: V): boolean {\n if (this._isObjKey(key)) {\n if (!this.objMap.has(key)) {\n this._size++;\n }\n this.objMap.set(key, value);\n } else {\n const strKey = this._getNoObjKey(key);\n if (this.store[strKey] === undefined) {\n this._size++;\n }\n this._store[strKey] = { key, value };\n }\n return true;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The function `setMany` takes an iterable collection of objects, maps each object to a key-value\n * pair using a mapping function, and sets each key-value pair in the current object.\n * @param entryOrRawElements - The `entryOrRawElements` parameter is an iterable collection of elements of a type\n * `T`.\n * @returns The `setMany` function is returning an array of booleans.\n */\n setMany(entryOrRawElements: Iterable<R | [K, V]>): boolean[] {\n const results: boolean[] = [];\n for (const rawEle of entryOrRawElements) {\n let key: K | undefined, value: V | undefined;\n if (this.isEntry(rawEle)) {\n key = rawEle[0];\n value = rawEle[1];\n } else if (this._toEntryFn) {\n const item = this._toEntryFn(rawEle);\n key = item[0];\n value = item[1];\n }\n\n if (key !== undefined && value !== undefined) results.push(this.set(key, value));\n }\n return results;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `get` function retrieves a value from a map based on a given key, either from an object map or\n * a string map.\n * @param {K} key - The `key` parameter is the key used to retrieve a value from the map. It can be\n * of any type, but it should be compatible with the key type used when the map was created.\n * @returns The method `get(key: K)` returns a value of type `V` if the key exists in the `_objMap`\n * or `_store`, otherwise it returns `undefined`.\n */\n override get(key: K): V | undefined {\n if (this._isObjKey(key)) {\n return this.objMap.get(key);\n } else {\n const strKey = this._getNoObjKey(key);\n return this._store[strKey]?.value;\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `has` function checks if a given key exists in the `_objMap` or `_store` based on whether it\n * is an object key or not.\n * @param {K} key - The parameter \"key\" is of type K, which means it can be any type.\n * @returns The `has` method is returning a boolean value.\n */\n override has(key: K): boolean {\n if (this._isObjKey(key)) {\n return this.objMap.has(key);\n } else {\n const strKey = this._getNoObjKey(key);\n return strKey in this.store;\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `delete` function removes an element from a map-like data structure based on the provided key.\n * @param {K} key - The `key` parameter is the key of the element that you want to delete from the\n * data structure.\n * @returns The `delete` method returns a boolean value. It returns `true` if the key was\n * successfully deleted from the map, and `false` if the key was not found in the map.\n */\n delete(key: K): boolean {\n if (this._isObjKey(key)) {\n if (this.objMap.has(key)) {\n this._size--;\n }\n\n return this.objMap.delete(key);\n } else {\n const strKey = this._getNoObjKey(key);\n if (strKey in this.store) {\n delete this.store[strKey];\n this._size--;\n return true;\n }\n return false;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The clone function creates a new HashMap with the same key-value pairs as\n * this one. The clone function is useful for creating a copy of an existing\n * HashMap, and then modifying that copy without affecting the original.\n *\n * @return A new hashmap with the same values as this one\n */\n clone(): HashMap<K, V, R> {\n return new HashMap<K, V, R>(this, { hashFn: this._hashFn, toEntryFn: this._toEntryFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function in TypeScript creates a new HashMap by applying a callback function to each\n * key-value pair in the original HashMap.\n * @param callbackfn - The callback function that will be called for each key-value pair in the\n * HashMap. It takes four parameters:\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will\n * be passed as the `this` value to the `callbackfn` function. If `thisArg\n * @returns The `map` method is returning a new `HashMap` object with the transformed values based on\n * the provided callback function.\n */\n map<VM>(callbackfn: EntryCallback<K, V, VM>, thisArg?: any): HashMap<K, VM> {\n const resultMap = new HashMap<K, VM>();\n let index = 0;\n for (const [key, value] of this) {\n resultMap.set(key, callbackfn.call(thisArg, key, value, index++, this));\n }\n return resultMap;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new HashMap containing key-value pairs from the original HashMap\n * that satisfy a given predicate function.\n * @param predicate - The predicate parameter is a function that takes four arguments: value, key,\n * index, and map. It is used to determine whether an element should be included in the filtered map\n * or not. The function should return a boolean value - true if the element should be included, and\n * false otherwise.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `predicate` function. If `thisArg` is\n * @returns The `filter` method is returning a new `HashMap` object that contains the key-value pairs\n * from the original `HashMap` that pass the provided `predicate` function.\n */\n filter(predicate: EntryCallback<K, V, boolean>, thisArg?: any): HashMap<K, V> {\n const filteredMap = new HashMap<K, V>();\n let index = 0;\n for (const [key, value] of this) {\n if (predicate.call(thisArg, key, value, index++, this)) {\n filteredMap.set(key, value);\n }\n }\n return filteredMap;\n }\n\n /**\n * The function returns an iterator that yields key-value pairs from both an object store and an\n * object map.\n */\n protected *_getIterator(): IterableIterator<[K, V]> {\n for (const node of Object.values(this.store)) {\n yield [node.key, node.value] as [K, V];\n }\n for (const node of this.objMap) {\n yield node as [K, V];\n }\n }\n\n /**\n * The function checks if a given key is an object or a function.\n * @param {any} key - The parameter \"key\" can be of any type.\n * @returns a boolean value.\n */\n protected _isObjKey(key: any): key is object | ((...args: any[]) => any) {\n const keyType = typeof key;\n return (keyType === 'object' || keyType === 'function') && key !== null;\n }\n\n /**\n * The function `_getNoObjKey` takes a key and returns a string representation of the key, handling\n * different types of keys.\n * @param {K} key - The `key` parameter is of type `K`, which represents the type of the key being\n * passed to the `_getNoObjKey` function.\n * @returns a string value.\n */\n protected _getNoObjKey(key: K): string {\n const keyType = typeof key;\n\n let strKey: string;\n if (keyType !== 'string' && keyType !== 'number' && keyType !== 'symbol') {\n strKey = this._hashFn(key);\n } else {\n if (keyType === 'number') {\n // TODO numeric key should has its own hash\n strKey = <string>key;\n } else {\n strKey = <string>key;\n }\n }\n return strKey;\n }\n}\n\n/**\n * 1. Maintaining the Order of Element Insertion: Unlike HashMap, LinkedHashMap maintains the order in which entries are inserted. Therefore, when you traverse it, entries will be returned in the order they were inserted into the map.\n * 2. Based on Hash Table and Linked List: It combines the structures of a hash table and a linked list, using the hash table to ensure fast access, while maintaining the order of entries through the linked list.\n * 3. Time Complexity: Similar to HashMap, LinkedHashMap offers constant-time performance for get and put operations in most cases.\n */\nexport class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K, V> {\n protected readonly _sentinel: HashMapLinkedNode<K, V | undefined>;\n\n /**\n * The constructor initializes a LinkedHashMap object with an optional raw collection and options.\n * @param entryOrRawElements - The `entryOrRawElements` parameter is an iterable collection of elements. It is\n * used to initialize the HashMapLinked instance with key-value pairs. Each element in the\n * `entryOrRawElements` is converted to a key-value pair using the `toEntryFn` function (if provided) and\n * then added to the HashMap\n * @param [options] - The `options` parameter is an optional object that can contain the following\n * properties:\n */\n constructor(entryOrRawElements: Iterable<R | [K, V]> = [], options?: LinkedHashMapOptions<K, V, R>) {\n super();\n this._sentinel = <HashMapLinkedNode<K, V>>{};\n this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel;\n\n if (options) {\n const { hashFn, objHashFn, toEntryFn } = options;\n if (hashFn) this._hashFn = hashFn;\n if (objHashFn) this._objHashFn = objHashFn;\n\n if (toEntryFn) {\n this._toEntryFn = toEntryFn;\n }\n }\n\n if (entryOrRawElements) {\n this.setMany(entryOrRawElements);\n }\n }\n\n protected _hashFn: (key: K) => string = (key: K) => String(key);\n\n /**\n * The function returns the hash function used for generating a hash value for a given key.\n * @returns The hash function that takes a key of type K and returns a string.\n */\n get hashFn(): (key: K) => string {\n return this._hashFn;\n }\n\n protected _objHashFn: (key: K) => object = (key: K) => <object>key;\n\n /**\n * The function returns the object hash function.\n * @returns The function `objHashFn` is being returned.\n */\n get objHashFn(): (key: K) => object {\n return this._objHashFn;\n }\n\n protected _noObjMap: Record<string, HashMapLinkedNode<K, V | undefined>> = {};\n\n /**\n * The function returns a record of HashMapLinkedNode objects with string keys.\n * @returns The method is returning a Record object, which is a TypeScript type that represents an\n * object with string keys and values that are HashMapLinkedNode objects with keys of type K and\n * values of type V or undefined.\n */\n get noObjMap(): Record<string, HashMapLinkedNode<K, V | undefined>> {\n return this._noObjMap;\n }\n\n protected _objMap = new WeakMap<object, HashMapLinkedNode<K, V | undefined>>();\n\n /**\n * The function returns the WeakMap object used to map objects to HashMapLinkedNode instances.\n * @returns The `objMap` property is being returned.\n */\n get objMap(): WeakMap<object, HashMapLinkedNode<K, V | undefined>> {\n return this._objMap;\n }\n\n protected _head: HashMapLinkedNode<K, V | undefined>;\n\n /**\n * The function returns the head node of a HashMapLinkedNode.\n * @returns The method `getHead()` is returning a `HashMapLinkedNode` object with key type `K` and\n * a value type `V | undefined`.\n */\n get head(): HashMapLinkedNode<K, V | undefined> {\n return this._head;\n }\n\n protected _tail: HashMapLinkedNode<K, V | undefined>;\n\n /**\n * The function returns the tail node of a HashMapLinkedNode.\n * @returns The `_tail` property of type `HashMapLinkedNode<K, V | undefined>` is being returned.\n */\n get tail(): HashMapLinkedNode<K, V | undefined> {\n return this._tail;\n }\n\n protected _toEntryFn?: (rawElement: R) => [K, V] = (rawElement: R) => {\n if (this.isEntry(rawElement)) {\n // TODO, For performance optimization, it may be necessary to only inspect the first element traversed.\n return rawElement;\n } else {\n throw new Error(\n \"If the provided entryOrRawElements does not adhere to the [key, value] type format, the toEntryFn in the constructor's options parameter needs to specified.\"\n );\n }\n };\n\n /**\n * The function returns the value of the _toEntryFn property.\n * @returns The function being returned is `this._toEntryFn`.\n */\n get toEntryFn() {\n return this._toEntryFn;\n }\n\n protected _size = 0;\n\n /**\n * The function returns the size of an object.\n * @returns The size of the object.\n */\n get size() {\n return this._size;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function returns the key-value pair at the front of a data structure.\n * @returns The front element of the data structure, represented as a tuple with a key (K) and a\n * value (V).\n */\n get first() {\n if (this._size === 0) return;\n return <[K, V]>[this.head.key, this.head.value];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function returns the key-value pair at the end of a data structure.\n * @returns The method is returning an array containing the key-value pair of the tail element in the\n * data structure.\n */\n get last() {\n if (this._size === 0) return;\n return <[K, V]>[this.tail.key, this.tail.value];\n }\n\n /**\n * The `begin()` function in TypeScript iterates over a linked list and yields key-value pairs.\n */\n *begin() {\n let node = this.head;\n while (node !== this._sentinel) {\n yield [node.key, node.value];\n node = node.next;\n }\n }\n\n /**\n * The function `reverseBegin()` iterates over a linked list in reverse order, yielding each node's\n * key and value.\n */\n *reverseBegin() {\n let node = this.tail;\n while (node !== this._sentinel) {\n yield [node.key, node.value];\n node = node.prev;\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `set` function adds a new key-value pair to a data structure, either using an object key or a\n * string key.\n * @param {K} key - The `key` parameter is the key to be set in the data structure. It can be of any\n * type, but typically it is a string or symbol.\n * @param {V} [value] - The `value` parameter is an optional parameter of type `V`. It represents the\n * value associated with the key being set in the data structure.\n * @returns the size of the data structure after the key-value pair has been set.\n */\n set(key: K, value?: V): boolean {\n let node;\n const isNewKey = !this.has(key); // Check if the key is new\n\n if (isWeakKey(key)) {\n const hash = this._objHashFn(key);\n node = this.objMap.get(hash);\n\n if (!node && isNewKey) {\n // Create a new node\n node = { key: <K>hash, value, prev: this.tail, next: this._sentinel };\n this.objMap.set(hash, node);\n } else if (node) {\n // Update the value of an existing node\n node.value = value;\n }\n } else {\n const hash = this._hashFn(key);\n node = this.noObjMap[hash];\n\n if (!node && isNewKey) {\n this.noObjMap[hash] = node = { key, value, prev: this.tail, next: this._sentinel };\n } else if (node) {\n // Update the value of an existing node\n node.value = value;\n }\n }\n\n if (node && isNewKey) {\n // Update the head and tail of the linked list\n if (this._size === 0) {\n this._head = node;\n this._sentinel.next = node;\n } else {\n this.tail.next = node;\n node.prev = this.tail; // Make sure that the prev of the new node points to the current tail node\n }\n this._tail = node;\n this._sentinel.prev = node;\n this._size++;\n }\n\n return true;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The function `setMany` takes an iterable collection, converts each element into a key-value pair\n * using a provided function, and sets each key-value pair in the current object, returning an array\n * of booleans indicating the success of each set operation.\n * @param entryOrRawElements - The entryOrRawElements parameter is an iterable collection of elements of type\n * R.\n * @returns The `setMany` function returns an array of booleans.\n */\n setMany(entryOrRawElements: Iterable<R | [K, V]>): boolean[] {\n const results: boolean[] = [];\n for (const rawEle of entryOrRawElements) {\n let key: K | undefined, value: V | undefined;\n if (this.isEntry(rawEle)) {\n key = rawEle[0];\n value = rawEle[1];\n } else if (this._toEntryFn) {\n const item = this._toEntryFn(rawEle);\n key = item[0];\n value = item[1];\n }\n\n if (key !== undefined && value !== undefined) results.push(this.set(key, value));\n }\n return results;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if a given key exists in a map, using different logic depending on whether the\n * key is a weak key or not.\n * @param {K} key - The `key` parameter is the key that is being checked for existence in the map.\n * @returns The method `has` is returning a boolean value.\n */\n override has(key: K): boolean {\n if (isWeakKey(key)) {\n const hash = this._objHashFn(key);\n return this.objMap.has(hash);\n } else {\n const hash = this._hashFn(key);\n return hash in this.noObjMap;\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `get` retrieves the value associated with a given key from a map, either by using the\n * key directly or by using an index stored in the key object.\n * @param {K} key - The `key` parameter is the key used to retrieve a value from the map. It can be\n * of any type, but typically it is a string or symbol.\n * @returns The value associated with the given key is being returned. If the key is an object key,\n * the value is retrieved from the `_nodes` array using the index stored in the `OBJ_KEY_INDEX`\n * property of the key. If the key is a string key, the value is retrieved from the `_noObjMap` object\n * using the key itself. If the key is not found, `undefined` is\n */\n override get(key: K): V | undefined {\n if (isWeakKey(key)) {\n const hash = this._objHashFn(key);\n const node = this.objMap.get(hash);\n return node ? node.value : undefined;\n } else {\n const hash = this._hashFn(key);\n const node = this.noObjMap[hash];\n return node ? node.value : undefined;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `at` retrieves the key-value pair at a specified index in a linked list.\n * @param {number} index - The index parameter is a number that represents the position of the\n * element we want to retrieve from the data structure.\n * @returns The method `at(index: number)` is returning an array containing the key-value pair at\n * the specified index in the data structure. The key-value pair is represented as a tuple `[K, V]`,\n * where `K` is the key and `V` is the value.\n */\n at(index: number): V | undefined {\n rangeCheck(index, 0, this._size - 1);\n let node = this.head;\n while (index--) {\n node = node.next;\n }\n return node.value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `delete` function removes a key-value pair from a map-like data structure.\n * @param {K} key - The `key` parameter is the key that you want to delete from the data structure.\n * It can be of any type, but typically it is a string or an object.\n * @returns a boolean value. It returns `true` if the deletion was successful, and `false` if the key\n * was not found.\n */\n delete(key: K): boolean {\n let node;\n\n if (isWeakKey(key)) {\n const hash = this._objHashFn(key);\n // Get nodes from WeakMap\n node = this.objMap.get(hash);\n\n if (!node) {\n return false; // If the node does not exist, return false\n }\n\n // Remove nodes from WeakMap\n this.objMap.delete(hash);\n } else {\n const hash = this._hashFn(key);\n // Get nodes from noObjMap\n node = this.noObjMap[hash];\n\n if (!node) {\n return false; // If the node does not exist, return false\n }\n\n // Remove nodes from orgMap\n delete this.noObjMap[hash];\n }\n\n // Remove node from doubly linked list\n this._deleteNode(node);\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `deleteAt` function deletes a node at a specified index in a linked list.\n * @param {number} index - The index parameter represents the position at which the node should be\n * deleted in the linked list.\n * @returns The size of the list after deleting the element at the specified index.\n */\n deleteAt(index: number): boolean {\n rangeCheck(index, 0, this._size - 1);\n let node = this.head;\n while (index--) {\n node = node.next;\n }\n return this._deleteNode(node);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if a data structure is empty by comparing its size to zero.\n * @returns The method is returning a boolean value indicating whether the size of the object is 0 or\n * not.\n */\n isEmpty(): boolean {\n return this._size === 0;\n }\n\n /**\n * The function checks if a given element is an array with exactly two elements.\n * @param {any} rawElement - The `rawElement` parameter is of type `any`, which means it can be any\n * data type.\n * @returns a boolean value.\n */\n isEntry(rawElement: any): rawElement is [K, V] {\n return Array.isArray(rawElement) && rawElement.length === 2;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `clear` function clears all the entries in a data structure and resets its properties.\n */\n clear(): void {\n this._noObjMap = {};\n this._size = 0;\n this._head = this._tail = this._sentinel.prev = this._sentinel.next = this._sentinel;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `clone` function creates a new instance of a `LinkedHashMap` with the same key-value pairs as\n * the original.\n * @returns The `clone()` method is returning a new instance of `LinkedHashMap<K, V>` that is a clone\n * of the original `LinkedHashMap` object.\n */\n clone(): LinkedHashMap<K, V> {\n const cloned = new LinkedHashMap<K, V>([], { hashFn: this._hashFn, objHashFn: this._objHashFn });\n for (const entry of this) {\n const [key, value] = entry;\n cloned.set(key, value);\n }\n return cloned;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new `LinkedHashMap` containing key-value pairs from the original\n * map that satisfy a given predicate function.\n * @param predicate - The `predicate` parameter is a callback function that takes four arguments:\n * `value`, `key`, `index`, and `this`. It should return a boolean value indicating whether the\n * current element should be included in the filtered map or not.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the `predicate` function. It is used when you want to bind a\n * specific object as the context for the `predicate` function. If `thisArg` is not provided, `this\n * @returns a new `LinkedHashMap` object that contains the key-value pairs from the original\n * `LinkedHashMap` object that satisfy the given predicate function.\n */\n filter(predicate: EntryCallback<K, V, boolean>, thisArg?: any): LinkedHashMap<K, V> {\n const filteredMap = new LinkedHashMap<K, V>();\n let index = 0;\n for (const [key, value] of this) {\n if (predicate.call(thisArg, key, value, index, this)) {\n filteredMap.set(key, value);\n }\n index++;\n }\n return filteredMap;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function in TypeScript creates a new `LinkedHashMap` by applying a callback function to\n * each key-value pair in the original map.\n * @param callback - The callback parameter is a function that will be called for each key-value pair\n * in the map. It takes four arguments: the value of the current key-value pair, the key of the\n * current key-value pair, the index of the current key-value pair, and the map itself. The callback\n * function should\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. If provided, the callback function will\n * be called with `thisArg` as its `this` value. If not provided, `this` will refer to the current\n * map\n * @returns a new `LinkedHashMap` object with the values mapped according to the provided callback\n * function.\n */\n map<MK, MV>(callback: EntryCallback<K, V, [MK, MV]>, thisArg?: any): LinkedHashMap<MK, MV> {\n const mappedMap = new LinkedHashMap<MK, MV>();\n let index = 0;\n for (const [key, value] of this) {\n const [newKey, newValue] = callback.call(thisArg, key, value, index, this);\n mappedMap.set(newKey, newValue);\n index++;\n }\n return mappedMap;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n * where n is the number of entries in the LinkedHashMap.\n *\n * The above function is an iterator that yields key-value pairs from a linked list.\n */\n protected *_getIterator() {\n let node = this.head;\n while (node !== this._sentinel) {\n yield [node.key, node.value] as [K, V];\n node = node.next;\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_deleteNode` function removes a node from a doubly linked list and updates the head and tail\n * pointers if necessary.\n * @param node - The `node` parameter is an instance of the `HashMapLinkedNode` class, which\n * represents a node in a linked list. It contains a key-value pair and references to the previous\n * and next nodes in the list.\n */\n protected _deleteNode(node: HashMapLinkedNode<K, V | undefined>): boolean {\n const { prev, next } = node;\n prev.next = next;\n next.prev = prev;\n\n if (node === this.head) {\n this._head = next;\n }\n\n if (node === this.tail) {\n this._tail = prev;\n }\n\n this._size -= 1;\n return true;\n }\n}\n","import { ElementCallback, LinearBaseOptions, ReduceLinearCallback } from '../../types';\nimport { IterableElementBase } from './iterable-element-base';\n\nexport class LinkedListNode<E = any> {\n constructor(value: E) {\n this._value = value;\n this._next = undefined;\n }\n\n protected _value: E;\n\n get value(): E {\n return this._value;\n }\n\n set value(value: E) {\n this._value = value;\n }\n\n protected _next: LinkedListNode<E> | undefined;\n\n get next(): LinkedListNode<E> | undefined {\n return this._next;\n }\n\n set next(value: LinkedListNode<E> | undefined) {\n this._next = value;\n }\n}\n\nexport abstract class LinearBase<\n E,\n R = any,\n NODE extends LinkedListNode<E> = LinkedListNode<E>\n> extends IterableElementBase<E, R> {\n /**\n * The constructor initializes the LinearBase class with optional options, setting the maximum length\n * if provided.\n * @param [options] - The `options` parameter is an optional object that can be passed to the\n * constructor. It is of type `LinearBaseOptions<E, R>`. The constructor checks if the `options`\n * object is provided and then extracts the `maxLen` property from it. If `maxLen` is a\n */\n protected constructor(options?: LinearBaseOptions<E, R>) {\n super(options);\n if (options) {\n const { maxLen } = options;\n if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0) this._maxLen = maxLen;\n }\n }\n\n abstract get length(): number;\n\n protected _maxLen: number = -1;\n\n get maxLen() {\n return this._maxLen;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function indexOf searches for a specified element starting from a given index in an array-like\n * object and returns the index of the first occurrence, or -1 if not found.\n * @param {E} searchElement - The `searchElement` parameter in the `indexOf` function represents the\n * element that you want to find within the array. The function will search for this element starting\n * from the `fromIndex` (if provided) up to the end of the array. If the `searchElement` is found\n * within the\n * @param {number} [fromIndex=0] - The `fromIndex` parameter in the `indexOf` function represents the\n * index at which to start searching for the `searchElement` within the array. If provided, the\n * search will begin at this index and continue to the end of the array. If `fromIndex` is not\n * specified, the default\n * @returns The `indexOf` method is returning the index of the `searchElement` if it is found in the\n * array starting from the `fromIndex`. If the `searchElement` is not found, it returns -1.\n */\n indexOf(searchElement: E, fromIndex: number = 0): number {\n // Boundary checks and adjustments\n if (this.length === 0) return -1;\n if (fromIndex < 0) fromIndex = this.length + fromIndex;\n if (fromIndex < 0) fromIndex = 0;\n\n // Iterating from the specified index to the end\n for (let i = fromIndex; i < this.length; i++) {\n const element = this.at(i);\n if (element === searchElement) return i;\n }\n\n return -1; // Not found\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `lastIndexOf` in TypeScript returns the index of the last occurrence of a specified\n * element in an array.\n * @param {E} searchElement - The `searchElement` parameter is the element that you want to find the\n * last index of within the array. The `lastIndexOf` method will search the array starting from the\n * `fromIndex` (or the end of the array if not specified) and return the index of the last occurrence\n * of the\n * @param {number} fromIndex - The `fromIndex` parameter in the `lastIndexOf` method specifies the\n * index at which to start searching for the `searchElement` in the array. By default, it starts\n * searching from the last element of the array (`this.length - 1`). If a specific `fromIndex` is\n * provided\n * @returns The last index of the `searchElement` in the array is being returned. If the\n * `searchElement` is not found in the array, -1 is returned.\n */\n lastIndexOf(searchElement: E, fromIndex: number = this.length - 1): number {\n if (this.length === 0) return -1;\n if (fromIndex >= this.length) fromIndex = this.length - 1;\n if (fromIndex < 0) fromIndex = this.length + fromIndex;\n\n for (let i = fromIndex; i >= 0; i--) {\n const element = this.at(i);\n if (element === searchElement) return i;\n }\n\n return -1;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `findIndex` function iterates over an array and returns the index of the first element that\n * satisfies the provided predicate function.\n * @param predicate - The `predicate` parameter in the `findIndex` function is a callback function\n * that takes three arguments: `item`, `index`, and the array `this`. It should return a boolean\n * value indicating whether the current element satisfies the condition being checked for.\n * @param {any} [thisArg] - The `thisArg` parameter in the `findIndex` function is an optional\n * parameter that specifies the value to use as `this` when executing the `predicate` function. If\n * provided, the `predicate` function will be called with `thisArg` as its `this` value. If `\n * @returns The `findIndex` method is returning the index of the first element in the array that\n * satisfies the provided predicate function. If no such element is found, it returns -1.\n */\n findIndex(predicate: ElementCallback<E, R, boolean>, thisArg?: any): number {\n for (let i = 0; i < this.length; i++) {\n const item = this.at(i);\n if (item !== undefined && predicate.call(thisArg, item, i, this)) return i;\n }\n return -1;\n }\n\n concat(...items: this[]): this;\n\n /**\n * Time Complexity: O(n + m)\n * Space Complexity: O(n + m)\n *\n * The `concat` function in TypeScript concatenates multiple items into a new list, handling both\n * individual elements and instances of `LinearBase`.\n * @param {(E | this)[]} items - The `concat` method takes in an array of items, where\n * each item can be either of type `E` or an instance of `LinearBase<E, R>`.\n * @returns The `concat` method is returning a new instance of the class that it belongs to, with the\n * items passed as arguments concatenated to it.\n */\n concat(...items: (E | this)[]): this {\n const newList = this.clone();\n\n for (const item of items) {\n if (item instanceof LinearBase) {\n newList.pushMany(item);\n } else {\n newList.push(item);\n }\n }\n\n return newList;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * The `sort` function in TypeScript sorts the elements of a collection using a specified comparison\n * function.\n * @param [compareFn] - The `compareFn` parameter is a function that defines the sort order. It takes\n * two elements `a` and `b` as input and returns a number indicating their relative order. If the\n * returned value is negative, `a` comes before `b`. If the returned value is positive, `\n * @returns The `sort` method is returning the instance of the object on which it is called (this),\n * after sorting the elements based on the provided comparison function (compareFn).\n */\n sort(compareFn?: (a: E, b: E) => number): this {\n const arr = this.toArray();\n arr.sort(compareFn);\n this.clear();\n for (const item of arr) this.push(item);\n return this;\n }\n\n /**\n * Time Complexity: O(n + m)\n * Space Complexity: O(m)\n *\n * The `splice` function in TypeScript removes elements from an array and optionally inserts new\n * elements at the specified index.\n * @param {number} start - The `start` parameter in the `splice` method indicates the index at which\n * to start modifying the array. If `start` is a negative number, it will count from the end of the\n * array.\n * @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the\n * number of elements to remove from the array starting at the specified `start` index. If\n * `deleteCount` is not provided or is 0, no elements are removed, and only new elements are inserted\n * at the `start`\n * @param {E[]} items - The `items` parameter in the `splice` method represents the elements that\n * will be inserted into the array at the specified `start` index. These elements can be of any type\n * and you can pass multiple elements separated by commas. The `splice` method will insert these\n * items into the array at the\n * @returns The `splice` method returns a list of elements that were removed from the original list\n * during the operation.\n */\n splice(start: number, deleteCount: number = 0, ...items: E[]): this {\n const removedList = this._createInstance();\n\n // Handling negative indexes and bounds\n start = start < 0 ? this.length + start : start;\n start = Math.max(0, Math.min(start, this.length));\n deleteCount = Math.max(0, Math.min(deleteCount, this.length - start));\n\n // Delete elements\n for (let i = 0; i < deleteCount; i++) {\n const removed = this.deleteAt(start); // Always delete the start position\n if (removed !== undefined) {\n removedList.push(removed); // Add removed elements to the returned list\n }\n }\n\n // Insert new element\n for (let i = 0; i < items.length; i++) {\n this.addAt(start + i, items[i]); // Insert new elements one by one at the current position\n }\n\n return removedList; // Returns a list of removed elements\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `join` function in TypeScript returns a string by joining the elements of an array with a\n * specified separator.\n * @param {string} [separator=,] - The `separator` parameter is a string that specifies the character\n * or characters that will be used to separate each element when joining them into a single string.\n * By default, the separator is set to a comma (`,`), but you can provide a different separator if\n * needed.\n * @returns The `join` method is being returned, which takes an optional `separator` parameter\n * (defaulting to a comma) and returns a string created by joining all elements of the array after\n * converting it to an array.\n */\n join(separator: string = ','): string {\n return this.toArray().join(separator);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `toReversedArray` takes an array and returns a new array with its elements in reverse\n * order.\n * @returns The `toReversedArray()` function returns an array of elements of type `E` in reverse\n * order.\n */\n toReversedArray(): E[] {\n const array: E[] = [];\n for (let i = this.length - 1; i >= 0; i--) {\n array.push(this.at(i)!);\n }\n return array;\n }\n\n reduceRight(callbackfn: ReduceLinearCallback<E>): E;\n\n reduceRight(callbackfn: ReduceLinearCallback<E>, initialValue: E): E;\n\n reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue: U): U;\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `reduceRight` function in TypeScript iterates over an array from right to left and applies a\n * callback function to each element, accumulating a single result.\n * @param callbackfn - The `callbackfn` parameter in the `reduceRight` method is a function that will\n * be called on each element in the array from right to left. It takes four arguments:\n * @param {U} [initialValue] - The `initialValue` parameter in the `reduceRight` method is an\n * optional parameter that specifies the initial value of the accumulator. If provided, the\n * `accumulator` will start with this initial value before iterating over the elements of the array.\n * If `initialValue` is not provided, the accumulator will\n * @returns The `reduceRight` method is returning the final accumulated value after applying the\n * callback function to each element in the array from right to left.\n */\n reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue?: U): U {\n let accumulator = initialValue ?? (0 as U);\n for (let i = this.length - 1; i >= 0; i--) {\n accumulator = callbackfn(accumulator, this.at(i)!, i, this);\n }\n return accumulator;\n }\n\n /**\n * Time Complexity: O(m)\n * Space Complexity: O(m)\n *\n * The `slice` function in TypeScript creates a new instance by extracting a portion of elements from\n * the original instance based on the specified start and end indices.\n * @param {number} [start=0] - The `start` parameter in the `slice` method represents the index at\n * which to begin extracting elements from an array-like object. If no `start` parameter is provided,\n * the default value is 0, meaning the extraction will start from the beginning of the array.\n * @param {number} end - The `end` parameter in the `slice` method represents the index at which to\n * end the slicing. By default, if no `end` parameter is provided, it will slice until the end of the\n * array (i.e., `this.length`).\n * @returns The `slice` method is returning a new instance of the object with elements sliced from\n * the specified start index (default is 0) to the specified end index (default is the length of the\n * object).\n */\n slice(start: number = 0, end: number = this.length): this {\n start = start < 0 ? this.length + start : start;\n end = end < 0 ? this.length + end : end;\n\n const newList = this._createInstance();\n for (let i = start; i < end; i++) {\n newList.push(this.at(i)!);\n }\n return newList;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `fill` function in TypeScript fills a specified range in an array-like object with a given\n * value.\n * @param {E} value - The `value` parameter in the `fill` method represents the element that will be\n * used to fill the specified range in the array.\n * @param [start=0] - The `start` parameter specifies the index at which to start filling the array\n * with the specified value. If not provided, it defaults to 0, indicating the beginning of the\n * array.\n * @param end - The `end` parameter in the `fill` function represents the index at which the filling\n * of values should stop. It specifies the end of the range within the array where the `value` should\n * be filled.\n * @returns The `fill` method is returning the modified object (`this`) after filling the specified\n * range with the provided value.\n */\n fill(value: E, start = 0, end = this.length): this {\n // Handling negative indexes\n start = start < 0 ? this.length + start : start;\n end = end < 0 ? this.length + end : end;\n\n // Boundary processing\n if (start < 0) start = 0;\n if (end > this.length) end = this.length;\n if (start >= end) return this;\n\n // Iterate through the specified range and fill in the values\n for (let i = start; i < end; i++) {\n this.setAt(i, value);\n }\n\n return this;\n }\n\n abstract setAt(index: number, value: E): boolean;\n\n abstract override clone(): this;\n\n abstract reverse(): this;\n\n abstract push(elementOrNode: E | NODE): boolean;\n\n abstract pushMany(elements: Iterable<E> | Iterable<R> | Iterable<NODE>): boolean[];\n\n abstract delete(elementOrNode: E | NODE | undefined): boolean;\n\n abstract at(index: number): E | undefined;\n\n abstract deleteAt(pos: number): E | undefined;\n\n abstract addAt(index: number, newElementOrNode: E | NODE): boolean;\n\n protected abstract _createInstance(options?: LinearBaseOptions<E, R>): this;\n\n protected abstract _getReverseIterator(...args: any[]): IterableIterator<E>;\n}\n\nexport abstract class LinearLinkedBase<\n E,\n R = any,\n NODE extends LinkedListNode<E> = LinkedListNode<E>\n> extends LinearBase<E, R, NODE> {\n /**\n * The constructor initializes the LinearBase class with optional options, setting the maximum length\n * if provided and valid.\n * @param [options] - The `options` parameter is an optional object that can be passed to the\n * constructor. It is of type `LinearBaseOptions<E, R>`. This object may contain properties such as\n * `maxLen`, which is a number representing the maximum length. If `maxLen` is a positive integer,\n */\n protected constructor(options?: LinearBaseOptions<E, R>) {\n super(options);\n if (options) {\n const { maxLen } = options;\n if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0) this._maxLen = maxLen;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function overrides the indexOf method to improve performance by searching for an element in a\n * custom array implementation starting from a specified index.\n * @param {E} searchElement - The `searchElement` parameter is the element that you are searching for\n * within the array. The `indexOf` method will return the index of the first occurrence of this\n * element within the array.\n * @param {number} [fromIndex=0] - The `fromIndex` parameter in the `indexOf` method specifies the\n * index in the array at which to start the search for the `searchElement`. If provided, the search\n * will begin at the specified index and continue to the end of the array. If not provided, the\n * search will start at index\n * @returns The `indexOf` method is returning the index of the `searchElement` if it is found in the\n * array starting from the `fromIndex`. If the `searchElement` is not found, it returns -1.\n */\n override indexOf(searchElement: E, fromIndex: number = 0): number {\n // In order to improve performance, it is best to override this method in the subclass of the array implementation\n const iterator = this._getIterator();\n let current = iterator.next();\n\n let index = 0;\n while (index < fromIndex) {\n current = iterator.next();\n index++;\n }\n\n while (!current.done) {\n if (current.value === searchElement) return index;\n current = iterator.next();\n index++;\n }\n\n return -1;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function overrides the lastIndexOf method in TypeScript to improve performance by searching\n * for an element in reverse order starting from a specified index.\n * @param {E} searchElement - The `searchElement` parameter is the element that you want to find\n * within the array. The `lastIndexOf` method searches the array for this element starting from the\n * end of the array (or from the specified `fromIndex` if provided) and returns the index of the last\n * occurrence of the element\n * @param {number} fromIndex - The `fromIndex` parameter in the `lastIndexOf` method specifies the\n * index at which to start searching for the `searchElement` in the array. If provided, the search\n * will begin at this index and move towards the beginning of the array. If not provided, the search\n * will start at the\n * @returns The `lastIndexOf` method is being overridden to search for the `searchElement` starting\n * from the specified `fromIndex` (defaulting to the end of the array). It iterates over the array in\n * reverse order using a custom iterator `_getReverseIterator` and returns the index of the last\n * occurrence of the `searchElement` if found, or -1 if not found.\n */\n override lastIndexOf(searchElement: E, fromIndex: number = this.length - 1): number {\n // In order to improve performance, it is best to override this method in the subclass of the array implementation\n const iterator = this._getReverseIterator();\n let current = iterator.next();\n\n let index = this.length - 1;\n while (index > fromIndex) {\n current = iterator.next();\n index--;\n }\n\n while (!current.done) {\n if (current.value === searchElement) return index;\n current = iterator.next();\n index--;\n }\n\n return -1;\n }\n\n override concat(...items: LinearBase<E, R>[]): this;\n\n /**\n * Time Complexity: O(n + m)\n * Space Complexity: O(n + m)\n *\n * The `concat` function in TypeScript overrides the default behavior to concatenate items into a new\n * list, handling both individual elements and instances of `LinearBase`.\n * @param {(E | LinearBase<E, R>)[]} items - The `concat` method you provided takes in a variable\n * number of arguments of type `E` or `LinearBase<E, R>`. The method concatenates these items to the\n * current list and returns a new list with the concatenated items.\n * @returns The `concat` method is returning a new instance of the class that it belongs to, with the\n * items passed as arguments concatenated to it.\n */\n override concat(...items: (E | LinearBase<E, R>)[]): this {\n const newList = this.clone();\n\n for (const item of items) {\n if (item instanceof LinearBase) {\n newList.pushMany(item);\n } else {\n newList.push(item);\n }\n }\n\n return newList;\n }\n\n /**\n * Time Complexity: O(m)\n * Space Complexity: O(m)\n *\n * The `slice` method is overridden to improve performance by creating a new instance and iterating\n * through the array to extract a subset based on the specified start and end indices.\n * @param {number} [start=0] - The `start` parameter in the `slice` method specifies the index at\n * which to begin extracting elements from the array. If no `start` parameter is provided, the\n * default value is 0, indicating that extraction should start from the beginning of the array.\n * @param {number} end - The `end` parameter in the `slice` method represents the index at which to\n * end the slicing of the array. If not provided, it defaults to the length of the array.\n * @returns The `slice` method is returning a new instance of the array implementation with elements\n * sliced from the original array based on the `start` and `end` parameters.\n */\n override slice(start: number = 0, end: number = this.length): this {\n // In order to improve performance, it is best to override this method in the subclass of the array implementation\n start = start < 0 ? this.length + start : start;\n end = end < 0 ? this.length + end : end;\n\n const newList = this._createInstance();\n const iterator = this._getIterator();\n let current = iterator.next();\n let c = 0;\n while (c < start) {\n current = iterator.next();\n c++;\n }\n for (let i = start; i < end; i++) {\n newList.push(current.value);\n current = iterator.next();\n }\n\n return newList;\n }\n\n /**\n * Time Complexity: O(n + m)\n * Space Complexity: O(m)\n *\n * The function overrides the splice method to handle deletion and insertion of elements in a data\n * structure while returning the removed elements.\n * @param {number} start - The `start` parameter in the `splice` method indicates the index at which\n * to start modifying the array.\n * @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the\n * number of elements to remove from the array starting at the specified `start` index. If\n * `deleteCount` is not provided, it defaults to 0, meaning no elements will be removed but new\n * elements can still be inserted at\n * @param {E[]} items - The `items` parameter in the `splice` method represents the elements that\n * will be inserted into the array at the specified `start` index. These elements can be of any type\n * and there can be multiple elements passed as arguments to be inserted into the array.\n * @returns The `splice` method is returning a new instance of the data structure that was modified\n * by removing elements specified by the `start` and `deleteCount` parameters, and inserting new\n * elements provided in the `items` array.\n */\n override splice(start: number, deleteCount: number = 0, ...items: E[]): this {\n const removedList = this._createInstance(); // Used to store deleted elements\n\n // Handling negative indexes\n start = start < 0 ? this.length + start : start;\n start = Math.max(0, Math.min(start, this.length)); // Correct start range\n deleteCount = Math.max(0, deleteCount); // Make sure deleteCount is non-negative\n\n let currentIndex = 0;\n let currentNode: NODE | undefined = undefined;\n let previousNode: NODE | undefined = undefined;\n\n // Find the starting point using an iterator\n const iterator = this._getNodeIterator();\n for (const node of iterator) {\n if (currentIndex === start) {\n currentNode = node; // Find the starting node\n break;\n }\n previousNode = node; // Update the previous node\n currentIndex++;\n }\n\n // Delete nodes\n for (let i = 0; i < deleteCount && currentNode; i++) {\n removedList.push(currentNode.value); // Store the deleted value in removedList\n const nextNode = currentNode.next; // Save next node\n this.delete(currentNode); // Delete current node\n currentNode = nextNode as NODE;\n }\n\n // Insert new value\n for (let i = 0; i < items.length; i++) {\n if (previousNode) {\n this.addAfter(previousNode, items[i]); // Insert after previousNode\n previousNode = previousNode.next as NODE; // Move to newly inserted node\n } else {\n this.addAt(0, items[i]); // Insert at the head of the linked list\n previousNode = this._getNodeIterator().next().value; // Update the head node to be the first inserted node\n }\n }\n\n return removedList;\n }\n\n override reduceRight(callbackfn: ReduceLinearCallback<E>): E;\n\n override reduceRight(callbackfn: ReduceLinearCallback<E>, initialValue: E): E;\n\n override reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue: U): U;\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `reduceRight` iterates over an array in reverse order and applies a callback function\n * to each element, accumulating a single result.\n * @param callbackfn - The `callbackfn` parameter is a function that will be called on each element\n * of the array from right to left. It takes four arguments:\n * @param {U} [initialValue] - The `initialValue` parameter is an optional value that is used as the\n * initial accumulator value in the reduce operation. If provided, the reduce operation starts with\n * this initial value and iterates over the elements of the array, applying the callback function to\n * each element and the current accumulator value. If `initial\n * @returns The `reduceRight` method is returning the final accumulated value after applying the\n * callback function to each element in the array from right to left.\n */\n override reduceRight<U>(callbackfn: ReduceLinearCallback<E, U>, initialValue?: U): U {\n let accumulator = initialValue ?? (0 as U);\n let index = this.length - 1;\n for (const item of this._getReverseIterator()) {\n accumulator = callbackfn(accumulator, item, index--, this);\n }\n return accumulator;\n }\n\n abstract override delete(elementOrNode: E | NODE | undefined): boolean;\n\n abstract addBefore(existingElementOrNode: E | NODE, newElementOrNode: E | NODE): boolean;\n\n abstract addAfter(existingElementOrNode: E | NODE, newElementOrNode: E | NODE): boolean;\n\n abstract getNodeAt(index: number): NODE | undefined;\n\n protected abstract _getNodeIterator(...args: any[]): IterableIterator<NODE>;\n\n // protected abstract _getReverseNodeIterator(...args: any[]): IterableIterator<NODE>;\n\n protected abstract _getPrevNode(node: NODE): NODE | undefined;\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { ElementCallback, SinglyLinkedListOptions } from '../../types';\nimport { LinearLinkedBase, LinkedListNode } from '../base/linear-base';\n\nexport class SinglyLinkedListNode<E = any> extends LinkedListNode<E> {\n /**\n * The constructor function initializes an instance of a class with a given value and sets the next property to undefined.\n * @param {E} value - The \"value\" parameter is of type E, which means it can be any data type. It represents the value that\n * will be stored in the node of a linked list.\n */\n constructor(value: E) {\n super(value);\n this._value = value;\n this._next = undefined;\n }\n\n protected override _next: SinglyLinkedListNode<E> | undefined;\n\n override get next(): SinglyLinkedListNode<E> | undefined {\n return this._next;\n }\n\n override set next(value: SinglyLinkedListNode<E> | undefined) {\n this._next = value;\n }\n}\n\n/**\n * 1. Node Structure: Each node contains three parts: a data field, a pointer (or reference) to the previous node, and a pointer to the next node. This structure allows traversal of the linked list in both directions.\n * 2. Bidirectional Traversal: Unlike doubly linked lists, singly linked lists can be easily traversed forwards but not backwards.\n * 3. No Centralized Index: Unlike arrays, elements in a linked list are not stored contiguously, so there is no centralized index. Accessing elements in a linked list typically requires traversing from the head or tail node.\n * 4. High Efficiency in Insertion and Deletion: Adding or removing elements in a linked list does not require moving other elements, making these operations more efficient than in arrays.\n * Caution: Although our linked list classes provide methods such as at, setAt, addAt, and indexOf that are based on array indices, their time complexity, like that of the native Array.lastIndexOf, is 𝑂(𝑛). If you need to use these methods frequently, you might want to consider other data structures, such as Deque or Queue (designed for random access). Similarly, since the native Array.shift method has a time complexity of 𝑂(𝑛), using an array to simulate a queue can be inefficient. In such cases, you should use Queue or Deque, as these data structures leverage deferred array rearrangement, effectively reducing the average time complexity to 𝑂(1).\n *\n * @example\n * // implementation of a basic text editor\n * class TextEditor {\n * private content: SinglyLinkedList<string>;\n * private cursorIndex: number;\n * private undoStack: Stack<{ operation: string; data?: any }>;\n *\n * constructor() {\n * this.content = new SinglyLinkedList<string>();\n * this.cursorIndex = 0; // Cursor starts at the beginning\n * this.undoStack = new Stack<{ operation: string; data?: any }>(); // Stack to keep track of operations for undo\n * }\n *\n * insert(char: string) {\n * this.content.addAt(this.cursorIndex, char);\n * this.cursorIndex++;\n * this.undoStack.push({ operation: 'insert', data: { index: this.cursorIndex - 1 } });\n * }\n *\n * delete() {\n * if (this.cursorIndex === 0) return; // Nothing to delete\n * const deleted = this.content.deleteAt(this.cursorIndex - 1);\n * this.cursorIndex--;\n * this.undoStack.push({ operation: 'delete', data: { index: this.cursorIndex, char: deleted } });\n * }\n *\n * moveCursor(index: number) {\n * this.cursorIndex = Math.max(0, Math.min(index, this.content.length));\n * }\n *\n * undo() {\n * if (this.undoStack.size === 0) return; // No operations to undo\n * const lastAction = this.undoStack.pop();\n *\n * if (lastAction!.operation === 'insert') {\n * this.content.deleteAt(lastAction!.data.index);\n * this.cursorIndex = lastAction!.data.index;\n * } else if (lastAction!.operation === 'delete') {\n * this.content.addAt(lastAction!.data.index, lastAction!.data.char);\n * this.cursorIndex = lastAction!.data.index + 1;\n * }\n * }\n *\n * getText(): string {\n * return [...this.content].join('');\n * }\n * }\n *\n * // Example Usage\n * const editor = new TextEditor();\n * editor.insert('H');\n * editor.insert('e');\n * editor.insert('l');\n * editor.insert('l');\n * editor.insert('o');\n * console.log(editor.getText()); // 'Hello' // Output: \"Hello\"\n *\n * editor.delete();\n * console.log(editor.getText()); // 'Hell' // Output: \"Hell\"\n *\n * editor.undo();\n * console.log(editor.getText()); // 'Hello' // Output: \"Hello\"\n *\n * editor.moveCursor(1);\n * editor.insert('a');\n * console.log(editor.getText()); // 'Haello'\n */\nexport class SinglyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, SinglyLinkedListNode<E>> {\n constructor(\n elements: Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>> = [],\n options?: SinglyLinkedListOptions<E, R>\n ) {\n super(options);\n\n if (options) {\n }\n\n this.pushMany(elements);\n }\n\n protected _head: SinglyLinkedListNode<E> | undefined;\n\n get head(): SinglyLinkedListNode<E> | undefined {\n return this._head;\n }\n\n protected _tail: SinglyLinkedListNode<E> | undefined;\n\n get tail(): SinglyLinkedListNode<E> | undefined {\n return this._tail;\n }\n\n get first(): E | undefined {\n return this.head?.value;\n }\n\n get last(): E | undefined {\n return this.tail?.value;\n }\n\n protected _length: number = 0;\n\n get length(): number {\n return this._length;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `fromArray` function creates a new SinglyLinkedList instance and populates it with the elements from the given\n * array.\n * @param {E[]} data - The `data` parameter is an array of elements of type `E`.\n * @returns The `fromArray` function returns a `SinglyLinkedList` object.\n */\n static fromArray<E>(data: E[]) {\n const singlyLinkedList = new SinglyLinkedList<E>();\n for (const item of data) {\n singlyLinkedList.push(item);\n }\n return singlyLinkedList;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `push` function adds a new element or node to the end of a singly linked list.\n * @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the `push`\n * method can accept either an element of type `E` or a `SinglyLinkedListNode<E>` object.\n * @returns The `push` method is returning a boolean value, specifically `true`.\n */\n push(elementOrNode: E | SinglyLinkedListNode<E>): boolean {\n const newNode = this._ensureNode(elementOrNode);\n if (!this.head) {\n this._head = newNode;\n this._tail = newNode;\n } else {\n this.tail!.next = newNode;\n this._tail = newNode;\n }\n this._length++;\n if (this._maxLen > 0 && this.length > this._maxLen) this.shift();\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `pop` function removes and returns the value of the last element in a linked list.\n * @returns The method is returning the value of the element that is being popped from the end of the\n * list.\n */\n pop(): E | undefined {\n if (!this.head) return undefined;\n if (this.head === this.tail) {\n const value = this.head.value;\n this._head = undefined;\n this._tail = undefined;\n this._length--;\n return value;\n }\n\n let current = this.head;\n while (current.next !== this.tail) {\n current = current.next!;\n }\n const value = this.tail!.value;\n current.next = undefined;\n this._tail = current;\n this._length--;\n return value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `shift()` function removes and returns the value of the first element in a linked list.\n * @returns The value of the removed node.\n */\n shift(): E | undefined {\n if (!this.head) return undefined;\n const removedNode = this.head;\n this._head = this.head.next;\n this._length--;\n return removedNode.value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The unshift function adds a new element or node to the beginning of a singly linked list in\n * TypeScript.\n * @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the\n * `unshift` method can be either an element of type `E` or a `SinglyLinkedListNode` containing an\n * element of type `E`.\n * @returns The `unshift` method is returning a boolean value, specifically `true`.\n */\n unshift(elementOrNode: E | SinglyLinkedListNode<E>): boolean {\n const newNode = this._ensureNode(elementOrNode);\n if (!this.head) {\n this._head = newNode;\n this._tail = newNode;\n } else {\n newNode.next = this.head;\n this._head = newNode;\n }\n this._length++;\n return true;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The function `pushMany` iterates over elements and pushes them into a data structure, applying a\n * transformation function if provided.\n * @param {Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>>} elements - The `elements`\n * parameter in the `pushMany` function can accept an iterable containing elements of type `E`, `R`,\n * or `SinglyLinkedListNode<E>`.\n * @returns The `pushMany` function returns an array of boolean values indicating whether each\n * element was successfully pushed into the data structure.\n */\n pushMany(elements: Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>>) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) {\n ans.push(this.push(this.toElementFn(el as R)));\n continue;\n }\n ans.push(this.push(el as E | SinglyLinkedListNode<E>));\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The function `unshiftMany` iterates over elements and adds them to a data structure, optionally\n * converting them using a provided function.\n * @param {Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>>} elements - The `elements`\n * parameter in the `unshiftMany` function can accept an iterable containing elements of type `E`,\n * `R`, or `SinglyLinkedListNode<E>`. The function iterates over each element in the iterable and\n * performs an `unshift` operation on the linked list for each\n * @returns The `unshiftMany` function is returning an array of boolean values, where each value\n * represents the result of calling the `unshift` method on the current instance of the class.\n */\n unshiftMany(elements: Iterable<E> | Iterable<R> | Iterable<SinglyLinkedListNode<E>>) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) {\n ans.push(this.unshift(this.toElementFn(el as R)));\n continue;\n }\n ans.push(this.unshift(el as E | SinglyLinkedListNode<E>));\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * This function searches for a specific element in a singly linked list based on a given node or\n * predicate.\n * @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `get` method can be one of\n * the following types:\n * @returns The `get` method returns the value of the first node in the singly linked list that\n * satisfies the provided predicate function. If no such node is found, it returns `undefined`.\n */\n search(\n elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)\n ): E | undefined {\n const predicate = this._ensurePredicate(elementNodeOrPredicate);\n let current = this.head;\n while (current) {\n if (predicate(current)) return current.value;\n current = current.next;\n }\n return undefined;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `at` returns the value at a specified index in a linked list, or undefined if the index is out of range.\n * @param {number} index - The index parameter is a number that represents the position of the element we want to\n * retrieve from the list.\n * @returns The method `at(index: number): E | undefined` returns the value at the specified index in the linked list, or\n * `undefined` if the index is out of bounds.\n */\n at(index: number): E | undefined {\n if (index < 0 || index >= this._length) return undefined;\n let current = this.head;\n for (let i = 0; i < index; i++) {\n current = current!.next;\n }\n return current!.value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `isNode` in TypeScript checks if the input is an instance of `SinglyLinkedListNode`.\n * @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `isNode` function can be\n * one of the following types:\n * @returns The `isNode` function is checking if the `elementNodeOrPredicate` parameter is an\n * instance of `SinglyLinkedListNode<E>`. If it is, the function returns `true`, indicating that the\n * parameter is a `SinglyLinkedListNode<E>`. If it is not an instance of `SinglyLinkedListNode<E>`,\n * the function returns `false`.\n */\n isNode(\n elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)\n ): elementNodeOrPredicate is SinglyLinkedListNode<E> {\n return elementNodeOrPredicate instanceof SinglyLinkedListNode;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `getNodeAt` returns the node at a given index in a singly linked list.\n * @param {number} index - The `index` parameter is a number that represents the position of the node we want to\n * retrieve from the linked list. It indicates the zero-based index of the node we want to access.\n * @returns The method `getNodeAt(index: number)` returns a `SinglyLinkedListNode<E>` object if the node at the\n * specified index exists, or `undefined` if the index is out of bounds.\n */\n getNodeAt(index: number): SinglyLinkedListNode<E> | undefined {\n let current = this.head;\n for (let i = 0; i < index; i++) {\n current = current!.next;\n }\n return current;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `deleteAt` function removes an element at a specified index from a linked list and returns the removed element.\n * @param {number} index - The index parameter represents the position of the element that needs to be deleted in the\n * data structure. It is of type number.\n * @returns The method `deleteAt` returns the value of the node that was deleted, or `undefined` if the index is out of\n * bounds.\n */\n deleteAt(index: number): E | undefined {\n if (index < 0 || index >= this._length) return;\n let deleted: E | undefined;\n if (index === 0) {\n deleted = this.first;\n this.shift();\n return deleted;\n }\n\n const targetNode = this.getNodeAt(index);\n const prevNode = this._getPrevNode(targetNode!);\n\n if (prevNode && targetNode) {\n deleted = targetNode.value;\n prevNode.next = targetNode.next;\n if (targetNode === this.tail) this._tail = prevNode;\n this._length--;\n return deleted;\n }\n\n return;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The delete function removes a node with a specific value from a singly linked list.\n * @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter can accept either a value of type `E`\n * or a `SinglyLinkedListNode<E>` object.\n * @returns The `delete` method returns a boolean value. It returns `true` if the value or node is found and\n * successfully deleted from the linked list, and `false` if the value or node is not found in the linked list.\n */\n delete(elementOrNode: E | SinglyLinkedListNode<E> | undefined): boolean {\n if (elementOrNode === undefined || !this.head) return false;\n\n const node = this.isNode(elementOrNode) ? elementOrNode : this.getNode(elementOrNode);\n\n if (!node) return false;\n\n const prevNode = this._getPrevNode(node);\n\n if (!prevNode) {\n // The node is the head\n this._head = node.next;\n if (node === this.tail) this._tail = undefined;\n } else {\n prevNode.next = node.next;\n if (node === this.tail) this._tail = prevNode;\n }\n\n this._length--;\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `addAt` function inserts a new element or node at a specified index in a singly linked list.\n * @param {number} index - The `index` parameter represents the position at which you want to add a\n * new element or node in the linked list. It is a number that indicates the index where the new\n * element or node should be inserted.\n * @param {E | SinglyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the\n * `addAt` method can be either a value of type `E` or a `SinglyLinkedListNode<E>` object. This\n * parameter represents the element or node that you want to add to the linked list at the specified\n * index.\n * @returns The `addAt` method returns a boolean value - `true` if the element or node was\n * successfully added at the specified index, and `false` if the index is out of bounds.\n */\n addAt(index: number, newElementOrNode: E | SinglyLinkedListNode<E>): boolean {\n if (index < 0 || index > this._length) return false;\n\n if (index === 0) {\n this.unshift(newElementOrNode);\n return true;\n }\n if (index === this._length) {\n this.push(newElementOrNode);\n return true;\n }\n\n const newNode = this._ensureNode(newElementOrNode);\n const prevNode = this.getNodeAt(index - 1);\n newNode.next = prevNode!.next;\n prevNode!.next = newNode;\n this._length++;\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function setAt(index, value) updates the value at a specified index in a data structure if the\n * index exists.\n * @param {number} index - The `index` parameter in the `setAt` method refers to the position in the\n * data structure where you want to set a new value.\n * @param {E} value - The `value` parameter in the `setAt` method represents the new value that you\n * want to set at the specified index in the data structure.\n * @returns The `setAt` method returns a boolean value - `true` if the value at the specified index\n * is successfully updated, and `false` if the index is out of bounds (i.e., the node at that index\n * does not exist).\n */\n setAt(index: number, value: E): boolean {\n const node = this.getNodeAt(index);\n if (node) {\n node.value = value;\n return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if the length of a data structure is equal to zero and returns a boolean value indicating\n * whether it is empty or not.\n * @returns A boolean value indicating whether the length of the object is equal to 0.\n */\n isEmpty(): boolean {\n return this._length === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `clear` function resets the linked list by setting the head, tail, and length to undefined and 0 respectively.\n */\n clear(): void {\n this._head = undefined;\n this._tail = undefined;\n this._length = 0;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `reverse` function reverses the order of the nodes in a singly linked list.\n * @returns The reverse() method does not return anything. It has a return type of void.\n */\n reverse(): this {\n if (!this.head || this.head === this.tail) return this;\n\n let prev: SinglyLinkedListNode<E> | undefined = undefined;\n let current: SinglyLinkedListNode<E> | undefined = this.head;\n let next: SinglyLinkedListNode<E> | undefined = undefined;\n\n while (current) {\n next = current.next;\n current.next = prev;\n prev = current;\n current = next;\n }\n\n [this._head, this._tail] = [this.tail!, this.head!];\n return this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `getNode` in TypeScript searches for a node in a singly linked list based on a given\n * element, node, or predicate.\n * @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean) | undefined} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `getNode` method can be one\n * of the following types:\n * @returns The `getNode` method returns either a `SinglyLinkedListNode<E>` if a matching node is\n * found based on the provided predicate, or it returns `undefined` if no matching node is found or\n * if the input parameter is `undefined`.\n */\n getNode(\n elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean) | undefined\n ): SinglyLinkedListNode<E> | undefined {\n if (elementNodeOrPredicate === undefined) return;\n if (this.isNode(elementNodeOrPredicate)) return elementNodeOrPredicate;\n const predicate = this._ensurePredicate(elementNodeOrPredicate);\n let current = this.head;\n\n while (current) {\n if (predicate(current)) {\n return current;\n }\n current = current.next;\n }\n\n return undefined;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `addBefore` in TypeScript adds a new element or node before an existing element or\n * node in a singly linked list.\n * @param {E | SinglyLinkedListNode<E>} existingElementOrNode - existingElementOrNode represents the\n * element or node in the linked list before which you want to add a new element or node.\n * @param {E | SinglyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the\n * `addBefore` method represents the element or node that you want to insert before the existing\n * element or node in the linked list. This new element can be of type `E` or a\n * `SinglyLinkedListNode<E>`.\n * @returns The `addBefore` method returns a boolean value - `true` if the new element or node was\n * successfully added before the existing element or node, and `false` if the operation was\n * unsuccessful.\n */\n addBefore(\n existingElementOrNode: E | SinglyLinkedListNode<E>,\n newElementOrNode: E | SinglyLinkedListNode<E>\n ): boolean {\n const existingNode = this.getNode(existingElementOrNode);\n if (!existingNode) return false;\n\n const prevNode = this._getPrevNode(existingNode);\n const newNode = this._ensureNode(newElementOrNode);\n\n if (!prevNode) {\n // Add at the head\n this.unshift(newNode);\n } else {\n prevNode.next = newNode;\n newNode.next = existingNode;\n this._length++;\n }\n\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `addAfter` function in TypeScript adds a new element or node after an existing element or node\n * in a singly linked list.\n * @param {E | SinglyLinkedListNode<E>} existingElementOrNode - existingElementOrNode can be either\n * an element of type E or a SinglyLinkedListNode of type E.\n * @param {E | SinglyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the\n * `addAfter` method represents the element or node that you want to add after the existing element\n * or node in a singly linked list. This parameter can be either the value of the new element or a\n * reference to a `SinglyLinkedListNode` containing\n * @returns The `addAfter` method returns a boolean value - `true` if the new element or node was\n * successfully added after the existing element or node, and `false` if the existing element or node\n * was not found.\n */\n addAfter(existingElementOrNode: E | SinglyLinkedListNode<E>, newElementOrNode: E | SinglyLinkedListNode<E>): boolean {\n const existingNode: SinglyLinkedListNode<E> | undefined = this.getNode(existingElementOrNode);\n\n if (existingNode) {\n const newNode = this._ensureNode(newElementOrNode);\n newNode.next = existingNode.next;\n existingNode.next = newNode;\n if (existingNode === this.tail) {\n this._tail = newNode;\n }\n this._length++;\n return true;\n }\n\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `splice` in TypeScript overrides the default behavior to remove and insert elements\n * in a singly linked list while handling boundary cases.\n * @param {number} start - The `start` parameter in the `splice` method indicates the index at which\n * to start modifying the list. It specifies the position where elements will be added or removed.\n * @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the\n * number of elements to remove from the array starting at the specified `start` index. If\n * `deleteCount` is not provided, it defaults to 0, meaning no elements will be removed but new\n * elements can still be inserted at\n * @param {E[]} items - The `items` parameter in the `splice` method represents the elements to be\n * inserted into the list at the specified `start` index. These elements will be inserted in place of\n * the elements that are removed from the list. The `splice` method allows you to add new elements to\n * the list while\n * @returns The `splice` method is returning a `SinglyLinkedList` containing the elements that were\n * removed from the original list during the splice operation.\n */\n override splice(start: number, deleteCount: number = 0, ...items: E[]): this {\n const removedList = this._createInstance({ toElementFn: this._toElementFn, maxLen: this._maxLen });\n\n // If `start` is out of range, perform boundary processing\n start = Math.max(0, Math.min(start, this.length));\n deleteCount = Math.max(0, deleteCount);\n\n // Find the predecessor node of `start`\n const prevNode = start === 0 ? undefined : this.getNodeAt(start - 1);\n const startNode = prevNode ? prevNode.next : this.head;\n\n let current = startNode;\n for (let i = 0; i < deleteCount && current; i++) {\n removedList.push(current.value);\n current = current.next;\n }\n\n const nextNode = current;\n let lastInsertedNode: SinglyLinkedListNode<E> | undefined = undefined;\n\n for (const item of items) {\n const newNode = this._ensureNode(item);\n if (!lastInsertedNode) {\n if (prevNode) {\n prevNode.next = newNode;\n } else {\n this._head = newNode;\n }\n } else {\n lastInsertedNode.next = newNode;\n }\n lastInsertedNode = newNode;\n }\n\n // Connect new node to `nextNode`\n if (lastInsertedNode) {\n lastInsertedNode.next = nextNode;\n } else if (prevNode) {\n prevNode.next = nextNode;\n }\n\n // Update tail node and length\n if (!nextNode) {\n this._tail = lastInsertedNode || prevNode;\n }\n this._length += items.length - removedList.length;\n\n return removedList as this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `countOccurrences` iterates through a singly linked list and counts the occurrences\n * of a specified element or nodes that satisfy a given predicate.\n * @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementOrNode\n * - The `elementOrNode` parameter in the `countOccurrences` method can accept three types of values:\n * @returns The `countOccurrences` method returns the number of occurrences of the specified element,\n * node, or predicate function in the singly linked list.\n */\n countOccurrences(elementOrNode: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)): number {\n const predicate = this._ensurePredicate(elementOrNode);\n let count = 0;\n let current = this.head;\n\n while (current) {\n if (predicate(current)) {\n count++;\n }\n current = current.next;\n }\n\n return count;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `clone` function returns a new instance of the `SinglyLinkedList` class with the same values\n * as the original list.\n * @returns The `clone()` method is returning a new instance of the `SinglyLinkedList` class, which\n * is a clone of the original list.\n */\n clone(): this {\n return new SinglyLinkedList<E, R>(this, { toElementFn: this.toElementFn, maxLen: this._maxLen }) as this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new SinglyLinkedList by iterating over the elements of the current\n * list and applying a callback function to each element to determine if it should be included in the\n * filtered list.\n * @param callback - The callback parameter is a function that will be called for each element in the\n * list. It takes three arguments: the current element, the index of the current element, and the\n * list itself. The callback function should return a boolean value indicating whether the current\n * element should be included in the filtered list or not\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `SinglyLinkedList` object that contains the\n * elements that pass the filter condition specified by the `callback` function.\n */\n filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): SinglyLinkedList<E, R> {\n const filteredList = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredList.push(current);\n }\n index++;\n }\n return filteredList;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function takes a callback function and returns a new SinglyLinkedList with the results\n * of applying the callback to each element in the original list.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the original list. It takes three arguments: `current` (the current element being processed),\n * `index` (the index of the current element), and `this` (the original list). It should return a\n * value\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to\n * convert the raw element (`RR`) to the desired element type (`T`). It takes the raw element as\n * input and returns the converted element. If this parameter is not provided, the raw element will\n * be used as is.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `SinglyLinkedList` class with the mapped elements.\n */\n map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): SinglyLinkedList<EM, RM> {\n const mappedList = new SinglyLinkedList<EM, RM>([], { toElementFn, maxLen: this._maxLen });\n let index = 0;\n for (const current of this) {\n mappedList.push(callback.call(thisArg, current, index, this));\n index++;\n }\n\n return mappedList;\n }\n\n /**\n * The function `_createInstance` returns a new instance of `SinglyLinkedList` with the specified\n * options.\n * @param [options] - The `options` parameter in the `_createInstance` method is of type\n * `SinglyLinkedListOptions<E, R>`, which is used to configure the behavior of the `SinglyLinkedList`\n * instance being created. It is an optional parameter, meaning it can be omitted when calling the\n * method.\n * @returns An instance of the `SinglyLinkedList` class with an empty array and the provided options\n * is being returned.\n */\n protected override _createInstance(options?: SinglyLinkedListOptions<E, R>): this {\n return new SinglyLinkedList<E, R>([], options) as this;\n }\n\n /**\n * The function `_getIterator` returns an iterable iterator that yields the values of a linked list.\n */\n protected *_getIterator(): IterableIterator<E> {\n let current = this.head;\n\n while (current) {\n yield current.value;\n current = current.next;\n }\n }\n\n /**\n * The function returns an iterator that iterates over the elements of a collection in reverse order.\n */\n protected *_getReverseIterator(): IterableIterator<E> {\n const reversedArr = [...this].reverse();\n\n for (const item of reversedArr) {\n yield item;\n }\n }\n\n /**\n * The function `_getNodeIterator` returns an iterator that iterates over the nodes of a singly\n * linked list.\n */\n protected *_getNodeIterator(): IterableIterator<SinglyLinkedListNode<E>> {\n let current = this.head;\n\n while (current) {\n yield current;\n current = current.next;\n }\n }\n\n // protected *_getReverseNodeIterator(): IterableIterator<SinglyLinkedListNode<E>> {\n // const reversedArr = [...this._getNodeIterator()].reverse();\n //\n // for (const item of reversedArr) {\n // yield item;\n // }\n // }\n\n /**\n * The _isPredicate function in TypeScript checks if the input is a function that takes a\n * SinglyLinkedListNode as an argument and returns a boolean.\n * @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following types:\n * @returns The _isPredicate method is returning a boolean value based on whether the\n * elementNodeOrPredicate parameter is a function or not. If the elementNodeOrPredicate is a\n * function, the method will return true, indicating that it is a predicate function. If it is not a\n * function, the method will return false.\n */\n protected _isPredicate(\n elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)\n ): elementNodeOrPredicate is (node: SinglyLinkedListNode<E>) => boolean {\n return typeof elementNodeOrPredicate === 'function';\n }\n\n /**\n * The function `_ensureNode` ensures that the input is a valid node and returns it, creating a new\n * node if necessary.\n * @param {E | SinglyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter can be either\n * an element of type `E` or a `SinglyLinkedListNode` containing an element of type `E`.\n * @returns A SinglyLinkedListNode<E> object is being returned.\n */\n protected _ensureNode(elementOrNode: E | SinglyLinkedListNode<E>) {\n if (this.isNode(elementOrNode)) return elementOrNode;\n\n return new SinglyLinkedListNode<E>(elementOrNode);\n }\n\n /**\n * The function `_ensurePredicate` in TypeScript ensures that the input is either a node, a predicate\n * function, or a value to compare with the node's value.\n * @param {E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following types:\n * @returns A function is being returned. If the input `elementNodeOrPredicate` is already a node, a\n * function is returned that checks if a given node is equal to the input node. If the input is a\n * predicate function, it is returned as is. If the input is neither a node nor a predicate function,\n * a function is returned that checks if a given node's value is equal to the input\n */\n protected _ensurePredicate(\n elementNodeOrPredicate: E | SinglyLinkedListNode<E> | ((node: SinglyLinkedListNode<E>) => boolean)\n ) {\n if (this.isNode(elementNodeOrPredicate)) return (node: SinglyLinkedListNode<E>) => node === elementNodeOrPredicate;\n\n if (this._isPredicate(elementNodeOrPredicate)) return elementNodeOrPredicate;\n\n return (node: SinglyLinkedListNode<E>) => node.value === elementNodeOrPredicate;\n }\n\n /**\n * The function `_getPrevNode` returns the node before a given node in a singly linked list.\n * @param node - The `node` parameter in the `_getPrevNode` method is a reference to a node in a\n * singly linked list. The method is used to find the node that comes before the given node in the\n * linked list.\n * @returns The `_getPrevNode` method returns either the previous node of the input node in a singly\n * linked list or `undefined` if the input node is the head of the list or if the input node is not\n * found in the list.\n */\n protected _getPrevNode(node: SinglyLinkedListNode<E>): SinglyLinkedListNode<E> | undefined {\n if (!this.head || this.head === node) return undefined;\n\n let current = this.head;\n while (current.next && current.next !== node) {\n current = current.next;\n }\n\n return current.next === node ? current : undefined;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { DoublyLinkedListOptions, ElementCallback } from '../../types';\nimport { LinearLinkedBase, LinkedListNode } from '../base/linear-base';\n\nexport class DoublyLinkedListNode<E = any> extends LinkedListNode<E> {\n /**\n * The constructor function initializes the value, next, and previous properties of an object.\n * @param {E} value - The \"value\" parameter is the value that will be stored in the node. It can be of any data type, as it\n * is defined as a generic type \"E\".\n */\n constructor(value: E) {\n super(value);\n this._value = value;\n this._next = undefined;\n this._prev = undefined;\n }\n\n protected override _next: DoublyLinkedListNode<E> | undefined;\n\n override get next(): DoublyLinkedListNode<E> | undefined {\n return this._next;\n }\n\n override set next(value: DoublyLinkedListNode<E> | undefined) {\n this._next = value;\n }\n\n protected _prev: DoublyLinkedListNode<E> | undefined;\n\n get prev(): DoublyLinkedListNode<E> | undefined {\n return this._prev;\n }\n\n set prev(value: DoublyLinkedListNode<E> | undefined) {\n this._prev = value;\n }\n}\n\n/**\n * 1. Node Structure: Each node contains three parts: a data field, a pointer (or reference) to the previous node, and a pointer to the next node. This structure allows traversal of the linked list in both directions.\n * 2. Bidirectional Traversal: Unlike singly linked lists, doubly linked lists can be easily traversed forwards or backwards. This makes insertions and deletions in the list more flexible and efficient.\n * 3. No Centralized Index: Unlike arrays, elements in a linked list are not stored contiguously, so there is no centralized index. Accessing elements in a linked list typically requires traversing from the head or tail node.\n * 4. High Efficiency in Insertion and Deletion: Adding or removing elements in a linked list does not require moving other elements, making these operations more efficient than in arrays.\n * Caution: Although our linked list classes provide methods such as at, setAt, addAt, and indexOf that are based on array indices, their time complexity, like that of the native Array.lastIndexOf, is 𝑂(𝑛). If you need to use these methods frequently, you might want to consider other data structures, such as Deque or Queue (designed for random access). Similarly, since the native Array.shift method has a time complexity of 𝑂(𝑛), using an array to simulate a queue can be inefficient. In such cases, you should use Queue or Deque, as these data structures leverage deferred array rearrangement, effectively reducing the average time complexity to 𝑂(1).\n * @example\n * // text editor operation history\n * const actions = [\n * { type: 'insert', content: 'first line of text' },\n * { type: 'insert', content: 'second line of text' },\n * { type: 'delete', content: 'delete the first line' }\n * ];\n * const editorHistory = new DoublyLinkedList<{ type: string; content: string }>(actions);\n *\n * console.log(editorHistory.last?.type); // 'delete'\n * console.log(editorHistory.pop()?.content); // 'delete the first line'\n * console.log(editorHistory.last?.type); // 'insert'\n * @example\n * // Browser history\n * const browserHistory = new DoublyLinkedList<string>();\n *\n * browserHistory.push('home page');\n * browserHistory.push('search page');\n * browserHistory.push('details page');\n *\n * console.log(browserHistory.last); // 'details page'\n * console.log(browserHistory.pop()); // 'details page'\n * console.log(browserHistory.last); // 'search page'\n * @example\n * // Use DoublyLinkedList to implement music player\n * // Define the Song interface\n * interface Song {\n * title: string;\n * artist: string;\n * duration: number; // duration in seconds\n * }\n *\n * class Player {\n * private playlist: DoublyLinkedList<Song>;\n * private currentSong: ReturnType<typeof this.playlist.getNodeAt> | undefined;\n *\n * constructor(songs: Song[]) {\n * this.playlist = new DoublyLinkedList<Song>();\n * songs.forEach(song => this.playlist.push(song));\n * this.currentSong = this.playlist.head;\n * }\n *\n * // Play the next song in the playlist\n * playNext(): Song | undefined {\n * if (!this.currentSong?.next) {\n * this.currentSong = this.playlist.head; // Loop to the first song\n * } else {\n * this.currentSong = this.currentSong.next;\n * }\n * return this.currentSong?.value;\n * }\n *\n * // Play the previous song in the playlist\n * playPrevious(): Song | undefined {\n * if (!this.currentSong?.prev) {\n * this.currentSong = this.playlist.tail; // Loop to the last song\n * } else {\n * this.currentSong = this.currentSong.prev;\n * }\n * return this.currentSong?.value;\n * }\n *\n * // Get the current song\n * getCurrentSong(): Song | undefined {\n * return this.currentSong?.value;\n * }\n *\n * // Loop through the playlist twice\n * loopThroughPlaylist(): Song[] {\n * const playedSongs: Song[] = [];\n * const initialNode = this.currentSong;\n *\n * // Loop through the playlist twice\n * for (let i = 0; i < this.playlist.length * 2; i++) {\n * playedSongs.push(this.currentSong!.value);\n * this.currentSong = this.currentSong!.next || this.playlist.head; // Loop back to the start if needed\n * }\n *\n * // Reset the current song to the initial song\n * this.currentSong = initialNode;\n * return playedSongs;\n * }\n * }\n *\n * const songs = [\n * { title: 'Bohemian Rhapsody', artist: 'Queen', duration: 354 },\n * { title: 'Hotel California', artist: 'Eagles', duration: 391 },\n * { title: 'Shape of You', artist: 'Ed Sheeran', duration: 233 },\n * { title: 'Billie Jean', artist: 'Michael Jackson', duration: 294 }\n * ];\n * let player = new Player(songs);\n * // should play the next song\n * player = new Player(songs);\n * const firstSong = player.getCurrentSong();\n * const nextSong = player.playNext();\n *\n * // Expect the next song to be \"Hotel California by Eagles\"\n * console.log(nextSong); // { title: 'Hotel California', artist: 'Eagles', duration: 391 }\n * console.log(firstSong); // { title: 'Bohemian Rhapsody', artist: 'Queen', duration: 354 }\n *\n * // should play the previous song\n * player = new Player(songs);\n * player.playNext(); // Move to the second song\n * const currentSong = player.getCurrentSong();\n * const previousSong = player.playPrevious();\n *\n * // Expect the previous song to be \"Bohemian Rhapsody by Queen\"\n * console.log(previousSong); // { title: 'Bohemian Rhapsody', artist: 'Queen', duration: 354 }\n * console.log(currentSong); // { title: 'Hotel California', artist: 'Eagles', duration: 391 }\n *\n * // should loop to the first song when playing next from the last song\n * player = new Player(songs);\n * player.playNext(); // Move to the second song\n * player.playNext(); // Move to the third song\n * player.playNext(); // Move to the fourth song\n *\n * const nextSongToFirst = player.playNext(); // Should loop to the first song\n *\n * // Expect the next song to be \"Bohemian Rhapsody by Queen\"\n * console.log(nextSongToFirst); // { title: 'Bohemian Rhapsody', artist: 'Queen', duration: 354 }\n *\n * // should loop to the last song when playing previous from the first song\n * player = new Player(songs);\n * player.playNext(); // Move to the first song\n * player.playNext(); // Move to the second song\n * player.playNext(); // Move to the third song\n * player.playNext(); // Move to the fourth song\n *\n * const previousToLast = player.playPrevious(); // Should loop to the last song\n *\n * // Expect the previous song to be \"Billie Jean by Michael Jackson\"\n * console.log(previousToLast); // { title: 'Billie Jean', artist: 'Michael Jackson', duration: 294 }\n *\n * // should loop through the entire playlist\n * player = new Player(songs);\n * const playedSongs = player.loopThroughPlaylist();\n *\n * // The expected order of songs for two loops\n * console.log(playedSongs); // [\n * // { title: 'Bohemian Rhapsody', artist: 'Queen', duration: 354 },\n * // { title: 'Hotel California', artist: 'Eagles', duration: 391 },\n * // { title: 'Shape of You', artist: 'Ed Sheeran', duration: 233 },\n * // { title: 'Billie Jean', artist: 'Michael Jackson', duration: 294 },\n * // { title: 'Bohemian Rhapsody', artist: 'Queen', duration: 354 },\n * // { title: 'Hotel California', artist: 'Eagles', duration: 391 },\n * // { title: 'Shape of You', artist: 'Ed Sheeran', duration: 233 },\n * // { title: 'Billie Jean', artist: 'Michael Jackson', duration: 294 }\n * // ]\n * @example\n * // Use DoublyLinkedList to implement LRU cache\n * interface CacheEntry<K, V> {\n * key: K;\n * value: V;\n * }\n *\n * class LRUCache<K = string, V = any> {\n * private readonly capacity: number;\n * private list: DoublyLinkedList<CacheEntry<K, V>>;\n * private map: Map<K, DoublyLinkedListNode<CacheEntry<K, V>>>;\n *\n * constructor(capacity: number) {\n * if (capacity <= 0) {\n * throw new Error('lru cache capacity must be greater than 0');\n * }\n * this.capacity = capacity;\n * this.list = new DoublyLinkedList<CacheEntry<K, V>>();\n * this.map = new Map<K, DoublyLinkedListNode<CacheEntry<K, V>>>();\n * }\n *\n * // Get cached value\n * get(key: K): V | undefined {\n * const node = this.map.get(key);\n *\n * if (!node) return undefined;\n *\n * // Move the visited node to the head of the linked list (most recently used)\n * this.moveToFront(node);\n *\n * return node.value.value;\n * }\n *\n * // Set cache value\n * set(key: K, value: V): void {\n * // Check if it already exists\n * const node = this.map.get(key);\n *\n * if (node) {\n * // Update value and move to head\n * node.value.value = value;\n * this.moveToFront(node);\n * return;\n * }\n *\n * // Check capacity\n * if (this.list.length >= this.capacity) {\n * // Delete the least recently used element (the tail of the linked list)\n * const removedNode = this.list.tail;\n * if (removedNode) {\n * this.map.delete(removedNode.value.key);\n * this.list.pop();\n * }\n * }\n *\n * // Create new node and add to head\n * const newEntry: CacheEntry<K, V> = { key, value };\n * this.list.unshift(newEntry);\n *\n * // Save node reference in map\n * const newNode = this.list.head;\n * if (newNode) {\n * this.map.set(key, newNode);\n * }\n * }\n *\n * // Move the node to the head of the linked list\n * private moveToFront(node: DoublyLinkedListNode<CacheEntry<K, V>>): void {\n * this.list.delete(node);\n * this.list.unshift(node.value);\n * }\n *\n * // Delete specific key\n * delete(key: K): boolean {\n * const node = this.map.get(key);\n * if (!node) return false;\n *\n * // Remove from linked list\n * this.list.delete(node);\n * // Remove from map\n * this.map.delete(key);\n *\n * return true;\n * }\n *\n * // Clear cache\n * clear(): void {\n * this.list.clear();\n * this.map.clear();\n * }\n *\n * // Get the current cache length\n * get length(): number {\n * return this.list.length;\n * }\n *\n * // Check if it is empty\n * get isEmpty(): boolean {\n * return this.list.isEmpty();\n * }\n * }\n *\n * // should set and get values correctly\n * const cache = new LRUCache<string, number>(3);\n * cache.set('a', 1);\n * cache.set('b', 2);\n * cache.set('c', 3);\n *\n * console.log(cache.get('a')); // 1\n * console.log(cache.get('b')); // 2\n * console.log(cache.get('c')); // 3\n *\n * // The least recently used element should be evicted when capacity is exceeded\n * cache.clear();\n * cache.set('a', 1);\n * cache.set('b', 2);\n * cache.set('c', 3);\n * cache.set('d', 4); // This will eliminate 'a'\n *\n * console.log(cache.get('a')); // undefined\n * console.log(cache.get('b')); // 2\n * console.log(cache.get('c')); // 3\n * console.log(cache.get('d')); // 4\n *\n * // The priority of an element should be updated when it is accessed\n * cache.clear();\n * cache.set('a', 1);\n * cache.set('b', 2);\n * cache.set('c', 3);\n *\n * cache.get('a'); // access 'a'\n * cache.set('d', 4); // This will eliminate 'b'\n *\n * console.log(cache.get('a')); // 1\n * console.log(cache.get('b')); // undefined\n * console.log(cache.get('c')); // 3\n * console.log(cache.get('d')); // 4\n *\n * // Should support updating existing keys\n * cache.clear();\n * cache.set('a', 1);\n * cache.set('a', 10);\n *\n * console.log(cache.get('a')); // 10\n *\n * // Should support deleting specified keys\n * cache.clear();\n * cache.set('a', 1);\n * cache.set('b', 2);\n *\n * console.log(cache.delete('a')); // true\n * console.log(cache.get('a')); // undefined\n * console.log(cache.length); // 1\n *\n * // Should support clearing cache\n * cache.clear();\n * cache.set('a', 1);\n * cache.set('b', 2);\n * cache.clear();\n *\n * console.log(cache.length); // 0\n * console.log(cache.isEmpty); // true\n * @example\n * // finding lyrics by timestamp in Coldplay's \"Fix You\"\n * // Create a DoublyLinkedList to store song lyrics with timestamps\n * const lyricsList = new DoublyLinkedList<{ time: number; text: string }>();\n *\n * // Detailed lyrics with precise timestamps (in milliseconds)\n * const lyrics = [\n * { time: 0, text: \"When you try your best, but you don't succeed\" },\n * { time: 4000, text: 'When you get what you want, but not what you need' },\n * { time: 8000, text: \"When you feel so tired, but you can't sleep\" },\n * { time: 12000, text: 'Stuck in reverse' },\n * { time: 16000, text: 'And the tears come streaming down your face' },\n * { time: 20000, text: \"When you lose something you can't replace\" },\n * { time: 24000, text: 'When you love someone, but it goes to waste' },\n * { time: 28000, text: 'Could it be worse?' },\n * { time: 32000, text: 'Lights will guide you home' },\n * { time: 36000, text: 'And ignite your bones' },\n * { time: 40000, text: 'And I will try to fix you' }\n * ];\n *\n * // Populate the DoublyLinkedList with lyrics\n * lyrics.forEach(lyric => lyricsList.push(lyric));\n *\n * // Test different scenarios of lyric synchronization\n *\n * // 1. Find lyric at exact timestamp\n * const exactTimeLyric = lyricsList.getBackward(lyric => lyric.value.time <= 36000);\n * console.log(exactTimeLyric?.text); // 'And ignite your bones'\n *\n * // 2. Find lyric between timestamps\n * const betweenTimeLyric = lyricsList.getBackward(lyric => lyric.value.time <= 22000);\n * console.log(betweenTimeLyric?.text); // \"When you lose something you can't replace\"\n *\n * // 3. Find first lyric when timestamp is less than first entry\n * const earlyTimeLyric = lyricsList.getBackward(lyric => lyric.value.time <= -1000);\n * console.log(earlyTimeLyric); // undefined\n *\n * // 4. Find last lyric when timestamp is after last entry\n * const lateTimeLyric = lyricsList.getBackward(lyric => lyric.value.time <= 50000);\n * console.log(lateTimeLyric?.text); // 'And I will try to fix you'\n * @example\n * // cpu process schedules\n * class Process {\n * constructor(\n * public id: number,\n * public priority: number\n * ) {}\n *\n * execute(): string {\n * return `Process ${this.id} executed.`;\n * }\n * }\n *\n * class Scheduler {\n * private queue: DoublyLinkedList<Process>;\n *\n * constructor() {\n * this.queue = new DoublyLinkedList<Process>();\n * }\n *\n * addProcess(process: Process): void {\n * // Insert processes into a queue based on priority, keeping priority in descending order\n * let current = this.queue.head;\n * while (current && current.value.priority >= process.priority) {\n * current = current.next;\n * }\n *\n * if (!current) {\n * this.queue.push(process);\n * } else {\n * this.queue.addBefore(current, process);\n * }\n * }\n *\n * executeNext(): string | undefined {\n * // Execute tasks at the head of the queue in order\n * const process = this.queue.shift();\n * return process ? process.execute() : undefined;\n * }\n *\n * listProcesses(): string[] {\n * return this.queue.toArray().map(process => `Process ${process.id} (Priority: ${process.priority})`);\n * }\n *\n * clear(): void {\n * this.queue.clear();\n * }\n * }\n *\n * // should add processes based on priority\n * let scheduler = new Scheduler();\n * scheduler.addProcess(new Process(1, 10));\n * scheduler.addProcess(new Process(2, 20));\n * scheduler.addProcess(new Process(3, 15));\n *\n * console.log(scheduler.listProcesses()); // [\n * // 'Process 2 (Priority: 20)',\n * // 'Process 3 (Priority: 15)',\n * // 'Process 1 (Priority: 10)'\n * // ]\n *\n * // should execute the highest priority process\n * scheduler = new Scheduler();\n * scheduler.addProcess(new Process(1, 10));\n * scheduler.addProcess(new Process(2, 20));\n *\n * console.log(scheduler.executeNext()); // 'Process 2 executed.'\n * console.log(scheduler.listProcesses()); // ['Process 1 (Priority: 10)']\n *\n * // should clear all processes\n * scheduler = new Scheduler();\n * scheduler.addProcess(new Process(1, 10));\n * scheduler.addProcess(new Process(2, 20));\n *\n * scheduler.clear();\n * console.log(scheduler.listProcesses()); // []\n */\nexport class DoublyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, DoublyLinkedListNode<E>> {\n /**\n * This TypeScript constructor initializes a DoublyLinkedList with optional elements and options.\n * @param {Iterable<E> | Iterable<R>} elements - The `elements` parameter in the constructor is an\n * iterable collection of elements of type `E` or `R`. It is used to initialize the DoublyLinkedList\n * with the elements provided in the iterable. If no elements are provided, the default value is an\n * empty iterable.\n * @param [options] - The `options` parameter in the constructor is of type\n * `DoublyLinkedListOptions<E, R>`. It is an optional parameter that allows you to pass additional\n * configuration options to customize the behavior of the DoublyLinkedList.\n */\n constructor(\n elements: Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>> = [],\n options?: DoublyLinkedListOptions<E, R>\n ) {\n super(options);\n this._head = undefined;\n this._tail = undefined;\n this._length = 0;\n\n if (options) {\n const { maxLen } = options;\n if (typeof maxLen === 'number' && maxLen > 0 && maxLen % 1 === 0) this._maxLen = maxLen;\n }\n\n this.pushMany(elements);\n }\n\n protected _head: DoublyLinkedListNode<E> | undefined;\n\n get head(): DoublyLinkedListNode<E> | undefined {\n return this._head;\n }\n\n protected _tail: DoublyLinkedListNode<E> | undefined;\n\n get tail(): DoublyLinkedListNode<E> | undefined {\n return this._tail;\n }\n\n protected _length: number;\n\n get length(): number {\n return this._length;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `get first` function returns the first node in a doubly linked list, or undefined if the list is empty.\n * @returns The method `get first()` returns the first node of the doubly linked list, or `undefined` if the list is empty.\n */\n get first(): E | undefined {\n return this.head?.value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `get last` function returns the last node in a doubly linked list, or undefined if the list is empty.\n * @returns The method `get last()` returns the last node of the doubly linked list, or `undefined` if the list is empty.\n */\n get last(): E | undefined {\n return this.tail?.value;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `fromArray` function creates a new instance of a DoublyLinkedList and populates it with the elements from the\n * given array.\n * @param {E[]} data - The `data` parameter is an array of elements of type `E`.\n * @returns The `fromArray` function returns a DoublyLinkedList object.\n */\n static fromArray<E>(data: E[]) {\n return new DoublyLinkedList<E>(data);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `isNode` in TypeScript checks if a given input is an instance of\n * `DoublyLinkedListNode`.\n * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `isNode` function can\n * be one of the following types:\n * @returns The `isNode` function is checking if the `elementNodeOrPredicate` parameter is an\n * instance of `DoublyLinkedListNode<E>`. If it is, the function returns `true`, indicating that the\n * parameter is a `DoublyLinkedListNode<E>`. If it is not an instance of `DoublyLinkedListNode<E>`,\n * the function returns `false`.\n */\n isNode(\n elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)\n ): elementNodeOrPredicate is DoublyLinkedListNode<E> {\n return elementNodeOrPredicate instanceof DoublyLinkedListNode;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `push` function adds a new element or node to the end of a doubly linked list.\n * @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the `push`\n * method can accept either an element of type `E` or a `DoublyLinkedListNode<E>` object.\n * @returns The `push` method is returning a boolean value, specifically `true`.\n */\n push(elementOrNode: E | DoublyLinkedListNode<E>): boolean {\n const newNode = this._ensureNode(elementOrNode);\n if (!this.head) {\n this._head = newNode;\n this._tail = newNode;\n } else {\n newNode.prev = this.tail;\n this.tail!.next = newNode;\n this._tail = newNode;\n }\n this._length++;\n if (this._maxLen > 0 && this.length > this._maxLen) this.shift();\n return true;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `pop()` function removes and returns the value of the last element in a linked list.\n * @returns The method is returning the value of the removed node.\n */\n pop(): E | undefined {\n if (!this.tail) return undefined;\n const removedNode = this.tail;\n if (this.head === this.tail) {\n this._head = undefined;\n this._tail = undefined;\n } else {\n this._tail = removedNode.prev;\n this.tail!.next = undefined;\n }\n this._length--;\n return removedNode.value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `shift()` function removes and returns the value of the first element in a doubly linked list.\n * @returns The value of the removed node.\n */\n shift(): E | undefined {\n if (!this.head) return undefined;\n const removedNode = this.head;\n if (this.head === this.tail) {\n this._head = undefined;\n this._tail = undefined;\n } else {\n this._head = removedNode.next;\n this.head!.prev = undefined;\n }\n this._length--;\n return removedNode.value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The unshift function adds a new element or node to the beginning of a doubly linked list.\n * @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter in the\n * `unshift` method can be either an element of type `E` or a `DoublyLinkedListNode` containing an\n * element of type `E`.\n * @returns The `unshift` method is returning a boolean value, specifically `true`.\n */\n unshift(elementOrNode: E | DoublyLinkedListNode<E>): boolean {\n const newNode = this._ensureNode(elementOrNode);\n if (!this.head) {\n this._head = newNode;\n this._tail = newNode;\n } else {\n newNode.next = this.head;\n this.head!.prev = newNode;\n this._head = newNode;\n }\n this._length++;\n if (this._maxLen > 0 && this._length > this._maxLen) this.pop();\n return true;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The function `pushMany` iterates over elements and pushes them into a data structure, applying a\n * transformation function if provided.\n * @param {Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>} elements - The `elements`\n * parameter in the `pushMany` function can accept an iterable containing elements of type `E`, `R`,\n * or `DoublyLinkedListNode<E>`. The function iterates over each element in the iterable and pushes\n * it onto the linked list. If a transformation function `to\n * @returns The `pushMany` function is returning an array of boolean values (`ans`) which indicate\n * the success or failure of pushing each element into the data structure.\n */\n pushMany(elements: Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) {\n ans.push(this.push(this.toElementFn(el as R)));\n continue;\n }\n ans.push(this.push(el as E | DoublyLinkedListNode<E>));\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The function `unshiftMany` iterates through a collection of elements and adds them to the\n * beginning of a Doubly Linked List, returning an array of boolean values indicating the success of\n * each insertion.\n * @param {Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>} elements - The `elements`\n * parameter in the `unshiftMany` function can accept an iterable containing elements of type `E`,\n * `R`, or `DoublyLinkedListNode<E>`. The function iterates over each element in the iterable and\n * performs an `unshift` operation on the doubly linked list\n * @returns The `unshiftMany` function returns an array of boolean values indicating the success of\n * each unshift operation performed on the elements passed as input.\n */\n unshiftMany(elements: Iterable<E> | Iterable<R> | Iterable<DoublyLinkedListNode<E>>) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) {\n ans.push(this.unshift(this.toElementFn(el as R)));\n continue;\n }\n ans.push(this.unshift(el as E | DoublyLinkedListNode<E>));\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `at` function returns the value at a specified index in a linked list, or undefined if the index is out of bounds.\n * @param {number} index - The index parameter is a number that represents the position of the element we want to\n * retrieve from the list.\n * @returns The method is returning the value at the specified index in the linked list. If the index is out of bounds\n * or the linked list is empty, it will return undefined.\n */\n at(index: number): E | undefined {\n if (index < 0 || index >= this._length) return undefined;\n let current = this.head;\n for (let i = 0; i < index; i++) {\n current = current!.next;\n }\n return current!.value;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `getNodeAt` returns the node at a given index in a doubly linked list, or undefined if the index is out of\n * range.\n * @param {number} index - The `index` parameter is a number that represents the position of the node we want to\n * retrieve from the doubly linked list. It indicates the zero-based index of the node we want to access.\n * @returns The method `getNodeAt(index: number)` returns a `DoublyLinkedListNode<E>` object if the index is within the\n * valid range of the linked list, otherwise it returns `undefined`.\n */\n getNodeAt(index: number): DoublyLinkedListNode<E> | undefined {\n if (index < 0 || index >= this._length) return undefined;\n let current = this.head;\n for (let i = 0; i < index; i++) {\n current = current!.next;\n }\n return current;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * This TypeScript function searches for a node in a doubly linked list based on a given element node\n * or predicate.\n * @param {| E\n * | DoublyLinkedListNode<E>\n * | ((node: DoublyLinkedListNode<E>) => boolean)\n * | undefined} elementNodeOrPredicate - The `getNode` method you provided is used to find a\n * node in a doubly linked list based on a given element, node, or predicate function. The\n * `elementNodeOrPredicate` parameter can be one of the following:\n * @returns The `getNode` method returns a `DoublyLinkedListNode<E>` or `undefined` based on the\n * input `elementNodeOrPredicate`. If the input is `undefined`, the method returns `undefined`.\n * Otherwise, it iterates through the linked list starting from the head node and applies the\n * provided predicate function to each node. If a node satisfies the predicate, that node is\n * returned. If\n */\n getNode(\n elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean) | undefined\n ): DoublyLinkedListNode<E> | undefined {\n if (elementNodeOrPredicate === undefined) return;\n if (this.isNode(elementNodeOrPredicate)) return elementNodeOrPredicate;\n const predicate = this._ensurePredicate(elementNodeOrPredicate);\n let current = this.head;\n\n while (current) {\n if (predicate(current)) {\n return current;\n }\n current = current.next;\n }\n\n return undefined;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `addAt` function inserts a new element or node at a specified index in a doubly linked list.\n * @param {number} index - The `index` parameter in the `addAt` method represents the position at\n * which you want to add a new element or node in the doubly linked list. It indicates the location\n * where the new element or node should be inserted.\n * @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the\n * `addAt` method can be either a value of type `E` or a `DoublyLinkedListNode<E>` object.\n * @returns The `addAt` method returns a boolean value. It returns `true` if the element or node was\n * successfully added at the specified index, and `false` if the index is out of bounds (less than 0\n * or greater than the length of the list).\n */\n addAt(index: number, newElementOrNode: E | DoublyLinkedListNode<E>): boolean {\n if (index < 0 || index > this._length) return false;\n if (index === 0) {\n this.unshift(newElementOrNode);\n return true;\n }\n if (index === this._length) {\n this.push(newElementOrNode);\n return true;\n }\n\n const newNode = this._ensureNode(newElementOrNode);\n const prevNode = this.getNodeAt(index - 1);\n const nextNode = prevNode!.next;\n newNode.prev = prevNode;\n newNode.next = nextNode;\n prevNode!.next = newNode;\n nextNode!.prev = newNode;\n this._length++;\n return true;\n }\n\n /**\n * Time Complexity: O(1) or O(n)\n * Space Complexity: O(1)\n *\n * The `addBefore` function in TypeScript adds a new element or node before an existing element or\n * node in a doubly linked list.\n * @param {E | DoublyLinkedListNode<E>} existingElementOrNode - The `existingElementOrNode` parameter\n * in the `addBefore` method can be either an element of type `E` or a `DoublyLinkedListNode<E>`.\n * @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter\n * represents the element or node that you want to add before the `existingElementOrNode` in a doubly\n * linked list.\n * @returns The `addBefore` method returns a boolean value - `true` if the new element or node was\n * successfully added before the existing element or node, and `false` if the existing element or\n * node was not found.\n */\n addBefore(\n existingElementOrNode: E | DoublyLinkedListNode<E>,\n newElementOrNode: E | DoublyLinkedListNode<E>\n ): boolean {\n const existingNode: DoublyLinkedListNode<E> | undefined = this.isNode(existingElementOrNode)\n ? existingElementOrNode\n : this.getNode(existingElementOrNode);\n\n if (existingNode) {\n const newNode = this._ensureNode(newElementOrNode);\n newNode.prev = existingNode.prev;\n if (existingNode.prev) {\n existingNode.prev.next = newNode;\n }\n newNode.next = existingNode;\n existingNode.prev = newNode;\n if (existingNode === this.head) {\n this._head = newNode;\n }\n this._length++;\n return true;\n }\n\n return false;\n }\n\n /**\n * Time Complexity: O(1) or O(n)\n * Space Complexity: O(1)\n *\n * The `addAfter` function in TypeScript adds a new element or node after an existing element or node\n * in a doubly linked list.\n * @param {E | DoublyLinkedListNode<E>} existingElementOrNode - existingElementOrNode represents the\n * element or node in the doubly linked list after which you want to add a new element or node.\n * @param {E | DoublyLinkedListNode<E>} newElementOrNode - The `newElementOrNode` parameter in the\n * `addAfter` method represents the element or node that you want to add after the existing element\n * or node in a doubly linked list. This parameter can be either an element value or a\n * `DoublyLinkedListNode` object that you want to insert\n * @returns The `addAfter` method returns a boolean value - `true` if the new element or node was\n * successfully added after the existing element or node, and `false` if the existing element or node\n * was not found in the linked list.\n */\n addAfter(existingElementOrNode: E | DoublyLinkedListNode<E>, newElementOrNode: E | DoublyLinkedListNode<E>): boolean {\n const existingNode: DoublyLinkedListNode<E> | undefined = this.isNode(existingElementOrNode)\n ? existingElementOrNode\n : this.getNode(existingElementOrNode);\n\n if (existingNode) {\n const newNode = this._ensureNode(newElementOrNode);\n newNode.next = existingNode.next;\n if (existingNode.next) {\n existingNode.next.prev = newNode;\n }\n newNode.prev = existingNode;\n existingNode.next = newNode;\n if (existingNode === this.tail) {\n this._tail = newNode;\n }\n this._length++;\n return true;\n }\n\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `setAt` updates the value at a specified index in a data structure if the index\n * exists.\n * @param {number} index - The `index` parameter in the `setAt` method refers to the position in the\n * data structure where you want to set a new value.\n * @param {E} value - The `value` parameter in the `setAt` method represents the new value that you\n * want to set at the specified index in the data structure.\n * @returns The `setAt` method returns a boolean value - `true` if the value at the specified index\n * is successfully updated, and `false` if the index is out of bounds.\n */\n setAt(index: number, value: E): boolean {\n const node = this.getNodeAt(index);\n if (node) {\n node.value = value;\n return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `deleteAt` function removes an element at a specified index from a linked list and returns the removed element.\n * @param {number} index - The index parameter represents the position of the element that needs to be deleted in the\n * data structure. It is of type number.\n * @returns The method `deleteAt` returns the value of the node that was deleted, or `undefined` if the index is out of\n * bounds.\n */\n deleteAt(index: number): E | undefined {\n if (index < 0 || index >= this._length) return;\n let deleted: E | undefined;\n if (index === 0) {\n deleted = this.first;\n this.shift();\n return deleted;\n }\n if (index === this._length - 1) {\n deleted = this.last;\n this.pop();\n return deleted;\n }\n\n const removedNode = this.getNodeAt(index);\n const prevNode = removedNode!.prev;\n const nextNode = removedNode!.next;\n prevNode!.next = nextNode;\n nextNode!.prev = prevNode;\n this._length--;\n return removedNode?.value;\n }\n\n /**\n * Time Complexity: O(1) or O(n)\n * Space Complexity: O(1)\n *\n * The `delete` function removes a specified element or node from a doubly linked list if it exists.\n * @param {E | DoublyLinkedListNode<E> | undefined} elementOrNode - The `elementOrNode` parameter in\n * the `delete` method can accept an element of type `E`, a `DoublyLinkedListNode` of type `E`, or it\n * can be `undefined`. This parameter is used to identify the node that needs to be deleted from the\n * doubly linked list\n * @returns The `delete` method returns a boolean value - `true` if the element or node was\n * successfully deleted from the doubly linked list, and `false` if the element or node was not found\n * in the list.\n */\n delete(elementOrNode: E | DoublyLinkedListNode<E> | undefined): boolean {\n const node: DoublyLinkedListNode<E> | undefined = this.getNode(elementOrNode);\n\n if (node) {\n if (node === this.head) {\n this.shift();\n } else if (node === this.tail) {\n this.pop();\n } else {\n const prevNode = node.prev;\n const nextNode = node.next;\n if (prevNode) prevNode.next = nextNode;\n if (nextNode) nextNode.prev = prevNode;\n this._length--;\n }\n return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if a variable has a length greater than zero and returns a boolean value.\n * @returns A boolean value is being returned.\n */\n isEmpty(): boolean {\n return this._length === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `clear` function resets the linked list by setting the head, tail, and length to undefined and 0 respectively.\n */\n clear(): void {\n this._head = undefined;\n this._tail = undefined;\n this._length = 0;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * This function retrieves an element from a doubly linked list based on a given element\n * node or predicate.\n * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `get` method takes in a parameter called `elementNodeOrPredicate`,\n * which can be one of the following types:\n * @returns The `get` method returns the value of the first node in the doubly linked list that\n * satisfies the provided predicate function. If no such node is found, it returns `undefined`.\n */\n search(\n elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)\n ): E | undefined {\n const predicate = this._ensurePredicate(elementNodeOrPredicate);\n let current = this.head;\n while (current) {\n if (predicate(current)) return current.value;\n current = current.next;\n }\n return undefined;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `getBackward` function searches for a specific element in a doubly linked list starting from\n * the tail and moving backwards.\n * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `getBackward`\n * function can be one of the following types:\n * @returns The `getBackward` method returns the value of the element node that matches the provided\n * predicate when traversing the doubly linked list backwards. If no matching element is found, it\n * returns `undefined`.\n */\n getBackward(\n elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)\n ): E | undefined {\n const predicate = this._ensurePredicate(elementNodeOrPredicate);\n let current = this.tail;\n while (current) {\n if (predicate(current)) return current.value;\n current = current.prev;\n }\n return undefined;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `reverse` function reverses the order of the elements in a doubly linked list.\n */\n reverse(): this {\n let current = this.head;\n [this._head, this._tail] = [this.tail, this.head];\n while (current) {\n const next = current.next;\n [current.prev, current.next] = [current.next, current.prev];\n current = next;\n }\n return this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `clone` function creates a new instance of the `DoublyLinkedList` class with the same values\n * as the original list.\n * @returns The `clone()` method is returning a new instance of the `DoublyLinkedList` class, which\n * is a copy of the original list.\n */\n clone(): this {\n return new DoublyLinkedList<E, R>(this, { toElementFn: this._toElementFn, maxLen: this._maxLen }) as this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new DoublyLinkedList by iterating over the elements of the current\n * list and applying a callback function to each element, returning only the elements for which the\n * callback function returns true.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the DoublyLinkedList. It takes three arguments: the current element, the index of the current\n * element, and the DoublyLinkedList itself. The callback function should return a boolean value\n * indicating whether the current element should be included\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `DoublyLinkedList` object that contains the\n * elements that pass the filter condition specified by the `callback` function.\n */\n filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): DoublyLinkedList<E, R> {\n const filteredList = this._createInstance({ toElementFn: this.toElementFn, maxLen: this._maxLen });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredList.push(current);\n }\n index++;\n }\n return filteredList;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function takes a callback function and returns a new DoublyLinkedList with the results\n * of applying the callback to each element in the original list.\n * @param callback - The callback parameter is a function that will be called for each element in the\n * original DoublyLinkedList. It takes three arguments: current (the current element being\n * processed), index (the index of the current element), and this (the original DoublyLinkedList).\n * The callback function should return a value of type\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to\n * convert the raw element (`RR`) to the desired element type (`T`). It takes the raw element as\n * input and returns the converted element. If this parameter is not provided, the raw element will\n * be used as is.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `DoublyLinkedList` class with elements of type `T` and `RR`.\n */\n map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): DoublyLinkedList<EM, RM> {\n const mappedList = new DoublyLinkedList<EM, RM>([], { toElementFn, maxLen: this._maxLen });\n let index = 0;\n for (const current of this) {\n mappedList.push(callback.call(thisArg, current, index, this));\n index++;\n }\n\n return mappedList;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `countOccurrences` iterates through a doubly linked list and counts the occurrences\n * of a specified element or nodes that satisfy a given predicate.\n * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementOrNode\n * - The `elementOrNode` parameter in the `countOccurrences` method can accept three types of values:\n * @returns The `countOccurrences` method returns the number of occurrences of the specified element,\n * node, or predicate function in the doubly linked list.\n */\n countOccurrences(elementOrNode: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)): number {\n const predicate = this._ensurePredicate(elementOrNode);\n let count = 0;\n let current = this.head;\n\n while (current) {\n if (predicate(current)) {\n count++;\n }\n current = current.next;\n }\n\n return count;\n }\n\n /**\n * The function returns an iterator that iterates over the values of a linked list.\n */\n protected *_getIterator(): IterableIterator<E> {\n let current = this.head;\n\n while (current) {\n yield current.value;\n current = current.next;\n }\n }\n\n /**\n * The function returns an iterator that iterates over the elements of a data structure in reverse\n * order.\n */\n protected *_getReverseIterator(): IterableIterator<E> {\n let current = this.tail;\n\n while (current) {\n yield current.value;\n current = current.prev;\n }\n }\n\n /**\n * The function returns an iterator that iterates over the nodes of a doubly linked list starting\n * from the head.\n */\n protected *_getNodeIterator(): IterableIterator<DoublyLinkedListNode<E>> {\n let current = this.head;\n\n while (current) {\n yield current;\n current = current.next;\n }\n }\n\n // protected *_getReverseNodeIterator(): IterableIterator<DoublyLinkedListNode<E>> {\n // const reversedArr = [...this._getNodeIterator()].reverse();\n //\n // for (const item of reversedArr) {\n // yield item;\n // }\n // }\n\n /**\n * The function `_isPredicate` checks if the input is a function that takes a `DoublyLinkedListNode`\n * as an argument and returns a boolean.\n * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following\n * types:\n * @returns The _isPredicate method is returning a boolean value indicating whether the\n * elementNodeOrPredicate parameter is a function or not. If the elementNodeOrPredicate is a\n * function, the method will return true, indicating that it is a predicate function.\n */\n protected _isPredicate(\n elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)\n ): elementNodeOrPredicate is (node: DoublyLinkedListNode<E>) => boolean {\n return typeof elementNodeOrPredicate === 'function';\n }\n\n /**\n * The function `_ensureNode` ensures that the input is a valid node in a doubly linked list.\n * @param {E | DoublyLinkedListNode<E>} elementOrNode - The `elementOrNode` parameter can be either\n * an element of type `E` or a `DoublyLinkedListNode` containing an element of type `E`.\n * @returns If the `elementOrNode` parameter is already a `DoublyLinkedListNode`, it will be returned\n * as is. Otherwise, a new `DoublyLinkedListNode` instance will be created with the `elementOrNode`\n * value and returned.\n */\n protected _ensureNode(elementOrNode: E | DoublyLinkedListNode<E>) {\n if (this.isNode(elementOrNode)) return elementOrNode;\n\n return new DoublyLinkedListNode<E>(elementOrNode);\n }\n\n /**\n * The function `_ensurePredicate` in TypeScript ensures that the input is either a node, a predicate\n * function, or a value to compare with the node's value.\n * @param {E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)} elementNodeOrPredicate\n * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following\n * types:\n * @returns A function is being returned that takes a `DoublyLinkedListNode` as a parameter and\n * returns a boolean value based on the conditions specified in the code.\n */\n protected _ensurePredicate(\n elementNodeOrPredicate: E | DoublyLinkedListNode<E> | ((node: DoublyLinkedListNode<E>) => boolean)\n ) {\n if (this.isNode(elementNodeOrPredicate)) return (node: DoublyLinkedListNode<E>) => node === elementNodeOrPredicate;\n\n if (this._isPredicate(elementNodeOrPredicate)) return elementNodeOrPredicate;\n\n return (node: DoublyLinkedListNode<E>) => node.value === elementNodeOrPredicate;\n }\n\n /**\n * The function `_createInstance` returns a new instance of `DoublyLinkedList` with the specified\n * options.\n * @param [options] - The `options` parameter in the `_createInstance` method is of type\n * `DoublyLinkedListOptions<E, R>`. It is an optional parameter that allows you to pass additional\n * configuration options when creating a new instance of the `DoublyLinkedList` class.\n * @returns An instance of the `DoublyLinkedList` class with an empty array and the provided options\n * is being returned, cast as the current class type.\n */\n protected override _createInstance(options?: DoublyLinkedListOptions<E, R>): this {\n return new DoublyLinkedList<E, R>([], options) as this;\n }\n\n /**\n * The function `_getPrevNode` returns the previous node of a given node in a doubly linked list.\n * @param node - The parameter `node` in the `_getPrevNode` method is of type\n * `DoublyLinkedListNode<E>`, which represents a node in a doubly linked list containing an element\n * of type `E`.\n * @returns The `_getPrevNode` method is returning the previous node of the input `node` in a doubly\n * linked list. If the input node has a previous node, it will return that node. Otherwise, it will\n * return `undefined`.\n */\n protected _getPrevNode(node: DoublyLinkedListNode<E>): DoublyLinkedListNode<E> | undefined {\n return node.prev;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { SkipLinkedListOptions } from '../../types';\n\nexport class SkipListNode<K, V> {\n key: K;\n value: V;\n forward: SkipListNode<K, V>[];\n\n constructor(key: K, value: V, level: number) {\n this.key = key;\n this.value = value;\n this.forward = new Array(level);\n }\n}\n\n/**\n *\n */\nexport class SkipList<K, V> {\n /**\n * The constructor function initializes a SkipLinkedList object with optional options and elements.\n * @param elements - The `elements` parameter is an iterable containing key-value pairs `[K, V]`. It\n * is used to initialize the SkipLinkedList with the given key-value pairs. If no elements are\n * provided, the SkipLinkedList will be empty.\n * @param {SkipLinkedListOptions} [options] - The `options` parameter is an optional object that can\n * contain two properties:\n */\n constructor(elements: Iterable<[K, V]> = [], options?: SkipLinkedListOptions) {\n if (options) {\n const { maxLevel, probability } = options;\n if (typeof maxLevel === 'number') this._maxLevel = maxLevel;\n if (typeof probability === 'number') this._probability = probability;\n }\n\n if (elements) {\n for (const [key, value] of elements) this.add(key, value);\n }\n }\n\n protected _head: SkipListNode<K, V> = new SkipListNode<K, V>(undefined as any, undefined as any, this.maxLevel);\n\n /**\n * The function returns the head node of a SkipList.\n * @returns The method is returning a SkipListNode object with generic key type K and value type V.\n */\n get head(): SkipListNode<K, V> {\n return this._head;\n }\n\n protected _level: number = 0;\n\n /**\n * The function returns the value of the protected variable _level.\n * @returns The level property of the object.\n */\n get level(): number {\n return this._level;\n }\n\n protected _maxLevel: number = 16;\n\n /**\n * The function returns the maximum level.\n * @returns The value of the variable `_maxLevel` is being returned.\n */\n get maxLevel(): number {\n return this._maxLevel;\n }\n\n protected _probability: number = 0.5;\n\n /**\n * The function returns the probability value.\n * @returns The probability value stored in the protected variable `_probability` is being returned.\n */\n get probability(): number {\n return this._probability;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Get the value of the first element (the smallest element) in the Skip List.\n * @returns The value of the first element, or undefined if the Skip List is empty.\n */\n get first(): V | undefined {\n const firstNode = this.head.forward[0];\n return firstNode ? firstNode.value : undefined;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Get the value of the last element (the largest element) in the Skip List.\n * @returns The value of the last element, or undefined if the Skip List is empty.\n */\n get last(): V | undefined {\n let current = this.head;\n for (let i = this.level - 1; i >= 0; i--) {\n while (current.forward[i]) {\n current = current.forward[i];\n }\n }\n return current.value;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The add function adds a new node with a given key and value to a Skip List data structure.\n * @param {K} key - The key parameter represents the key of the node that needs to be added to the skip list.\n * @param {V} value - The \"value\" parameter represents the value associated with the key that is being added to the Skip\n * List.\n */\n add(key: K, value: V): void {\n const newNode = new SkipListNode(key, value, this._randomLevel());\n const update: SkipListNode<K, V>[] = new Array(this.maxLevel).fill(this.head);\n let current = this.head;\n\n for (let i = this.level - 1; i >= 0; i--) {\n while (current.forward[i] && current.forward[i].key < key) {\n current = current.forward[i];\n }\n update[i] = current;\n }\n\n for (let i = 0; i < newNode.forward.length; i++) {\n newNode.forward[i] = update[i].forward[i];\n update[i].forward[i] = newNode;\n }\n\n if (!newNode.forward[0]) {\n this._level = Math.max(this.level, newNode.forward.length);\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The function `get` retrieves the value associated with a given key from a skip list data structure.\n * @param {K} key - The `key` parameter is the key of the element that we want to retrieve from the data structure.\n * @returns The method `get(key: K)` returns the value associated with the given key if it exists in the data structure,\n * otherwise it returns `undefined`.\n */\n get(key: K): V | undefined {\n let current = this.head;\n for (let i = this.level - 1; i >= 0; i--) {\n while (current.forward[i] && current.forward[i].key < key) {\n current = current.forward[i];\n }\n }\n\n current = current.forward[0];\n\n if (current && current.key === key) {\n return current.value;\n }\n\n return undefined;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The function checks if a key exists in a data structure.\n * @param {K} key - The parameter \"key\" is of type K, which represents the type of the key being\n * checked.\n * @returns a boolean value.\n */\n has(key: K): boolean {\n return this.get(key) !== undefined;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The `delete` function removes a node with a specific key from a Skip List data structure.\n * @param {K} key - The key parameter represents the key of the node that needs to be removed from the skip list.\n * @returns The `delete` method returns a boolean value. It returns `true` if the key was successfully removed from the\n * skip list, and `false` if the key was not found in the skip list.\n */\n delete(key: K): boolean {\n const update: SkipListNode<K, V>[] = new Array(this.maxLevel).fill(this.head);\n let current = this.head;\n\n for (let i = this.level - 1; i >= 0; i--) {\n while (current.forward[i] && current.forward[i].key < key) {\n current = current.forward[i];\n }\n update[i] = current;\n }\n\n current = current.forward[0];\n\n if (current && current.key === key) {\n for (let i = 0; i < this.level; i++) {\n if (update[i].forward[i] !== current) {\n break;\n }\n update[i].forward[i] = current.forward[i];\n }\n while (this.level > 0 && !this.head.forward[this.level - 1]) {\n this._level--;\n }\n return true;\n }\n\n return false;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Get the value of the first element in the Skip List that is greater than the given key.\n * @param key - the given key.\n * @returns The value of the first element greater than the given key, or undefined if there is no such element.\n */\n higher(key: K): V | undefined {\n let current = this.head;\n for (let i = this.level - 1; i >= 0; i--) {\n while (current.forward[i] && current.forward[i].key <= key) {\n current = current.forward[i];\n }\n }\n const nextNode = current.forward[0];\n return nextNode ? nextNode.value : undefined;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Get the value of the last element in the Skip List that is less than the given key.\n * @param key - the given key.\n * @returns The value of the last element less than the given key, or undefined if there is no such element.\n */\n lower(key: K): V | undefined {\n let current = this.head;\n let lastLess = undefined;\n\n for (let i = this.level - 1; i >= 0; i--) {\n while (current.forward[i] && current.forward[i].key < key) {\n current = current.forward[i];\n }\n if (current.key < key) {\n lastLess = current;\n }\n }\n\n return lastLess ? lastLess.value : undefined;\n }\n\n /**\n * Time Complexity: O(maxLevel)\n * Space Complexity: O(1)\n *\n * The function \"_randomLevel\" generates a random level based on a given probability and maximum level.\n * @returns the level, which is a number.\n */\n protected _randomLevel(): number {\n let level = 1;\n while (Math.random() < this.probability && level < this.maxLevel) {\n level++;\n }\n return level;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { ElementCallback, StackOptions } from '../../types';\nimport { IterableElementBase } from '../base';\n\n/**\n * 1. Last In, First Out (LIFO): The core characteristic of a stack is its last in, first out nature, meaning the last element added to the stack will be the first to be removed.\n * 2. Uses: Stacks are commonly used for managing a series of tasks or elements that need to be processed in a last in, first out manner. They are widely used in various scenarios, such as in function calls in programming languages, evaluation of arithmetic expressions, and backtracking algorithms.\n * 3. Performance: Stack operations are typically O(1) in time complexity, meaning that regardless of the stack's size, adding, removing, and viewing the top element are very fast operations.\n * 4. Function Calls: In most modern programming languages, the records of function calls are managed through a stack. When a function is called, its record (including parameters, local variables, and return address) is 'pushed' into the stack. When the function returns, its record is 'popped' from the stack.\n * 5. Expression Evaluation: Used for the evaluation of arithmetic or logical expressions, especially when dealing with parenthesis matching and operator precedence.\n * 6. Backtracking Algorithms: In problems where multiple branches need to be explored but only one branch can be explored at a time, stacks can be used to save the state at each branching point.\n * @example\n * // Balanced Parentheses or Brackets\n * type ValidCharacters = ')' | '(' | ']' | '[' | '}' | '{';\n *\n * const stack = new Stack<string>();\n * const input: ValidCharacters[] = '[({})]'.split('') as ValidCharacters[];\n * const matches: { [key in ValidCharacters]?: ValidCharacters } = { ')': '(', ']': '[', '}': '{' };\n * for (const char of input) {\n * if ('([{'.includes(char)) {\n * stack.push(char);\n * } else if (')]}'.includes(char)) {\n * if (stack.pop() !== matches[char]) {\n * fail('Parentheses are not balanced');\n * }\n * }\n * }\n * console.log(stack.isEmpty()); // true\n * @example\n * // Expression Evaluation and Conversion\n * const stack = new Stack<number>();\n * const expression = [5, 3, '+']; // Equivalent to 5 + 3\n * expression.forEach(token => {\n * if (typeof token === 'number') {\n * stack.push(token);\n * } else {\n * const b = stack.pop()!;\n * const a = stack.pop()!;\n * stack.push(token === '+' ? a + b : 0); // Only handling '+' here\n * }\n * });\n * console.log(stack.pop()); // 8\n * @example\n * // Depth-First Search (DFS)\n * const stack = new Stack<number>();\n * const graph: { [key in number]: number[] } = { 1: [2, 3], 2: [4], 3: [5], 4: [], 5: [] };\n * const visited: number[] = [];\n * stack.push(1);\n * while (!stack.isEmpty()) {\n * const node = stack.pop()!;\n * if (!visited.includes(node)) {\n * visited.push(node);\n * graph[node].forEach(neighbor => stack.push(neighbor));\n * }\n * }\n * console.log(visited); // [1, 3, 5, 2, 4]\n * @example\n * // Backtracking Algorithms\n * const stack = new Stack<[number, number]>();\n * const maze = [\n * ['S', ' ', 'X'],\n * ['X', ' ', 'X'],\n * [' ', ' ', 'E']\n * ];\n * const start: [number, number] = [0, 0];\n * const end = [2, 2];\n * const directions = [\n * [0, 1], // To the right\n * [1, 0], // down\n * [0, -1], // left\n * [-1, 0] // up\n * ];\n *\n * const visited = new Set<string>(); // Used to record visited nodes\n * stack.push(start);\n * const path: number[][] = [];\n *\n * while (!stack.isEmpty()) {\n * const [x, y] = stack.pop()!;\n * if (visited.has(`${x},${y}`)) continue; // Skip already visited nodes\n * visited.add(`${x},${y}`);\n *\n * path.push([x, y]);\n *\n * if (x === end[0] && y === end[1]) {\n * break; // Find the end point and exit\n * }\n *\n * for (const [dx, dy] of directions) {\n * const nx = x + dx;\n * const ny = y + dy;\n * if (\n * maze[nx]?.[ny] === ' ' || // feasible path\n * maze[nx]?.[ny] === 'E' // destination\n * ) {\n * stack.push([nx, ny]);\n * }\n * }\n * }\n *\n * expect(path).toContainEqual(end);\n * @example\n * // Function Call Stack\n * const functionStack = new Stack<string>();\n * functionStack.push('main');\n * functionStack.push('foo');\n * functionStack.push('bar');\n * console.log(functionStack.pop()); // 'bar'\n * console.log(functionStack.pop()); // 'foo'\n * console.log(functionStack.pop()); // 'main'\n * @example\n * // Simplify File Paths\n * const stack = new Stack<string>();\n * const path = '/a/./b/../../c';\n * path.split('/').forEach(segment => {\n * if (segment === '..') stack.pop();\n * else if (segment && segment !== '.') stack.push(segment);\n * });\n * console.log(stack.elements.join('/')); // 'c'\n * @example\n * // Stock Span Problem\n * const stack = new Stack<number>();\n * const prices = [100, 80, 60, 70, 60, 75, 85];\n * const spans: number[] = [];\n * prices.forEach((price, i) => {\n * while (!stack.isEmpty() && prices[stack.peek()!] <= price) {\n * stack.pop();\n * }\n * spans.push(stack.isEmpty() ? i + 1 : i - stack.peek()!);\n * stack.push(i);\n * });\n * console.log(spans); // [1, 1, 1, 2, 1, 4, 6]\n */\nexport class Stack<E = any, R = any> extends IterableElementBase<E, R> {\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: StackOptions<E, R>) {\n super(options);\n this.pushMany(elements);\n }\n\n protected _elements: E[] = [];\n\n /**\n * The elements function returns the elements of this set.\n * @return An array of elements\n */\n get elements(): E[] {\n return this._elements;\n }\n\n /**\n * The size() function returns the number of elements in an array.\n * @returns The size of the elements array.\n */\n get size(): number {\n return this.elements.length;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function \"fromArray\" creates a new Stack object from an array of elements.\n * @param {E[]} elements - The `elements` parameter is an array of elements of type `E`.\n * @returns {Stack} The method is returning a new instance of the Stack class, initialized with the elements from the input\n * array.\n */\n static fromArray<E>(elements: E[]): Stack<E> {\n return new Stack(elements);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if an array is empty and returns a boolean value.\n * @returns A boolean value indicating whether the `_elements` array is empty or not.\n */\n isEmpty(): boolean {\n return this.elements.length === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `peek` function returns the last element of an array, or undefined if the array is empty.\n * @returns The `peek()` function returns the last element of the `_elements` array, or `undefined` if the array is empty.\n */\n peek(): E | undefined {\n if (this.isEmpty()) return undefined;\n\n return this.elements[this.elements.length - 1];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The push function adds an element to the stack and returns the updated stack.\n * @param {E} element - The parameter \"element\" is of type E, which means it can be any data type.\n * @returns The `push` method is returning the updated `Stack<E>` object.\n */\n push(element: E): boolean {\n this.elements.push(element);\n return true;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `pop` function removes and returns the last element from an array, or returns undefined if the array is empty.\n * @returns The `pop()` method is returning the last element of the array `_elements` if the array is not empty. If the\n * array is empty, it returns `undefined`.\n */\n pop(): E | undefined {\n if (this.isEmpty()) return;\n\n return this.elements.pop();\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(1)\n *\n * The function `pushMany` iterates over elements and pushes them into an array after applying a\n * transformation function if provided.\n * @param {Iterable<E> | Iterable<R>} elements - The `elements` parameter in the `pushMany` function\n * is an iterable containing elements of type `E` or `R`. The function iterates over each element in\n * the iterable and pushes it into the data structure. If a transformation function `toElementFn` is\n * provided, it is used to\n * @returns The `pushMany` function is returning an array of boolean values indicating whether each\n * element was successfully pushed into the data structure.\n */\n pushMany(elements: Iterable<E> | Iterable<R>) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) {\n ans.push(this.push(this.toElementFn(el as R)));\n } else {\n ans.push(this.push(el as E));\n }\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The toArray function returns a copy of the elements in an array.\n * @returns An array of type E.\n */\n delete(element: E): boolean {\n const index = this.elements.indexOf(element);\n return this.deleteAt(index);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The toArray function returns a copy of the elements in an array.\n * @returns An array of type E.\n */\n deleteAt(index: number): boolean {\n const spliced = this.elements.splice(index, 1);\n return spliced.length === 1;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear function clears the elements array.\n */\n clear(): void {\n this._elements = [];\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `clone()` function returns a new `Stack` object with the same elements as the original stack.\n * @returns The `clone()` method is returning a new `Stack` object with a copy of the `_elements` array.\n */\n clone(): Stack<E, R> {\n return new Stack<E, R>(this, { toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new stack containing elements from the original stack that satisfy\n * a given predicate function.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * the current element being iterated over, the index of the current element, and the stack itself.\n * It should return a boolean value indicating whether the element should be included in the filtered\n * stack or not.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `predicate` function. If `thisArg` is\n * @returns The `filter` method is returning a new `Stack` object that contains the elements that\n * satisfy the given predicate function.\n */\n filter(predicate: ElementCallback<E, R, boolean>, thisArg?: any): Stack<E, R> {\n const newStack = new Stack<E, R>([], { toElementFn: this.toElementFn });\n let index = 0;\n for (const el of this) {\n if (predicate.call(thisArg, el, index, this)) {\n newStack.push(el);\n }\n index++;\n }\n return newStack;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function takes a callback function and applies it to each element in the stack,\n * returning a new stack with the results.\n * @param callback - The callback parameter is a function that will be called for each element in the\n * stack. It takes three arguments: the current element, the index of the element, and the stack\n * itself. It should return a new value that will be added to the new stack.\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to\n * transform the raw element (`RM`) into a new element (`EM`) before pushing it into the new stack.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new Stack object with elements of type EM and raw elements of type RM.\n */\n map<EM, RM>(callback: ElementCallback<E, R, EM>, toElementFn?: (rawElement: RM) => EM, thisArg?: any): Stack<EM, RM> {\n const newStack = new Stack<EM, RM>([], { toElementFn });\n let index = 0;\n for (const el of this) {\n newStack.push(callback.call(thisArg, el, index, this));\n index++;\n }\n return newStack;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * Custom iterator for the Stack class.\n * @returns An iterator object.\n */\n protected *_getIterator(): IterableIterator<E> {\n for (let i = 0; i < this.elements.length; i++) {\n yield this.elements[i];\n }\n }\n}\n","/**\n * @license MIT\n * @copyright Pablo Zeng <zrwusa@gmail.com>\n * @class\n */\nimport type { ElementCallback, QueueOptions } from '../../types';\nimport { SinglyLinkedList } from '../linked-list';\nimport { LinearBase } from '../base/linear-base';\n\n/**\n * 1. First In, First Out (FIFO): The core feature of a queue is its first in, first out nature. The element added to the queue first will be the one to be removed first.\n * 2. Operations: The main operations include enqueue (adding an element to the end of the queue) and dequeue (removing and returning the element at the front of the queue). Typically, there is also a peek operation (looking at the front element without removing it).\n * 3. Uses: Queues are commonly used to manage a series of tasks or elements that need to be processed in order. For example, managing task queues in a multi-threaded environment, or in algorithms for data structures like trees and graphs for breadth-first search.\n * 4. Task Scheduling: Managing the order of task execution in operating systems or applications.\n * 5. Data Buffering: Acting as a buffer for data packets in network communication.\n * 6. Breadth-First Search (BFS): In traversal algorithms for graphs and trees, queues store elements that are to be visited.\n * 7. Real-time Queuing: Like queuing systems in banks or supermarkets.\n * @example\n * // Sliding Window using Queue\n * const nums = [2, 3, 4, 1, 5];\n * const k = 2;\n * const queue = new Queue<number>();\n *\n * let maxSum = 0;\n * let currentSum = 0;\n *\n * nums.forEach((num, i) => {\n * queue.push(num);\n * currentSum += num;\n *\n * if (queue.length > k) {\n * currentSum -= queue.shift()!;\n * }\n *\n * if (queue.length === k) {\n * maxSum = Math.max(maxSum, currentSum);\n * }\n * });\n *\n * console.log(maxSum); // 7\n * @example\n * // Breadth-First Search (BFS) using Queue\n * const graph: { [key in number]: number[] } = {\n * 1: [2, 3],\n * 2: [4, 5],\n * 3: [],\n * 4: [],\n * 5: []\n * };\n *\n * const queue = new Queue<number>();\n * const visited: number[] = [];\n *\n * queue.push(1);\n *\n * while (!queue.isEmpty()) {\n * const node = queue.shift()!;\n * if (!visited.includes(node)) {\n * visited.push(node);\n * graph[node].forEach(neighbor => queue.push(neighbor));\n * }\n * }\n *\n * console.log(visited); // [1, 2, 3, 4, 5]\n */\nexport class Queue<E = any, R = any> extends LinearBase<E, R> {\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: QueueOptions<E, R>) {\n super(options);\n\n if (options) {\n const { autoCompactRatio = 0.5 } = options;\n this._autoCompactRatio = autoCompactRatio;\n }\n\n this.pushMany(elements);\n }\n\n protected _elements: E[] = [];\n\n get elements(): E[] {\n return this._elements;\n }\n\n protected _offset: number = 0;\n\n get offset(): number {\n return this._offset;\n }\n\n get length(): number {\n return this.elements.length - this.offset;\n }\n\n protected _autoCompactRatio: number = 0.5;\n\n get autoCompactRatio(): number {\n return this._autoCompactRatio;\n }\n\n set autoCompactRatio(v: number) {\n this._autoCompactRatio = v;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `first` function returns the first element of the array `_elements` if it exists, otherwise it returns `undefined`.\n * @returns The `get first()` method returns the first element of the data structure, represented by the `_elements` array at\n * the `_offset` index. If the data structure is empty (length is 0), it returns `undefined`.\n */\n get first(): E | undefined {\n return this.length > 0 ? this.elements[this.offset] : undefined;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `last` function returns the last element in an array-like data structure, or undefined if the structure is empty.\n * @returns The method `get last()` returns the last element of the `_elements` array if the array is not empty. If the\n * array is empty, it returns `undefined`.\n */\n get last(): E | undefined {\n return this.length > 0 ? this.elements[this.elements.length - 1] : undefined;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function \"fromArray\" creates a new Queue object from an array of elements.Creates a queue from an existing array.\n * @public\n * @param {E[]} elements - The \"elements\" parameter is an array of elements of type E.\n * @returns The method is returning a new instance of the Queue class, initialized with the elements from the input\n * array.\n */\n static fromArray<E>(elements: E[]): Queue<E> {\n return new Queue(elements);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The push function adds an element to the end of the queue and returns true. Adds an element at the back of the queue.\n * @param {E} element - The `element` parameter represents the element that you want to add to the queue.\n * @returns Always returns true, indicating the element was successfully added.\n */\n push(element: E): boolean {\n this.elements.push(element);\n if (this._maxLen > 0 && this.length > this._maxLen) this.shift();\n return true;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The `pushMany` function iterates over elements and pushes them into an array after applying a\n * transformation function if provided.\n * @param {Iterable<E> | Iterable<R>} elements - The `elements` parameter in the `pushMany` function\n * is an iterable containing elements of type `E` or `R`.\n * @returns The `pushMany` function is returning an array of boolean values indicating whether each\n * element was successfully pushed into the data structure.\n */\n pushMany(elements: Iterable<E> | Iterable<R>) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) ans.push(this.push(this.toElementFn(el as R)));\n else ans.push(this.push(el as E));\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `shift` function removes and returns the first element in the queue, and adjusts the internal data structure if\n * necessary to optimize performance.\n * @returns The function `shift()` returns either the first element in the queue or `undefined` if the queue is empty.\n */\n shift(): E | undefined {\n if (this.length === 0) return undefined;\n\n const first = this.first;\n this._offset += 1;\n\n if (this.offset / this.elements.length > this.autoCompactRatio) this.compact();\n return first;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The delete function removes an element from the list.\n * @param {E} element - Specify the element to be deleted\n * @return A boolean value indicating whether the element was successfully deleted or not\n */\n delete(element: E): boolean {\n const index = this.elements.indexOf(element);\n return !!this.deleteAt(index);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The deleteAt function deletes the element at a given index.\n * @param {number} index - Determine the index of the element to be deleted\n * @return A boolean value\n */\n deleteAt(index: number): E | undefined {\n const deleted = this.elements[index];\n this.elements.splice(index, 1);\n return deleted;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `at` function returns the element at a specified index adjusted by an offset, or `undefined`\n * if the index is out of bounds.\n * @param {number} index - The `index` parameter represents the position of the element you want to\n * retrieve from the data structure.\n * @returns The `at` method is returning the element at the specified index adjusted by the offset\n * `_offset`.\n */\n at(index: number): E | undefined {\n return this.elements[index + this._offset];\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `reverse` function in TypeScript reverses the elements of an array starting from a specified\n * offset.\n * @returns The `reverse()` method is returning the modified object itself (`this`) after reversing\n * the elements in the array and resetting the offset to 0.\n */\n reverse(): this {\n this._elements = this.elements.slice(this.offset).reverse();\n this._offset = 0;\n return this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `addAt` inserts a new element at a specified index in an array, returning true if\n * successful and false if the index is out of bounds.\n * @param {number} index - The `index` parameter represents the position at which the `newElement`\n * should be added in the array.\n * @param {E} newElement - The `newElement` parameter represents the element that you want to insert\n * into the array at the specified index.\n * @returns The `addAt` method returns a boolean value - `true` if the new element was successfully\n * added at the specified index, and `false` if the index is out of bounds (less than 0 or greater\n * than the length of the array).\n */\n addAt(index: number, newElement: E): boolean {\n if (index < 0 || index > this.length) return false;\n this._elements.splice(this.offset + index, 0, newElement);\n return true;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `setAt` updates an element at a specified index in an array-like data structure.\n * @param {number} index - The `index` parameter is a number that represents the position in the\n * array where the new element will be set.\n * @param {E} newElement - The `newElement` parameter represents the new value that you want to set\n * at the specified index in the array.\n * @returns The `setAt` method returns a boolean value - `true` if the element was successfully set\n * at the specified index, and `false` if the index is out of bounds (less than 0 or greater than the\n * length of the array).\n */\n setAt(index: number, newElement: E): boolean {\n if (index < 0 || index > this.length) return false;\n this._elements[this.offset + index] = newElement;\n return true;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if a data structure is empty by comparing its length to zero.\n * @returns {boolean} A boolean value indicating whether the length of the object is 0 or not.\n */\n isEmpty(): boolean {\n return this.length === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear function resets the elements array and offset to their initial values.\n */\n clear(): void {\n this._elements = [];\n this._offset = 0;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `compact` function in TypeScript slices the elements array based on the offset and resets the\n * offset to zero.\n * @returns The `compact()` method is returning a boolean value of `true`.\n */\n compact(): boolean {\n this._elements = this.elements.slice(this.offset);\n this._offset = 0;\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function overrides the splice method to remove and insert elements in a queue-like data\n * structure.\n * @param {number} start - The `start` parameter in the `splice` method specifies the index at which\n * to start changing the array. Items will be added or removed starting from this index.\n * @param {number} [deleteCount=0] - The `deleteCount` parameter in the `splice` method specifies the\n * number of elements to remove from the array starting at the specified `start` index. If\n * `deleteCount` is not provided, it defaults to 0, meaning no elements will be removed but new\n * elements can still be inserted at\n * @param {E[]} items - The `items` parameter in the `splice` method represents the elements that\n * will be added to the array at the specified `start` index. These elements will replace the\n * existing elements starting from the `start` index for the `deleteCount` number of elements.\n * @returns The `splice` method is returning the `removedQueue`, which is an instance of the same\n * class as the original object.\n */\n override splice(start: number, deleteCount: number = 0, ...items: E[]): this {\n const removedQueue = this._createInstance();\n\n start = Math.max(0, Math.min(start, this.length));\n deleteCount = Math.max(0, Math.min(deleteCount, this.length - start));\n\n const globalStartIndex = this.offset + start;\n\n const removedElements = this._elements.splice(globalStartIndex, deleteCount, ...items);\n removedQueue.pushMany(removedElements);\n\n this.compact();\n\n return removedQueue;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `clone()` function returns a new Queue object with the same elements as the original Queue.\n * @returns The `clone()` method is returning a new instance of the `Queue` class.\n */\n clone(): this {\n return new Queue(this.elements.slice(this.offset), { toElementFn: this.toElementFn, maxLen: this._maxLen }) as this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new `Queue` object containing elements from the original `Queue`\n * that satisfy a given predicate function.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * the current element being iterated over, the index of the current element, and the queue itself.\n * It should return a boolean value indicating whether the element should be included in the filtered\n * queue or not.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `predicate` function. If `thisArg` is\n * @returns The `filter` method is returning a new `Queue` object that contains the elements that\n * satisfy the given predicate function.\n */\n filter(predicate: ElementCallback<E, R, boolean>, thisArg?: any): Queue<E, R> {\n const newDeque = this._createInstance({\n toElementFn: this._toElementFn,\n autoCompactRatio: this._autoCompactRatio,\n maxLen: this._maxLen\n });\n let index = 0;\n for (const el of this) {\n if (predicate.call(thisArg, el, index, this)) {\n newDeque.push(el);\n }\n index++;\n }\n return newDeque;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function in TypeScript creates a new Queue by applying a callback function to each\n * element in the original Queue.\n * @param callback - The `callback` parameter is a function that will be applied to each element in\n * the queue. It takes the current element, its index, and the queue itself as arguments, and returns\n * a new element.\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be provided to\n * convert a raw element of type `RM` to a new element of type `EM`. This function is used within the\n * `map` method to transform each raw element before passing it to the `callback` function. If\n * @param {any} [thisArg] - The `thisArg` parameter in the `map` function is used to specify the\n * value of `this` when executing the `callback` function. It allows you to set the context (the\n * value of `this`) within the callback function. If `thisArg` is provided, it will be\n * @returns A new Queue object containing elements of type EM, which are the result of applying the\n * callback function to each element in the original Queue object.\n */\n map<EM, RM>(callback: ElementCallback<E, R, EM>, toElementFn?: (rawElement: RM) => EM, thisArg?: any): Queue<EM, RM> {\n const newDeque = new Queue<EM, RM>([], {\n toElementFn,\n autoCompactRatio: this._autoCompactRatio,\n maxLen: this._maxLen\n });\n let index = 0;\n for (const el of this) {\n newDeque.push(callback.call(thisArg, el, index, this));\n index++;\n }\n return newDeque;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `_getIterator` returns an iterable iterator for the elements in the class.\n */\n protected *_getIterator(): IterableIterator<E> {\n for (const item of this.elements.slice(this.offset)) {\n yield item;\n }\n }\n\n /**\n * The function `_createInstance` returns a new instance of the `Queue` class with the specified\n * options.\n * @param [options] - The `options` parameter in the `_createInstance` method is of type\n * `QueueOptions<E, R>`, which is used to configure the behavior of the queue being created. It\n * allows you to specify settings or properties that can influence how the queue operates.\n * @returns An instance of the `Queue` class with an empty array and the provided options is being\n * returned.\n */\n protected override _createInstance(options?: QueueOptions<E, R>): this {\n return new Queue<E, R>([], options) as this;\n }\n\n /**\n * The function `_getReverseIterator` returns an iterator that iterates over elements in reverse\n * order.\n */\n protected *_getReverseIterator(): IterableIterator<E> {\n for (let i = this.length - 1; i >= 0; i--) {\n const cur = this.at(i); // `at()` handles the offset.\n if (cur !== undefined) yield cur;\n }\n }\n}\n\n/**\n * 1. First In, First Out (FIFO) Strategy: Like other queue implementations, LinkedListQueue follows the first in, first out principle, meaning the element that is added to the queue first will be the first to be removed.\n * 2. Based on Linked List: LinkedListQueue uses a linked list to store elements. Each node in the linked list contains data and a pointer to the next node.\n * 3. Memory Usage: Since each element requires additional space to store a pointer to the next element, linked lists may use more memory compared to arrays.\n * 4. Frequent Enqueuing and Dequeuing Operations: If your application involves frequent enqueuing and dequeuing operations and is less concerned with random access, then LinkedListQueue is a good choice.\n */\nexport class LinkedListQueue<E = any, R = any> extends SinglyLinkedList<E, R> {\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n * The `clone` function returns a new instance of the `LinkedListQueue` class with the same values as\n * the current instance.\n * @returns The `clone()` method is returning a new instance of `LinkedListQueue` with the same\n * values as the original `LinkedListQueue`.\n */\n override clone(): this {\n return new LinkedListQueue<E, R>(this, { toElementFn: this.toElementFn, maxLen: this._maxLen }) as this;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { DequeOptions, ElementCallback, IterableWithSizeOrLength } from '../../types';\nimport { calcMinUnitsRequired, rangeCheck } from '../../utils';\nimport { LinearBase } from '../base/linear-base';\n\n/**\n * 1. Operations at Both Ends: Supports adding and removing elements at both the front and back of the queue. This allows it to be used as a stack (last in, first out) and a queue (first in, first out).\n * 2. Efficient Random Access: Being based on an array, it offers fast random access capability, allowing constant time access to any element.\n * 3. Continuous Memory Allocation: Since it is based on an array, all elements are stored contiguously in memory, which can bring cache friendliness and efficient memory access.\n * 4. Efficiency: Adding and removing elements at both ends of a deque is usually very fast. However, when the dynamic array needs to expand, it may involve copying the entire array to a larger one, and this operation has a time complexity of O(n).\n * 5. Performance jitter: Deque may experience performance jitter, but DoublyLinkedList will not\n * @example\n * // prize roulette\n * class PrizeRoulette {\n * private deque: Deque<string>;\n *\n * constructor(prizes: string[]) {\n * // Initialize the deque with prizes\n * this.deque = new Deque<string>(prizes);\n * }\n *\n * // Rotate clockwise to the right (forward)\n * rotateClockwise(steps: number): void {\n * const n = this.deque.length;\n * if (n === 0) return;\n *\n * for (let i = 0; i < steps; i++) {\n * const last = this.deque.pop(); // Remove the last element\n * this.deque.unshift(last!); // Add it to the front\n * }\n * }\n *\n * // Rotate counterclockwise to the left (backward)\n * rotateCounterClockwise(steps: number): void {\n * const n = this.deque.length;\n * if (n === 0) return;\n *\n * for (let i = 0; i < steps; i++) {\n * const first = this.deque.shift(); // Remove the first element\n * this.deque.push(first!); // Add it to the back\n * }\n * }\n *\n * // Display the current prize at the head\n * display() {\n * return this.deque.first;\n * }\n * }\n *\n * // Example usage\n * const prizes = ['Car', 'Bike', 'Laptop', 'Phone', 'Watch', 'Headphones']; // Initialize the prize list\n * const roulette = new PrizeRoulette(prizes);\n *\n * // Display the initial state\n * console.log(roulette.display()); // 'Car' // Car\n *\n * // Rotate clockwise by 3 steps\n * roulette.rotateClockwise(3);\n * console.log(roulette.display()); // 'Phone' // Phone\n *\n * // Rotate counterclockwise by 2 steps\n * roulette.rotateCounterClockwise(2);\n * console.log(roulette.display()); // 'Headphones'\n * @example\n * // sliding window\n * // Maximum function of sliding window\n * function maxSlidingWindow(nums: number[], k: number): number[] {\n * const n = nums.length;\n * if (n * k === 0) return [];\n *\n * const deq = new Deque<number>();\n * const result: number[] = [];\n *\n * for (let i = 0; i < n; i++) {\n * // Delete indexes in the queue that are not within the window range\n * if (deq.length > 0 && deq.first! === i - k) {\n * deq.shift();\n * }\n *\n * // Remove all indices less than the current value from the tail of the queue\n * while (deq.length > 0 && nums[deq.last!] < nums[i]) {\n * deq.pop();\n * }\n *\n * // Add the current index to the end of the queue\n * deq.push(i);\n *\n * // Add the maximum value of the window to the results\n * if (i >= k - 1) {\n * result.push(nums[deq.first!]);\n * }\n * }\n *\n * return result;\n * }\n *\n * const nums = [1, 3, -1, -3, 5, 3, 6, 7];\n * const k = 3;\n * console.log(maxSlidingWindow(nums, k)); // [3, 3, 5, 5, 6, 7]\n */\nexport class Deque<E = any, R = any> extends LinearBase<E, R> {\n /**\n * The constructor initializes a Deque object with optional iterable of elements and options.\n * @param elements - An iterable object (such as an array or a Set) that contains the initial\n * elements to be added to the deque. It can also be an object with a `length` or `size` property\n * that represents the number of elements in the iterable object. If no elements are provided, an\n * empty deque\n * @param {DequeOptions} [options] - The `options` parameter is an optional object that can contain\n * configuration options for the deque. In this code, it is used to set the `bucketSize` option,\n * which determines the size of each bucket in the deque. If the `bucketSize` option is not provided\n * or is not a number\n */\n constructor(elements: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R> = [], options?: DequeOptions<E, R>) {\n super(options);\n\n if (options) {\n const { bucketSize } = options;\n if (typeof bucketSize === 'number') this._bucketSize = bucketSize;\n }\n\n let _size: number;\n if ('length' in elements) {\n if (elements.length instanceof Function) _size = elements.length();\n else _size = elements.length;\n } else {\n if (elements.size instanceof Function) _size = elements.size();\n else _size = elements.size;\n }\n\n this._bucketCount = calcMinUnitsRequired(_size, this._bucketSize) || 1;\n for (let i = 0; i < this._bucketCount; ++i) {\n this._buckets.push(new Array(this._bucketSize));\n }\n const needBucketNum = calcMinUnitsRequired(_size, this._bucketSize);\n this._bucketFirst = this._bucketLast = (this._bucketCount >> 1) - (needBucketNum >> 1);\n this._firstInBucket = this._lastInBucket = (this._bucketSize - (_size % this._bucketSize)) >> 1;\n this.pushMany(elements);\n }\n\n protected _bucketSize: number = 1 << 12;\n\n get bucketSize() {\n return this._bucketSize;\n }\n\n protected _bucketFirst = 0;\n\n get bucketFirst(): number {\n return this._bucketFirst;\n }\n\n protected _firstInBucket = 0;\n\n get firstInBucket(): number {\n return this._firstInBucket;\n }\n\n protected _bucketLast = 0;\n\n get bucketLast(): number {\n return this._bucketLast;\n }\n\n protected _lastInBucket = 0;\n\n get lastInBucket(): number {\n return this._lastInBucket;\n }\n\n protected _bucketCount = 0;\n\n get bucketCount(): number {\n return this._bucketCount;\n }\n\n protected _buckets: E[][] = [];\n\n get buckets() {\n return this._buckets;\n }\n\n protected _length = 0;\n\n get length() {\n return this._length;\n }\n\n /**\n * The function returns the first element in a collection if it exists, otherwise it returns\n * undefined.\n * @returns The first element of the collection, of type E, is being returned.\n */\n get first(): E | undefined {\n if (this._length === 0) return;\n return this._buckets[this._bucketFirst][this._firstInBucket];\n }\n\n /**\n * The last function returns the last element in the queue.\n * @return The last element in the array\n */\n get last(): E | undefined {\n if (this._length === 0) return;\n return this._buckets[this._bucketLast][this._lastInBucket];\n }\n\n /**\n * Time Complexity - Amortized O(1) (possible reallocation),\n * Space Complexity - O(n) (due to potential resizing).\n *\n * The push function adds an element to a data structure and reallocates memory if necessary.\n * @param {E} element - The `element` parameter represents the value that you want to add to the data\n * structure.\n * @returns The size of the data structure after the element has been pushed.\n */\n push(element: E): boolean {\n if (this._length) {\n if (this._lastInBucket < this._bucketSize - 1) {\n this._lastInBucket += 1;\n } else if (this._bucketLast < this._bucketCount - 1) {\n this._bucketLast += 1;\n this._lastInBucket = 0;\n } else {\n this._bucketLast = 0;\n this._lastInBucket = 0;\n }\n if (this._bucketLast === this._bucketFirst && this._lastInBucket === this._firstInBucket) this._reallocate();\n }\n this._length += 1;\n this._buckets[this._bucketLast][this._lastInBucket] = element;\n if (this._maxLen > 0 && this._length > this._maxLen) this.shift();\n return true;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `pop()` function removes and returns the last element from a data structure, updating the\n * internal state variables accordingly.\n * @returns The element that was removed from the data structure is being returned.\n */\n pop(): E | undefined {\n if (this._length === 0) return;\n const element = this._buckets[this._bucketLast][this._lastInBucket];\n if (this._length !== 1) {\n if (this._lastInBucket > 0) {\n this._lastInBucket -= 1;\n } else if (this._bucketLast > 0) {\n this._bucketLast -= 1;\n this._lastInBucket = this._bucketSize - 1;\n } else {\n this._bucketLast = this._bucketCount - 1;\n this._lastInBucket = this._bucketSize - 1;\n }\n }\n this._length -= 1;\n return element;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `shift()` function removes and returns the first element from a data structure, updating the\n * internal state variables accordingly.\n * @returns The element that is being removed from the beginning of the data structure is being\n * returned.\n */\n shift(): E | undefined {\n if (this._length === 0) return;\n const element = this._buckets[this._bucketFirst][this._firstInBucket];\n if (this._length !== 1) {\n if (this._firstInBucket < this._bucketSize - 1) {\n this._firstInBucket += 1;\n } else if (this._bucketFirst < this._bucketCount - 1) {\n this._bucketFirst += 1;\n this._firstInBucket = 0;\n } else {\n this._bucketFirst = 0;\n this._firstInBucket = 0;\n }\n }\n this._length -= 1;\n return element;\n }\n\n /**\n * Time Complexity: Amortized O(1)\n * Space Complexity: O(n)\n *\n * The `unshift` function adds an element to the beginning of an array-like data structure and\n * returns the new size of the structure.\n * @param {E} element - The `element` parameter represents the element that you want to add to the\n * beginning of the data structure.\n * @returns The size of the data structure after the element has been added.\n */\n unshift(element: E): boolean {\n if (this._length) {\n if (this._firstInBucket > 0) {\n this._firstInBucket -= 1;\n } else if (this._bucketFirst > 0) {\n this._bucketFirst -= 1;\n this._firstInBucket = this._bucketSize - 1;\n } else {\n this._bucketFirst = this._bucketCount - 1;\n this._firstInBucket = this._bucketSize - 1;\n }\n if (this._bucketFirst === this._bucketLast && this._firstInBucket === this._lastInBucket) this._reallocate();\n }\n this._length += 1;\n this._buckets[this._bucketFirst][this._firstInBucket] = element;\n if (this._maxLen > 0 && this._length > this._maxLen) this.pop();\n return true;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The function `pushMany` iterates over elements and pushes them into an array after applying a\n * transformation function if provided.\n * @param {IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>} elements - The `elements`\n * parameter in the `pushMany` function is expected to be an iterable containing elements of type `E`\n * or `R`. It can be either an `IterableWithSizeOrLength<E>` or an `IterableWithSizeOrLength<R>`. The\n * function iterates over each element\n * @returns The `pushMany` function is returning an array of boolean values, where each value\n * represents the result of calling the `push` method on the current object instance with the\n * corresponding element from the input `elements` iterable.\n */\n pushMany(elements: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) {\n ans.push(this.push(this.toElementFn(el as R)));\n } else {\n ans.push(this.push(el as E));\n }\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(k)\n * Space Complexity: O(k)\n *\n * The `unshiftMany` function in TypeScript iterates over elements and adds them to the beginning of\n * an array, optionally converting them using a provided function.\n * @param {IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R>} elements - The `elements`\n * parameter in the `unshiftMany` function is an iterable containing elements of type `E` or `R`. It\n * can be an array or any other iterable data structure that has a known size or length. The function\n * iterates over each element in the `elements` iterable and\n * @returns The `unshiftMany` function returns an array of boolean values indicating whether each\n * element was successfully added to the beginning of the array.\n */\n unshiftMany(elements: IterableWithSizeOrLength<E> | IterableWithSizeOrLength<R> = []) {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this.toElementFn) {\n ans.push(this.unshift(this.toElementFn(el as R)));\n } else {\n ans.push(this.unshift(el as E));\n }\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if the size of an object is equal to zero and returns a boolean value.\n * @returns A boolean value indicating whether the size of the object is 0 or not.\n */\n isEmpty(): boolean {\n return this._length === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear() function resets the state of the object by initializing all variables to their default\n * values.\n */\n clear(): void {\n this._buckets = [new Array(this._bucketSize)];\n this._bucketCount = 1;\n this._bucketFirst = this._bucketLast = this._length = 0;\n this._firstInBucket = this._lastInBucket = this._bucketSize >> 1;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `at` function retrieves an element at a specified position in an array-like data structure.\n * @param {number} pos - The `pos` parameter represents the position of the element that you want to\n * retrieve from the data structure. It is of type `number` and should be a valid index within the\n * range of the data structure.\n * @returns The element at the specified position in the data structure is being returned.\n */\n at(pos: number): E {\n rangeCheck(pos, 0, this._length - 1);\n const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);\n return this._buckets[bucketIndex][indexInBucket]!;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `setAt` function sets an element at a specific position in an array-like data structure.\n * @param {number} pos - The `pos` parameter represents the position at which the element needs to be\n * set. It is of type `number`.\n * @param {E} element - The `element` parameter is the value that you want to set at the specified\n * position in the data structure.\n */\n setAt(pos: number, element: E): boolean {\n rangeCheck(pos, 0, this._length - 1);\n const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);\n this._buckets[bucketIndex][indexInBucket] = element;\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `addAt` function inserts one or more elements at a specified position in an array-like data\n * structure.\n * @param {number} pos - The `pos` parameter represents the position at which the element(s) should\n * be inserted. It is of type `number`.\n * @param {E} element - The `element` parameter represents the element that you want to insert into\n * the array at the specified position.\n * @param [num=1] - The `num` parameter represents the number of times the `element` should be\n * inserted at the specified position (`pos`). By default, it is set to 1, meaning that the `element`\n * will be inserted once. However, you can provide a different value for `num` if you want\n * @returns The size of the array after the insertion is being returned.\n */\n addAt(pos: number, element: E, num = 1): boolean {\n const length = this._length;\n rangeCheck(pos, 0, length);\n if (pos === 0) {\n while (num--) this.unshift(element);\n } else if (pos === this._length) {\n while (num--) this.push(element);\n } else {\n const arr: E[] = [];\n for (let i = pos; i < this._length; ++i) {\n arr.push(this.at(i));\n }\n this.cut(pos - 1, true);\n for (let i = 0; i < num; ++i) this.push(element);\n for (let i = 0; i < arr.length; ++i) this.push(arr[i]);\n }\n return true;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `cut` function updates the state of the object based on the given position and returns the\n * updated size.\n * @param {number} pos - The `pos` parameter represents the position at which the string should be\n * cut. It is a number that indicates the index of the character where the cut should be made.\n * @param {boolean} isCutSelf - If true, the original deque will not be cut, and return a new deque\n * @returns The method is returning the updated size of the data structure.\n */\n cut(pos: number, isCutSelf = false): Deque<E> {\n if (isCutSelf) {\n if (pos < 0) {\n this.clear();\n return this;\n }\n const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);\n this._bucketLast = bucketIndex;\n this._lastInBucket = indexInBucket;\n this._length = pos + 1;\n return this;\n } else {\n const newDeque = this._createInstance({\n bucketSize: this._bucketSize,\n toElementFn: this._toElementFn,\n maxLen: this._maxLen\n });\n\n for (let i = 0; i <= pos; i++) {\n newDeque.push(this.at(i));\n }\n\n return newDeque;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `splice` function in TypeScript overrides the default behavior to remove and insert elements\n * in a Deque data structure while ensuring the starting position and delete count are within bounds.\n * @param {number} start - The `start` parameter in the `splice` method represents the index at which\n * to start changing the array. Items will be removed or added starting from this index.\n * @param {number} deleteCount - The `deleteCount` parameter in the `splice` method represents the\n * number of elements to remove from the array starting at the specified `start` index. If\n * `deleteCount` is not provided, it defaults to the number of elements from the `start` index to the\n * end of the array (`\n * @param {E[]} items - The `items` parameter in the `splice` method represents the elements that\n * will be inserted into the deque at the specified `start` index. These elements will be inserted in\n * place of the elements that are removed based on the `start` and `deleteCount` parameters.\n * @returns The `splice` method is returning the array `deletedElements` which contains the elements\n * that were removed from the Deque during the splice operation.\n */\n override splice(start: number, deleteCount: number = this._length - start, ...items: E[]): this {\n // Check whether the starting position is legal\n rangeCheck(start, 0, this._length);\n\n // Adjust the value of deleteCount\n if (deleteCount < 0) deleteCount = 0;\n if (start + deleteCount > this._length) deleteCount = this._length - start;\n\n // Save deleted elements\n const deletedElements = this._createInstance();\n\n // Add removed elements to the result\n for (let i = 0; i < deleteCount; i++) {\n deletedElements.push(this.at(start + i));\n }\n\n // Calculate the range that needs to be deleted\n const elementsAfter = [];\n for (let i = start + deleteCount; i < this._length; i++) {\n elementsAfter.push(this.at(i));\n }\n\n // Adjust the length of the current Deque\n this.cut(start - 1, true);\n\n for (const item of items) {\n this.push(item);\n }\n\n // Insert subsequent elements back\n for (const element of elementsAfter) {\n this.push(element);\n }\n\n return deletedElements;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1) or O(n)\n *\n * The `cutRest` function cuts the elements from a specified position in a deque and returns a new\n * deque with the cut elements.\n * @param {number} pos - The `pos` parameter represents the position from which to cut the Deque. It\n * is a number that indicates the index of the element in the Deque where the cut should start.\n * @param [isCutSelf=false] - isCutSelf is a boolean parameter that determines whether the original\n * Deque should be modified or a new Deque should be created. If isCutSelf is true, the original\n * Deque will be modified by cutting off elements starting from the specified position. If isCutSelf\n * is false, a new De\n * @returns The function `cutRest` returns either the modified original deque (`this`) or a new deque\n * (`newDeque`) depending on the value of the `isCutSelf` parameter.\n */\n cutRest(pos: number, isCutSelf = false): Deque<E> {\n if (isCutSelf) {\n if (pos < 0) {\n return this;\n }\n const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);\n this._bucketFirst = bucketIndex;\n this._firstInBucket = indexInBucket;\n this._length = this._length - pos;\n return this;\n } else {\n const newDeque = this._createInstance({\n bucketSize: this._bucketSize,\n toElementFn: this._toElementFn,\n maxLen: this._maxLen\n });\n if (pos < 0) pos = 0;\n for (let i = pos; i < this._length; i++) {\n newDeque.push(this.at(i));\n }\n\n return newDeque;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1) or O(n)\n *\n * The `deleteAt` function removes an element at a specified position in an array-like data\n * structure.\n * @param {number} pos - The `pos` parameter in the `deleteAt` function represents the position at\n * which an element needs to be deleted from the data structure. It is of type `number` and indicates\n * the index of the element to be deleted.\n * @returns The size of the data structure after the deletion operation is performed.\n */\n deleteAt(pos: number): E | undefined {\n rangeCheck(pos, 0, this._length - 1);\n\n let deleted: E | undefined;\n if (pos === 0) {\n //If it is the first element, use shift() directly\n return this.shift();\n } else if (pos === this._length - 1) {\n // If it is the last element, just use pop()\n deleted = this.last;\n this.pop();\n return deleted;\n } else {\n // Delete the middle element\n const length = this._length - 1;\n const { bucketIndex: targetBucket, indexInBucket: targetPointer } = this._getBucketAndPosition(pos);\n deleted = this._buckets[targetBucket][targetPointer];\n\n for (let i = pos; i < length; i++) {\n const { bucketIndex: curBucket, indexInBucket: curPointer } = this._getBucketAndPosition(i);\n const { bucketIndex: nextBucket, indexInBucket: nextPointer } = this._getBucketAndPosition(i + 1);\n this._buckets[curBucket][curPointer] = this._buckets[nextBucket][nextPointer];\n }\n\n // Remove last duplicate element\n this.pop();\n return deleted;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `delete` function removes all occurrences of a specified element from an array-like data\n * structure.\n * @param {E} element - The `element` parameter represents the element that you want to delete from\n * the data structure.\n * @returns The size of the data structure after the element has been deleted.\n */\n delete(element: E): boolean {\n const size = this._length;\n if (size === 0) return false;\n let i = 0;\n let index = 0;\n while (i < size) {\n const oldElement = this.at(i);\n if (oldElement !== element) {\n this.setAt(index, oldElement!);\n index += 1;\n }\n i += 1;\n }\n this.cut(index - 1, true);\n return true;\n }\n\n // /**\n // * Time Complexity: O(n)\n // * Space Complexity: O(1)\n // *\n // * This function overrides the indexOf method to search for an element within a custom data\n // * structure.\n // * @param {E} searchElement - The `searchElement` parameter is the element that you are searching for\n // * within the data structure. The `indexOf` method will return the index of the first occurrence of\n // * this element within the data structure.\n // * @param {number} [fromIndex=0] - The `fromIndex` parameter in the `indexOf` method specifies the\n // * index at which to start searching for the `searchElement` within the data structure. If provided,\n // * the search will begin at this index instead of the beginning of the data structure.\n // * @returns The indexOf method is returning the index of the searchElement if it is found in the data\n // * structure, or -1 if the searchElement is not found.\n // */\n // override indexOf(searchElement: E, fromIndex: number = 0): number {\n // let index = fromIndex;\n // let bucketIndex = this._bucketFirst;\n // let indexInBucket = this._firstInBucket + fromIndex;\n //\n // for (let i = 0; i < this._length; i++) {\n // if (this._buckets[bucketIndex][indexInBucket] === searchElement) {\n // return index;\n // }\n // index++;\n // indexInBucket++;\n // if (indexInBucket >= this._bucketSize) {\n // bucketIndex++;\n // indexInBucket = 0;\n // }\n // if (bucketIndex >= this._bucketCount) {\n // bucketIndex = 0;\n // }\n // }\n // return -1;\n // }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The reverse() function reverses the order of the buckets and the elements within each bucket in a\n * data structure.\n * @returns The reverse() method is returning the object itself (this) after performing the reverse\n * operation on the buckets and updating the relevant properties.\n */\n reverse(): this {\n this._buckets.reverse().forEach(function (bucket) {\n bucket.reverse();\n });\n const { _bucketFirst, _bucketLast, _firstInBucket, _lastInBucket } = this;\n this._bucketFirst = this._bucketCount - _bucketLast - 1;\n this._bucketLast = this._bucketCount - _bucketFirst - 1;\n this._firstInBucket = this._bucketSize - _lastInBucket - 1;\n this._lastInBucket = this._bucketSize - _firstInBucket - 1;\n return this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `unique()` function removes duplicate elements from an array-like data structure and returns\n * the number of unique elements.\n * @returns The size of the modified array is being returned.\n */\n unique(): this {\n if (this._length <= 1) {\n return this;\n }\n let index = 1;\n let prev = this.at(0);\n for (let i = 1; i < this._length; ++i) {\n const cur = this.at(i);\n if (cur !== prev) {\n prev = cur;\n this.setAt(index++, cur);\n }\n }\n this.cut(index - 1, true);\n return this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `shrinkToFit` function reorganizes the elements in an array-like data structure to minimize\n * memory usage.\n * @returns Nothing is being returned. The function is using the `return` statement to exit early if\n * `this._length` is 0, but it does not return any value.\n */\n shrinkToFit(): void {\n if (this._length === 0) return;\n const newBuckets = [];\n if (this._bucketFirst === this._bucketLast) return;\n else if (this._bucketFirst < this._bucketLast) {\n for (let i = this._bucketFirst; i <= this._bucketLast; ++i) {\n newBuckets.push(this._buckets[i]);\n }\n } else {\n for (let i = this._bucketFirst; i < this._bucketCount; ++i) {\n newBuckets.push(this._buckets[i]);\n }\n for (let i = 0; i <= this._bucketLast; ++i) {\n newBuckets.push(this._buckets[i]);\n }\n }\n this._bucketFirst = 0;\n this._bucketLast = newBuckets.length - 1;\n this._buckets = newBuckets;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `clone()` function returns a new instance of the `Deque` class with the same elements and\n * bucket size as the original instance.\n * @returns The `clone()` method is returning a new instance of the `Deque` class with the same\n * elements as the original deque (`this`) and the same bucket size.\n */\n clone(): this {\n return new Deque<E, R>(this, {\n bucketSize: this.bucketSize,\n toElementFn: this.toElementFn,\n maxLen: this._maxLen\n }) as this;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new deque containing elements from the original deque that satisfy\n * a given predicate function.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * the current element being iterated over, the index of the current element, and the deque itself.\n * It should return a boolean value indicating whether the element should be included in the filtered\n * deque or not.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `predicate` function. If `thisArg` is\n * @returns The `filter` method is returning a new `Deque` object that contains the elements that\n * satisfy the given predicate function.\n */\n filter(predicate: ElementCallback<E, R, boolean>, thisArg?: any): Deque<E, R> {\n const newDeque = this._createInstance({\n bucketSize: this._bucketSize,\n toElementFn: this.toElementFn,\n maxLen: this._maxLen\n });\n let index = 0;\n for (const el of this) {\n if (predicate.call(thisArg, el, index, this)) {\n newDeque.push(el);\n }\n index++;\n }\n return newDeque;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function takes a callback function and applies it to each element in the deque,\n * returning a new deque with the results.\n * @param callback - The callback parameter is a function that will be called for each element in the\n * deque. It takes three arguments: the current element, the index of the element, and the deque\n * itself. It should return a value of type EM.\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to\n * transform the raw element (`RM`) into a new element (`EM`) before adding it to the new deque. If\n * provided, this function will be called for each raw element in the original deque.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new Deque object with elements of type EM and raw elements of type RM.\n */\n map<EM, RM>(callback: ElementCallback<E, R, EM>, toElementFn?: (rawElement: RM) => EM, thisArg?: any): Deque<EM, RM> {\n const newDeque = new Deque<EM, RM>([], { bucketSize: this._bucketSize, toElementFn, maxLen: this._maxLen });\n let index = 0;\n for (const el of this) {\n newDeque.push(callback.call(thisArg, el, index, this));\n index++;\n }\n return newDeque;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The above function is an implementation of the iterator protocol in TypeScript, allowing the\n * object to be iterated over using a for...of loop.\n */\n protected *_getIterator(): IterableIterator<E> {\n for (let i = 0; i < this._length; ++i) {\n yield this.at(i);\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `_reallocate` function reallocates the buckets in an array, adding new buckets if needed.\n * @param {number} [needBucketNum] - The `needBucketNum` parameter is an optional number that\n * specifies the number of new buckets needed. If not provided, it will default to half of the\n * current bucket count (`this._bucketCount >> 1`) or 1 if the current bucket count is less than 2.\n */\n protected _reallocate(needBucketNum?: number) {\n const newBuckets = [];\n const addBucketNum = needBucketNum || this._bucketCount >> 1 || 1;\n for (let i = 0; i < addBucketNum; ++i) {\n newBuckets[i] = new Array(this._bucketSize);\n }\n for (let i = this._bucketFirst; i < this._bucketCount; ++i) {\n newBuckets[newBuckets.length] = this._buckets[i];\n }\n for (let i = 0; i < this._bucketLast; ++i) {\n newBuckets[newBuckets.length] = this._buckets[i];\n }\n newBuckets[newBuckets.length] = [...this._buckets[this._bucketLast]];\n this._bucketFirst = addBucketNum;\n this._bucketLast = newBuckets.length - 1;\n for (let i = 0; i < addBucketNum; ++i) {\n newBuckets[newBuckets.length] = new Array(this._bucketSize);\n }\n this._buckets = newBuckets;\n this._bucketCount = newBuckets.length;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function calculates the bucket index and index within the bucket based on the given position.\n * @param {number} pos - The `pos` parameter represents the position within the data structure. It is\n * a number that indicates the index or position of an element within the structure.\n * @returns an object with two properties: \"bucketIndex\" and \"indexInBucket\".\n */\n protected _getBucketAndPosition(pos: number) {\n let bucketIndex: number;\n let indexInBucket: number;\n\n const overallIndex = this._firstInBucket + pos;\n bucketIndex = this._bucketFirst + Math.floor(overallIndex / this._bucketSize);\n\n if (bucketIndex >= this._bucketCount) {\n bucketIndex -= this._bucketCount;\n }\n\n indexInBucket = ((overallIndex + 1) % this._bucketSize) - 1;\n if (indexInBucket < 0) {\n indexInBucket = this._bucketSize - 1;\n }\n\n return { bucketIndex, indexInBucket };\n }\n\n /**\n * The function `_createInstance` returns a new instance of the `Deque` class with the specified\n * options.\n * @param [options] - The `options` parameter in the `_createInstance` method is of type\n * `DequeOptions<E, R>`, which is an optional parameter that allows you to pass additional\n * configuration options when creating a new instance of the `Deque` class.\n * @returns An instance of the `Deque` class with an empty array and the provided options, casted as\n * `this`.\n */\n protected override _createInstance(options?: DequeOptions<E, R>): this {\n return new Deque<E, R>([], options) as this;\n }\n\n /**\n * This function returns an iterator that iterates over elements in reverse order.\n */\n protected *_getReverseIterator(): IterableIterator<E> {\n for (let i = this._length - 1; i > -1; i--) {\n yield this.at(i);\n }\n }\n}\n","/**\n * data-structure-typed\n * @author Kirk Qi\n * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>\n * @license MIT License\n */\n\nimport type { Comparator, DFSOrderPattern, ElementCallback, HeapOptions } from '../../types';\nimport { IterableElementBase } from '../base';\n\n/**\n * 1. Complete Binary Tree: Heaps are typically complete binary trees, meaning every level is fully filled except possibly for the last level, which has nodes as far left as possible.\n * 2. Heap Properties: Each node in a heap follows a specific order property, which varies depending on the type of heap:\n * Max Heap: The value of each parent node is greater than or equal to the value of its children.\n * Min Heap: The value of each parent node is less than or equal to the value of its children.\n * 3. Root Node Access: In a heap, the largest element (in a max heap) or the smallest element (in a min heap) is always at the root of the tree.\n * 4. Efficient Insertion and Deletion: Due to its structure, a heap allows for insertion and deletion operations in logarithmic time (O(log n)).\n * 5. Managing Dynamic Data Sets: Heaps effectively manage dynamic data sets, especially when frequent access to the largest or smallest elements is required.\n * 6. Non-linear Search: While a heap allows rapid access to its largest or smallest element, it is less efficient for other operations, such as searching for a specific element, as it is not designed for these tasks.\n * 7. Efficient Sorting Algorithms: For example, heap sort. Heap sort uses the properties of a heap to sort elements.\n * 8. Graph Algorithms: Such as Dijkstra's shortest path algorithm and Prime's minimum-spanning tree algorithm, which use heaps to improve performance.\n * @example\n * // Use Heap to sort an array\n * function heapSort(arr: number[]): number[] {\n * const heap = new Heap<number>(arr, { comparator: (a, b) => a - b });\n * const sorted: number[] = [];\n * while (!heap.isEmpty()) {\n * sorted.push(heap.poll()!); // Poll minimum element\n * }\n * return sorted;\n * }\n *\n * const array = [5, 3, 8, 4, 1, 2];\n * console.log(heapSort(array)); // [1, 2, 3, 4, 5, 8]\n * @example\n * // Use Heap to solve top k problems\n * function topKElements(arr: number[], k: number): number[] {\n * const heap = new Heap<number>([], { comparator: (a, b) => b - a }); // Max heap\n * arr.forEach(num => {\n * heap.add(num);\n * if (heap.size > k) heap.poll(); // Keep the heap size at K\n * });\n * return heap.toArray();\n * }\n *\n * const numbers = [10, 30, 20, 5, 15, 25];\n * console.log(topKElements(numbers, 3)); // [15, 10, 5]\n * @example\n * // Use Heap to merge sorted sequences\n * function mergeSortedSequences(sequences: number[][]): number[] {\n * const heap = new Heap<{ value: number; seqIndex: number; itemIndex: number }>([], {\n * comparator: (a, b) => a.value - b.value // Min heap\n * });\n *\n * // Initialize heap\n * sequences.forEach((seq, seqIndex) => {\n * if (seq.length) {\n * heap.add({ value: seq[0], seqIndex, itemIndex: 0 });\n * }\n * });\n *\n * const merged: number[] = [];\n * while (!heap.isEmpty()) {\n * const { value, seqIndex, itemIndex } = heap.poll()!;\n * merged.push(value);\n *\n * if (itemIndex + 1 < sequences[seqIndex].length) {\n * heap.add({\n * value: sequences[seqIndex][itemIndex + 1],\n * seqIndex,\n * itemIndex: itemIndex + 1\n * });\n * }\n * }\n *\n * return merged;\n * }\n *\n * const sequences = [\n * [1, 4, 7],\n * [2, 5, 8],\n * [3, 6, 9]\n * ];\n * console.log(mergeSortedSequences(sequences)); // [1, 2, 3, 4, 5, 6, 7, 8, 9]\n * @example\n * // Use Heap to dynamically maintain the median\n * class MedianFinder {\n * private low: MaxHeap<number>; // Max heap, stores the smaller half\n * private high: MinHeap<number>; // Min heap, stores the larger half\n *\n * constructor() {\n * this.low = new MaxHeap<number>([]);\n * this.high = new MinHeap<number>([]);\n * }\n *\n * addNum(num: number): void {\n * if (this.low.isEmpty() || num <= this.low.peek()!) this.low.add(num);\n * else this.high.add(num);\n *\n * // Balance heaps\n * if (this.low.size > this.high.size + 1) this.high.add(this.low.poll()!);\n * else if (this.high.size > this.low.size) this.low.add(this.high.poll()!);\n * }\n *\n * findMedian(): number {\n * if (this.low.size === this.high.size) return (this.low.peek()! + this.high.peek()!) / 2;\n * return this.low.peek()!;\n * }\n * }\n *\n * const medianFinder = new MedianFinder();\n * medianFinder.addNum(10);\n * console.log(medianFinder.findMedian()); // 10\n * medianFinder.addNum(20);\n * console.log(medianFinder.findMedian()); // 15\n * medianFinder.addNum(30);\n * console.log(medianFinder.findMedian()); // 20\n * medianFinder.addNum(40);\n * console.log(medianFinder.findMedian()); // 25\n * medianFinder.addNum(50);\n * console.log(medianFinder.findMedian()); // 30\n * @example\n * // Use Heap for load balancing\n * function loadBalance(requests: number[], servers: number): number[] {\n * const serverHeap = new Heap<{ id: number; load: number }>([], { comparator: (a, b) => a.load - b.load }); // min heap\n * const serverLoads = new Array(servers).fill(0);\n *\n * for (let i = 0; i < servers; i++) {\n * serverHeap.add({ id: i, load: 0 });\n * }\n *\n * requests.forEach(req => {\n * const server = serverHeap.poll()!;\n * serverLoads[server.id] += req;\n * server.load += req;\n * serverHeap.add(server); // The server after updating the load is re-entered into the heap\n * });\n *\n * return serverLoads;\n * }\n *\n * const requests = [5, 2, 8, 3, 7];\n * console.log(loadBalance(requests, 3)); // [12, 8, 5]\n * @example\n * // Use Heap to schedule tasks\n * type Task = [string, number];\n *\n * function scheduleTasks(tasks: Task[], machines: number): Map<number, Task[]> {\n * const machineHeap = new Heap<{ id: number; load: number }>([], { comparator: (a, b) => a.load - b.load }); // Min heap\n * const allocation = new Map<number, Task[]>();\n *\n * // Initialize the load on each machine\n * for (let i = 0; i < machines; i++) {\n * machineHeap.add({ id: i, load: 0 });\n * allocation.set(i, []);\n * }\n *\n * // Assign tasks\n * tasks.forEach(([task, load]) => {\n * const machine = machineHeap.poll()!;\n * allocation.get(machine.id)!.push([task, load]);\n * machine.load += load;\n * machineHeap.add(machine); // The machine after updating the load is re-entered into the heap\n * });\n *\n * return allocation;\n * }\n *\n * const tasks: Task[] = [\n * ['Task1', 3],\n * ['Task2', 1],\n * ['Task3', 2],\n * ['Task4', 5],\n * ['Task5', 4]\n * ];\n * const expectedMap = new Map<number, Task[]>();\n * expectedMap.set(0, [\n * ['Task1', 3],\n * ['Task4', 5]\n * ]);\n * expectedMap.set(1, [\n * ['Task2', 1],\n * ['Task3', 2],\n * ['Task5', 4]\n * ]);\n * console.log(scheduleTasks(tasks, 2)); // expectedMap\n */\nexport class Heap<E = any, R = any> extends IterableElementBase<E, R> {\n /**\n * The constructor initializes a heap data structure with optional elements and options.\n * @param elements - The `elements` parameter is an iterable object that contains the initial\n * elements to be added to the heap.\n * It is an optional parameter, and if not provided, the heap will\n * be initialized as empty.\n * @param [options] - The `options` parameter is an optional object that can contain additional\n * configuration options for the heap.\n * In this case, it is used to specify a custom comparator\n * function for comparing elements in the heap.\n * The comparator function is used to determine the\n * order of elements in the heap.\n */\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: HeapOptions<E, R>) {\n super(options);\n\n if (options) {\n const { comparator } = options;\n if (comparator) this._comparator = comparator;\n }\n\n this.addMany(elements);\n }\n\n protected _elements: E[] = [];\n\n /**\n * The function returns an array of elements.\n * @returns The element array is being returned.\n */\n get elements(): E[] {\n return this._elements;\n }\n\n /**\n * Get the size (number of elements) of the heap.\n */\n get size(): number {\n return this.elements.length;\n }\n\n /**\n * Get the last element in the heap, which is not necessarily a leaf node.\n * @returns The last element or undefined if the heap is empty.\n */\n get leaf(): E | undefined {\n return this.elements[this.size - 1] ?? undefined;\n }\n\n /**\n * Static method that creates a binary heap from an array of elements and a comparison function.\n * @returns A new Heap instance.\n * @param elements\n * @param options\n */\n static heapify<E = any, R = any>(elements: Iterable<E>, options: HeapOptions<E, R>): Heap<E> {\n return new Heap<E>(elements, options);\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The add function pushes an element into an array and then triggers a bubble-up operation.\n * @param {E} element - The `element` parameter represents the element that you want to add to the\n * data structure.\n * @returns The `add` method is returning a boolean value, which is the result of calling the\n * `_bubbleUp` method with the index `this.elements.length - 1` as an argument.\n */\n add(element: E): boolean {\n this._elements.push(element as E);\n return this._bubbleUp(this.elements.length - 1);\n }\n\n /**\n * Time Complexity: O(k log n)\n * Space Complexity: O(1)\n *\n * The `addMany` function iterates over elements and adds them to a collection, returning an array of\n * boolean values indicating success or failure.\n * @param {Iterable<E> | Iterable<R>} elements - The `elements` parameter in the `addMany` method is\n * an iterable containing elements of type `E` or `R`. The method iterates over each element in the\n * iterable and adds them to the data structure. If a transformation function `_toElementFn` is\n * provided, it transforms the element\n * @returns The `addMany` method returns an array of boolean values indicating whether each element\n * in the input iterable was successfully added to the data structure.\n */\n addMany(elements: Iterable<E> | Iterable<R>): boolean[] {\n const ans: boolean[] = [];\n for (const el of elements) {\n if (this._toElementFn) {\n ans.push(this.add(this._toElementFn(el as R)));\n continue;\n }\n ans.push(this.add(el as E));\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Remove and return the top element (the smallest or largest element) from the heap.\n * @returns The top element or undefined if the heap is empty.\n */\n poll(): E | undefined {\n if (this.elements.length === 0) return;\n const value = this.elements[0];\n const last = this.elements.pop()!;\n if (this.elements.length) {\n this.elements[0] = last;\n this._sinkDown(0, this.elements.length >> 1);\n }\n return value;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Peek at the top element of the heap without removing it.\n * @returns The top element or undefined if the heap is empty.\n */\n peek(): E | undefined {\n return this.elements[0];\n }\n\n /**\n * Check if the heap is empty.\n * @returns True if the heap is empty, otherwise false.\n */\n isEmpty(): boolean {\n return this.size === 0;\n }\n\n /**\n * Reset the elements of the heap. Make the elements empty.\n */\n clear(): void {\n this._elements = [];\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * Clear and add elements of the heap\n * @param elements\n */\n refill(elements: E[]): boolean[] {\n this._elements = elements;\n return this.fix();\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * Use a comparison function to check whether a binary heap contains a specific element.\n * @param element - the element to check.\n * @returns Returns true if the specified element is contained; otherwise, returns false.\n */\n override has(element: E): boolean {\n return this.elements.includes(element);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The `delete` function removes an element from an array-like data structure, maintaining the order\n * and structure of the remaining elements.\n * @param {E} element - The `element` parameter represents the element that you want to delete from\n * the array `this.elements`.\n * @returns The `delete` function is returning a boolean value. It returns `true` if the element was\n * successfully deleted from the array, and `false` if the element was not found in the array.\n */\n delete(element: E): boolean {\n const index = this.elements.indexOf(element);\n if (index < 0) return false;\n if (index === 0) {\n this.poll();\n } else if (index === this.elements.length - 1) {\n this.elements.pop();\n } else {\n this.elements.splice(index, 1, this.elements.pop()!);\n this._bubbleUp(index);\n this._sinkDown(index, this.elements.length >> 1);\n }\n return true;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * Depth-first search (DFS) method, different traversal orders can be selected。\n * @param order - Traverse order parameter: 'IN' (in-order), 'PRE' (pre-order) or 'POST' (post-order).\n * @returns An array containing elements traversed in the specified order.\n */\n dfs(order: DFSOrderPattern = 'PRE'): E[] {\n const result: E[] = [];\n\n // Auxiliary recursive function, traverses the binary heap according to the traversal order\n const _dfs = (index: number) => {\n const left = 2 * index + 1,\n right = left + 1;\n if (index < this.size) {\n if (order === 'IN') {\n _dfs(left);\n result.push(this.elements[index]);\n _dfs(right);\n } else if (order === 'PRE') {\n result.push(this.elements[index]);\n _dfs(left);\n _dfs(right);\n } else if (order === 'POST') {\n _dfs(left);\n _dfs(right);\n result.push(this.elements[index]);\n }\n }\n };\n\n _dfs(0); // Traverse starting from the root node\n\n return result;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * Clone the heap, creating a new heap with the same elements.\n * @returns A new Heap instance containing the same elements.\n */\n clone(): Heap<E, R> {\n return new Heap<E, R>(this, { comparator: this.comparator, toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * Sort the elements in the heap and return them as an array.\n * @returns An array containing the elements sorted in ascending order.\n */\n sort(): E[] {\n const visitedNode: E[] = [];\n const cloned = new Heap<E, R>(this, { comparator: this.comparator });\n while (cloned.size !== 0) {\n const top = cloned.poll();\n if (top !== undefined) visitedNode.push(top);\n }\n return visitedNode;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * Fix the entire heap to maintain heap properties.\n */\n fix(): boolean[] {\n const results: boolean[] = [];\n for (let i = Math.floor(this.size / 2); i >= 0; i--) results.push(this._sinkDown(i, this.elements.length >> 1));\n return results;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new Heap object containing elements that pass a given callback\n * function.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: the current element, the index of the current element, and the\n * heap itself. The callback function should return a boolean value indicating whether the current\n * element should be included in the filtered list\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `Heap` object that contains the elements that pass\n * the filter condition specified by the `callback` function.\n */\n filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): Heap<E, R> {\n const filteredList = new Heap<E, R>([], { toElementFn: this.toElementFn, comparator: this.comparator });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredList.add(current);\n }\n index++;\n }\n return filteredList;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function creates a new heap by applying a callback function to each element of the\n * original heap.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: `el` (the current element), `index` (the index of the current\n * element), and `this` (the heap itself). The callback function should return a value of\n * @param comparator - The `comparator` parameter is a function that defines the order of the\n * elements in the heap. It takes two elements `a` and `b` as arguments and returns a negative number\n * if `a` should be placed before `b`, a positive number if `a` should be placed after\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that converts the raw\n * element `RR` to the desired type `T`. It takes a single argument `rawElement` of type `RR` and\n * returns a value of type `T`. This function is used to transform the elements of the original\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `Heap` class with the mapped elements.\n */\n map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n comparator: Comparator<EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): Heap<EM, RM> {\n const mappedHeap: Heap<EM, RM> = new Heap<EM, RM>([], { comparator, toElementFn });\n let index = 0;\n for (const el of this) {\n mappedHeap.add(callback.call(thisArg, el, index, this));\n index++;\n }\n return mappedHeap;\n }\n\n protected _DEFAULT_COMPARATOR = (a: E, b: E): number => {\n if (typeof a === 'object' || typeof b === 'object') {\n throw TypeError(\n `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`\n );\n }\n if (a > b) return 1;\n if (a < b) return -1;\n return 0;\n };\n\n protected _comparator: Comparator<E> = this._DEFAULT_COMPARATOR;\n\n /**\n * The function returns the value of the _comparator property.\n * @returns The `_comparator` property is being returned.\n */\n get comparator() {\n return this._comparator;\n }\n\n /**\n * The function `_getIterator` returns an iterable iterator for the elements in the class.\n */\n protected *_getIterator(): IterableIterator<E> {\n for (const element of this.elements) {\n yield element;\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Float operation to maintain heap properties after adding an element.\n * @param index - The index of the newly added element.\n */\n protected _bubbleUp(index: number): boolean {\n const element = this.elements[index];\n while (index > 0) {\n const parent = (index - 1) >> 1;\n const parentItem = this.elements[parent];\n if (this.comparator(parentItem, element) <= 0) break;\n this.elements[index] = parentItem;\n index = parent;\n }\n this.elements[index] = element;\n return true;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Sinking operation to maintain heap properties after removing the top element.\n * @param index - The index from which to start sinking.\n * @param halfLength\n */\n protected _sinkDown(index: number, halfLength: number): boolean {\n const element = this.elements[index];\n while (index < halfLength) {\n let left = (index << 1) | 1;\n const right = left + 1;\n let minItem = this.elements[left];\n if (right < this.elements.length && this.comparator(minItem, this.elements[right]) > 0) {\n left = right;\n minItem = this.elements[right];\n }\n if (this.comparator(minItem, element) >= 0) break;\n this.elements[index] = minItem;\n index = left;\n }\n this.elements[index] = element;\n return true;\n }\n}\n\nexport class FibonacciHeapNode<E> {\n element: E;\n degree: number;\n left?: FibonacciHeapNode<E>;\n right?: FibonacciHeapNode<E>;\n child?: FibonacciHeapNode<E>;\n parent?: FibonacciHeapNode<E>;\n marked: boolean;\n\n /**\n * The constructor function initializes an object with an element and a degree, and sets the marked\n * property to false.\n * @param {E} element - The \"element\" parameter represents the value or data that will be stored in\n * the node of a data structure. It can be any type of data, such as a number, string, object, or\n * even another data structure.\n * @param [degree=0] - The degree parameter represents the degree of the element in a data structure\n * called a Fibonacci heap. The degree of a node is the number of children it has. By default, the\n * degree is set to 0 when a new node is created.\n */\n constructor(element: E, degree = 0) {\n this.element = element;\n this.degree = degree;\n this.marked = false;\n }\n}\n\nexport class FibonacciHeap<E> {\n /**\n * The constructor function initializes a FibonacciHeap object with an optional comparator function.\n * @param [comparator] - The `comparator` parameter is an optional argument that represents a\n * function used to compare elements in the FibonacciHeap. If a comparator function is provided, it\n * will be used to determine the order of elements in the heap. If no comparator function is\n * provided, a default comparator function will be used.\n */\n constructor(comparator?: Comparator<E>) {\n this.clear();\n this._comparator = comparator || this._defaultComparator;\n\n if (typeof this.comparator !== 'function') {\n throw new Error('FibonacciHeap constructor: given comparator should be a function.');\n }\n }\n\n protected _root?: FibonacciHeapNode<E>;\n\n /**\n * The function returns the root node of a Fibonacci heap.\n * @returns The method is returning either a FibonacciHeapNode object or undefined.\n */\n get root(): FibonacciHeapNode<E> | undefined {\n return this._root;\n }\n\n protected _size = 0;\n\n /**\n * The function returns the size of an object.\n * @returns The size of the object, which is a number.\n */\n get size(): number {\n return this._size;\n }\n\n protected _min?: FibonacciHeapNode<E>;\n\n /**\n * The function returns the minimum node in a Fibonacci heap.\n * @returns The method is returning the minimum node of the Fibonacci heap, which is of type\n * `FibonacciHeapNode<E>`. If there is no minimum node, it will return `undefined`.\n */\n get min(): FibonacciHeapNode<E> | undefined {\n return this._min;\n }\n\n protected _comparator: Comparator<E>;\n\n /**\n * The function returns the comparator used for comparing elements.\n * @returns The `_comparator` property of the object.\n */\n get comparator(): Comparator<E> {\n return this._comparator;\n }\n\n /**\n * Get the size (number of elements) of the heap.\n * @returns {number} The size of the heap. Returns 0 if the heap is empty. Returns -1 if the heap is invalid.\n */\n clear(): void {\n this._root = undefined;\n this._min = undefined;\n this._size = 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Insert an element into the heap and maintain the heap properties.\n * @param element\n * @returns {FibonacciHeap<E>} FibonacciHeap<E> - The heap itself.\n */\n add(element: E): FibonacciHeap<E> {\n return this.push(element);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Insert an element into the heap and maintain the heap properties.\n * @param element\n * @returns {FibonacciHeap<E>} FibonacciHeap<E> - The heap itself.\n */\n push(element: E): FibonacciHeap<E> {\n const node = this.createNode(element);\n node.left = node;\n node.right = node;\n this.mergeWithRoot(node);\n\n if (!this.min || this.comparator(node.element, this.min.element) <= 0) {\n this._min = node;\n }\n\n this._size++;\n return this;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Peek at the top element of the heap without removing it.\n * @returns The top element or undefined if the heap is empty.\n * @protected\n */\n peek(): E | undefined {\n return this.min ? this.min.element : undefined;\n }\n\n /**\n * Time Complexity: O(n), where n is the number of elements in the linked list.\n * Space Complexity: O(1)\n *\n * Get the size (number of elements) of the heap.\n * @param {FibonacciHeapNode<E>} head - The head of the linked list.\n * @protected\n * @returns FibonacciHeapNode<E>[] - An array containing the elements of the linked list.\n */\n consumeLinkedList(head?: FibonacciHeapNode<E>): FibonacciHeapNode<E>[] {\n const elements: FibonacciHeapNode<E>[] = [];\n if (!head) return elements;\n\n let node: FibonacciHeapNode<E> | undefined = head;\n let flag = false;\n\n while (true) {\n if (node === head && flag) break;\n else if (node === head) flag = true;\n\n if (node) {\n elements.push(node);\n node = node.right;\n }\n }\n\n return elements;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * @param parent\n * @param node\n */\n mergeWithChild(parent: FibonacciHeapNode<E>, node: FibonacciHeapNode<E>): void {\n if (!parent.child) {\n parent.child = node;\n } else {\n node.right = parent.child.right;\n node.left = parent.child;\n parent.child.right!.left = node;\n parent.child.right = node;\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Remove and return the top element (the smallest or largest element) from the heap.\n * @returns The top element or undefined if the heap is empty.\n */\n poll(): E | undefined {\n return this.pop();\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * Remove and return the top element (the smallest or largest element) from the heap.\n * @returns The top element or undefined if the heap is empty.\n */\n pop(): E | undefined {\n if (this._size === 0) return undefined;\n\n const z = this.min!;\n if (z.child) {\n const elements = this.consumeLinkedList(z.child);\n for (const node of elements) {\n this.mergeWithRoot(node);\n node.parent = undefined;\n }\n }\n\n this.removeFromRoot(z);\n\n if (z === z.right) {\n this._min = undefined;\n this._root = undefined;\n } else {\n this._min = z.right;\n this._consolidate();\n }\n\n this._size--;\n\n return z.element;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * merge two heaps. The heap that is merged will be cleared. The heap that is merged into will remain.\n * @param heapToMerge\n */\n merge(heapToMerge: FibonacciHeap<E>): void {\n if (heapToMerge.size === 0) {\n return; // Nothing to merge\n }\n\n // Merge the root lists of the two heaps\n if (this.root && heapToMerge.root) {\n const thisRoot = this.root;\n const otherRoot = heapToMerge.root;\n\n const thisRootRight = thisRoot.right!;\n const otherRootLeft = otherRoot.left!;\n\n thisRoot.right = otherRoot;\n otherRoot.left = thisRoot;\n\n thisRootRight.left = otherRootLeft;\n otherRootLeft.right = thisRootRight;\n }\n\n // Update the minimum node\n if (!this.min || (heapToMerge.min && this.comparator(heapToMerge.min.element, this.min.element) < 0)) {\n this._min = heapToMerge.min;\n }\n\n // Update the size\n this._size += heapToMerge.size;\n\n // Clear the heap that was merged\n heapToMerge.clear();\n }\n\n /**\n * Create a new node.\n * @param element\n * @protected\n */\n createNode(element: E): FibonacciHeapNode<E> {\n return new FibonacciHeapNode<E>(element);\n }\n\n /**\n * Default comparator function used by the heap.\n * @param {E} a\n * @param {E} b\n * @protected\n */\n protected _defaultComparator(a: E, b: E): number {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Merge the given node with the root list.\n * @param node - The node to be merged.\n */\n protected mergeWithRoot(node: FibonacciHeapNode<E>): void {\n if (!this.root) {\n this._root = node;\n } else {\n node.right = this.root.right;\n node.left = this.root;\n this.root.right!.left = node;\n this.root.right = node;\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Remove and return the top element (the smallest or largest element) from the heap.\n * @param node - The node to be removed.\n * @protected\n */\n protected removeFromRoot(node: FibonacciHeapNode<E>): void {\n if (this.root === node) this._root = node.right;\n if (node.left) node.left.right = node.right;\n if (node.right) node.right.left = node.left;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * Remove and return the top element (the smallest or largest element) from the heap.\n * @param y\n * @param x\n * @protected\n */\n protected _link(y: FibonacciHeapNode<E>, x: FibonacciHeapNode<E>): void {\n this.removeFromRoot(y);\n y.left = y;\n y.right = y;\n this.mergeWithChild(x, y);\n x.degree++;\n y.parent = x;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * Remove and return the top element (the smallest or largest element) from the heap.\n * @protected\n */\n protected _consolidate(): void {\n const A: (FibonacciHeapNode<E> | undefined)[] = new Array(this._size);\n const elements = this.consumeLinkedList(this.root);\n let x: FibonacciHeapNode<E> | undefined,\n y: FibonacciHeapNode<E> | undefined,\n d: number,\n t: FibonacciHeapNode<E> | undefined;\n\n for (const node of elements) {\n x = node;\n d = x.degree;\n\n while (A[d]) {\n y = A[d] as FibonacciHeapNode<E>;\n\n if (this.comparator(x.element, y.element) > 0) {\n t = x;\n x = y;\n y = t;\n }\n\n this._link(y, x);\n A[d] = undefined;\n d++;\n }\n\n A[d] = x;\n }\n\n for (let i = 0; i < this._size; i++) {\n if (A[i] && this.comparator(A[i]!.element, this.min!.element) <= 0) {\n this._min = A[i]!;\n }\n }\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Kirk Qi\n * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>\n * @license MIT License\n */\nimport type { Comparator, ElementCallback, HeapOptions } from '../../types';\nimport { Heap } from './heap';\n\n/**\n * 1. Complete Binary Tree: Heaps are typically complete binary trees, meaning every level is fully filled except possibly for the last level, which has nodes as far left as possible.\n * 2. Heap Properties: The value of each parent node is greater than or equal to the value of its children.\n * 3. Root Node Access: In a heap, the largest element (in a max heap) or the smallest element (in a min heap) is always at the root of the tree.\n * 4. Efficient Insertion and Deletion: Due to its structure, a heap allows for insertion and deletion operations in logarithmic time (O(log n)).\n * 5. Managing Dynamic Data Sets: Heaps effectively manage dynamic data sets, especially when frequent access to the largest or smallest elements is required.\n * 6. Non-linear Search: While a heap allows rapid access to its largest or smallest element, it is less efficient for other operations, such as searching for a specific element, as it is not designed for these tasks.\n * 7. Efficient Sorting Algorithms: For example, heap sort. Heap sort uses the properties of a heap to sort elements.\n * 8. Graph Algorithms: Such as Dijkstra's shortest path algorithm and Prim's minimum-spanning tree algorithm, which use heaps to improve performance.\n */\nexport class MaxHeap<E = any, R = any> extends Heap<E, R> {\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: HeapOptions<E, R>) {\n super(elements, {\n comparator: (a: E, b: E): number => {\n if (typeof a === 'object' || typeof b === 'object') {\n throw TypeError(\n `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`\n );\n }\n if (a < b) return 1;\n if (a > b) return -1;\n return 0;\n },\n ...options\n });\n }\n\n /**\n * The `clone` function returns a new instance of the `MaxHeap` class with the same properties as the\n * current instance.\n * @returns The `clone()` method is returning a new instance of the `MaxHeap` class with the same\n * properties as the current instance.\n */\n override clone(): MaxHeap<E, R> {\n return new MaxHeap<E, R>(this, { comparator: this.comparator, toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new MaxHeap object containing elements that pass a given callback\n * function.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: the current element, the index of the current element, and the\n * heap itself. The callback function should return a boolean value indicating whether the current\n * element should be included in the filtered list\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `MaxHeap` object that contains the elements that pass\n * the filter condition specified by the `callback` function.\n */\n override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): MaxHeap<E, R> {\n const filteredList = new MaxHeap<E, R>([], { toElementFn: this.toElementFn, comparator: this.comparator });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredList.add(current);\n }\n index++;\n }\n return filteredList;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * The `map` function creates a new heap by applying a callback function to each element of the\n * original heap.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: `el` (the current element), `index` (the index of the current\n * element), and `this` (the heap itself). The callback function should return a value of\n * @param comparator - The `comparator` parameter is a function that defines the order of the\n * elements in the heap. It takes two elements `a` and `b` as arguments and returns a negative number\n * if `a` should be placed before `b`, a positive number if `a` should be placed after\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that converts the raw\n * element `RR` to the desired type `T`. It takes a single argument `rawElement` of type `RR` and\n * returns a value of type `T`. This function is used to transform the elements of the original\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `MaxHeap` class with the mapped elements.\n */\n override map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n comparator: Comparator<EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): MaxHeap<EM, RM> {\n const mappedHeap: MaxHeap<EM, RM> = new MaxHeap<EM, RM>([], { comparator, toElementFn });\n let index = 0;\n for (const el of this) {\n mappedHeap.add(callback.call(thisArg, el, index, this));\n index++;\n }\n return mappedHeap;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Kirk Qi\n * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>\n * @license MIT License\n */\nimport type { Comparator, ElementCallback, HeapOptions } from '../../types';\nimport { Heap } from './heap';\n\n/**\n * 1. Complete Binary Tree: Heaps are typically complete binary trees, meaning every level is fully filled except possibly for the last level, which has nodes as far left as possible.\n * 2. MinHeap Properties: The value of each parent node is less than or equal to the value of its children.\n * 3. Root Node Access: In a heap, the largest element (in a max heap) or the smallest element (in a min heap) is always at the root of the tree.\n * 4. Efficient Insertion and Deletion: Due to its structure, a heap allows for insertion and deletion operations in logarithmic time (O(log n)).\n * 5. Managing Dynamic Data Sets: Heaps effectively manage dynamic data sets, especially when frequent access to the largest or smallest elements is required.\n * 6. Non-linear Search: While a heap allows rapid access to its largest or smallest element, it is less efficient for other operations, such as searching for a specific element, as it is not designed for these tasks.\n * 7. Efficient Sorting Algorithms: For example, heap sort. MinHeap sort uses the properties of a heap to sort elements.\n * 8. Graph Algorithms: Such as Dijkstra's shortest path algorithm and Prim's minimum spanning tree algorithm, which use heaps to improve performance.\n */\nexport class MinHeap<E = any, R = any> extends Heap<E, R> {\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: HeapOptions<E, R>) {\n super(elements, options);\n }\n\n /**\n * The `clone` function returns a new instance of the `MinHeap` class with the same comparator and\n * toElementFn as the original instance.\n * @returns The `clone()` method is returning a new instance of the `MinHeap` class with the same\n * properties as the current instance.\n */\n override clone(): MinHeap<E, R> {\n return new MinHeap<E, R>(this, { comparator: this.comparator, toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new MinHeap object containing elements that pass a given callback\n * function.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: the current element, the index of the current element, and the\n * heap itself. The callback function should return a boolean value indicating whether the current\n * element should be included in the filtered list\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `MinHeap` object that contains the elements that pass\n * the filter condition specified by the `callback` function.\n */\n override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): MinHeap<E, R> {\n const filteredList = new MinHeap<E, R>([], { toElementFn: this.toElementFn, comparator: this.comparator });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredList.add(current);\n }\n index++;\n }\n return filteredList;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * The `map` function creates a new heap by applying a callback function to each element of the\n * original heap.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: `el` (the current element), `index` (the index of the current\n * element), and `this` (the heap itself). The callback function should return a value of\n * @param comparator - The `comparator` parameter is a function that defines the order of the\n * elements in the heap. It takes two elements `a` and `b` as arguments and returns a negative number\n * if `a` should be placed before `b`, a positive number if `a` should be placed after\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that converts the raw\n * element `RR` to the desired type `T`. It takes a single argument `rawElement` of type `RR` and\n * returns a value of type `T`. This function is used to transform the elements of the original\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `MinHeap` class with the mapped elements.\n */\n override map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n comparator: Comparator<EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): MinHeap<EM, RM> {\n const mappedHeap: MinHeap<EM, RM> = new MinHeap<EM, RM>([], { comparator, toElementFn });\n let index = 0;\n for (const el of this) {\n mappedHeap.add(callback.call(thisArg, el, index, this));\n index++;\n }\n return mappedHeap;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { DijkstraResult, EntryCallback, VertexKey } from '../../types';\nimport { uuidV4 } from '../../utils';\nimport { IterableEntryBase } from '../base';\nimport { IGraph } from '../../interfaces';\nimport { Heap } from '../heap';\nimport { Queue } from '../queue';\n\nexport abstract class AbstractVertex<V = any> {\n key: VertexKey;\n value: V | undefined;\n\n /**\n * The function is a protected constructor that takes an key and an optional value as parameters.\n * @param {VertexKey} key - The `key` parameter is of type `VertexKey` and represents the identifier of the vertex. It is\n * used to uniquely identify the vertex object.\n * @param {V} [value] - The parameter \"value\" is an optional parameter of type V. It is used to assign a value to the\n * vertex. If no value is provided, it will be set to undefined.\n */\n protected constructor(key: VertexKey, value?: V) {\n this.key = key;\n this.value = value;\n }\n}\n\nexport abstract class AbstractEdge<E = any> {\n value: E | undefined;\n weight: number;\n\n /**\n * The above function is a protected constructor that initializes the weight, value, and hash code properties of an\n * object.\n * @param {number} [weight] - The `weight` parameter is an optional number that represents the weight of the object. If\n * a value is provided, it will be assigned to the `_weight` property. If no value is provided, the default value of 1\n * will be assigned.\n * @param {VO} [value] - The `value` parameter is of type `VO`, which means it can be any type. It is an optional parameter,\n * meaning it can be omitted when creating an instance of the class.\n */\n protected constructor(weight?: number, value?: E) {\n this.weight = weight !== undefined ? weight : 1;\n this.value = value;\n this._hashCode = uuidV4();\n }\n\n protected _hashCode: string;\n\n get hashCode(): string {\n return this._hashCode;\n }\n\n /**\n * In TypeScript, a subclass inherits the interface implementation of its parent class, without needing to implement the same interface again in the subclass. This behavior differs from Java's approach. In Java, if a parent class implements an interface, the subclass needs to explicitly implement the same interface, even if the parent class has already implemented it.\n * This means that using abstract methods in the parent class cannot constrain the grandchild classes. Defining methods within an interface also cannot constrain the descendant classes. When inheriting from this class, developers need to be aware that this method needs to be overridden.\n */\n}\n\nexport abstract class AbstractGraph<\n V = any,\n E = any,\n VO extends AbstractVertex<V> = AbstractVertex<V>,\n EO extends AbstractEdge<E> = AbstractEdge<E>\n >\n extends IterableEntryBase<VertexKey, V | undefined>\n implements IGraph<V, E, VO, EO>\n{\n constructor() {\n super();\n }\n\n protected _vertexMap: Map<VertexKey, VO> = new Map<VertexKey, VO>();\n\n get vertexMap(): Map<VertexKey, VO> {\n return this._vertexMap;\n }\n\n set vertexMap(v: Map<VertexKey, VO>) {\n this._vertexMap = v;\n }\n\n get size(): number {\n return this._vertexMap.size;\n }\n\n /**\n * In TypeScript, a subclass inherits the interface implementation of its parent class, without needing to implement the same interface again in the subclass. This behavior differs from Java's approach. In Java, if a parent class implements an interface, the subclass needs to explicitly implement the same interface, even if the parent class has already implemented it.\n * This means that using abstract methods in the parent class cannot constrain the grandchild classes. Defining methods within an interface also cannot constrain the descendant classes. When inheriting from this class, developers need to be aware that this method needs to be overridden.\n * @param key\n * @param value\n */\n abstract createVertex(key: VertexKey, value?: V): VO;\n\n /**\n * In TypeScript, a subclass inherits the interface implementation of its parent class, without needing to implement the same interface again in the subclass. This behavior differs from Java's approach. In Java, if a parent class implements an interface, the subclass needs to explicitly implement the same interface, even if the parent class has already implemented it.\n * This means that using abstract methods in the parent class cannot constrain the grandchild classes. Defining methods within an interface also cannot constrain the descendant classes. When inheriting from this class, developers need to be aware that this method needs to be overridden.\n * @param srcOrV1\n * @param destOrV2\n * @param weight\n * @param value\n */\n abstract createEdge(srcOrV1: VertexKey, destOrV2: VertexKey, weight?: number, value?: E): EO;\n\n abstract deleteEdge(edge: EO): EO | undefined;\n\n abstract getEdge(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | undefined;\n\n abstract degreeOf(vertexOrKey: VO | VertexKey): number;\n\n abstract edgeSet(): EO[];\n\n abstract edgesOf(vertexOrKey: VO | VertexKey): EO[];\n\n abstract getNeighbors(vertexOrKey: VO | VertexKey): VO[];\n\n abstract getEndsOfEdge(edge: EO): [VO, VO] | undefined;\n\n /**\n * Time Complexity: O(1) - Constant time for Map lookup.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n *\n * The function \"getVertex\" returns the vertex with the specified ID or undefined if it doesn't exist.\n * @param {VertexKey} vertexKey - The `vertexKey` parameter is the identifier of the vertex that you want to retrieve from\n * the `_vertexMap` map.\n * @returns The method `getVertex` returns the vertex with the specified `vertexKey` if it exists in the `_vertexMap`\n * map. If the vertex does not exist, it returns `undefined`.\n */\n getVertex(vertexKey: VertexKey): VO | undefined {\n return this._vertexMap.get(vertexKey) || undefined;\n }\n\n /**\n * Time Complexity: O(1) - Constant time for Map lookup.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n *\n * The function checks if a vertex exists in a graph.\n * @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can be either a vertex object (`VO`) or a vertex ID\n * (`VertexKey`).\n * @returns a boolean value.\n */\n hasVertex(vertexOrKey: VO | VertexKey): boolean {\n return this._vertexMap.has(this._getVertexKey(vertexOrKey));\n }\n\n addVertex(vertex: VO): boolean;\n\n addVertex(key: VertexKey, value?: V): boolean;\n\n /**\n * Time Complexity: O(1) - Constant time for Map operations.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n */\n\n addVertex(keyOrVertex: VertexKey | VO, value?: V): boolean {\n if (keyOrVertex instanceof AbstractVertex) {\n return this._addVertex(keyOrVertex);\n } else {\n const newVertex = this.createVertex(keyOrVertex, value);\n return this._addVertex(newVertex);\n }\n }\n\n isVertexKey(potentialKey: any): potentialKey is VertexKey {\n const potentialKeyType = typeof potentialKey;\n return potentialKeyType === 'string' || potentialKeyType === 'number';\n }\n\n /**\n * Time Complexity: O(1) - Constant time for Map operations.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n */\n\n abstract deleteVertex(vertexOrKey: VO | VertexKey): boolean;\n\n /**\n * Time Complexity: O(K), where K is the number of vertexMap to be removed.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n *\n * The function removes all vertexMap from a graph and returns a boolean indicating if any vertexMap were removed.\n * @param {VO[] | VertexKey[]} vertexMap - The `vertexMap` parameter can be either an array of vertexMap (`VO[]`) or an array\n * of vertex IDs (`VertexKey[]`).\n * @returns a boolean value. It returns true if at least one vertex was successfully removed, and false if no vertexMap\n * were removed.\n */\n removeManyVertices(vertexMap: VO[] | VertexKey[]): boolean {\n const removed: boolean[] = [];\n for (const v of vertexMap) {\n removed.push(this.deleteVertex(v));\n }\n return removed.length > 0;\n }\n\n /**\n * Time Complexity: O(1) - Depends on the implementation in the concrete class.\n * Space Complexity: O(1) - Depends on the implementation in the concrete class.\n *\n * The function checks if there is an edge between two vertexMap and returns a boolean value indicating the result.\n * @param {VertexKey | VO} v1 - The parameter v1 can be either a VertexKey or a VO. A VertexKey represents the unique\n * identifier of a vertex in a graph, while VO represents the type of the vertex object itself.\n * @param {VertexKey | VO} v2 - The parameter `v2` represents the second vertex in the edge. It can be either a\n * `VertexKey` or a `VO` type, which represents the type of the vertex.\n * @returns A boolean value is being returned.\n */\n hasEdge(v1: VertexKey | VO, v2: VertexKey | VO): boolean {\n const edge = this.getEdge(v1, v2);\n return !!edge;\n }\n\n addEdge(edge: EO): boolean;\n\n addEdge(src: VO | VertexKey, dest: VO | VertexKey, weight?: number, value?: E): boolean;\n\n /**\n * Time Complexity: O(1) - Depends on the implementation in the concrete class.\n * Space Complexity: O(1) - Depends on the implementation in the concrete class.\n */\n\n addEdge(srcOrEdge: VO | VertexKey | EO, dest?: VO | VertexKey, weight?: number, value?: E): boolean {\n if (srcOrEdge instanceof AbstractEdge) {\n return this._addEdge(srcOrEdge);\n } else {\n if (dest instanceof AbstractVertex || typeof dest === 'string' || typeof dest === 'number') {\n if (!(this.hasVertex(srcOrEdge) && this.hasVertex(dest))) return false;\n if (srcOrEdge instanceof AbstractVertex) srcOrEdge = srcOrEdge.key;\n if (dest instanceof AbstractVertex) dest = dest.key;\n const newEdge = this.createEdge(srcOrEdge, dest, weight, value);\n return this._addEdge(newEdge);\n } else {\n throw new Error('dest must be a Vertex or vertex key while srcOrEdge is an Edge');\n }\n }\n }\n\n /**\n * Time Complexity: O(1) - Constant time for Map and Edge operations.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n *\n * The function sets the weight of an edge between two vertexMap in a graph.\n * @param {VertexKey | VO} srcOrKey - The `srcOrKey` parameter can be either a `VertexKey` or a `VO` object. It represents\n * the source vertex of the edge.\n * @param {VertexKey | VO} destOrKey - The `destOrKey` parameter represents the destination vertex of the edge. It can be\n * either a `VertexKey` or a vertex object `VO`.\n * @param {number} weight - The weight parameter represents the weight of the edge between the source vertex (srcOrKey)\n * and the destination vertex (destOrKey).\n * @returns a boolean value. If the edge exists between the source and destination vertexMap, the function will update\n * the weight of the edge and return true. If the edge does not exist, the function will return false.\n */\n setEdgeWeight(srcOrKey: VertexKey | VO, destOrKey: VertexKey | VO, weight: number): boolean {\n const edge = this.getEdge(srcOrKey, destOrKey);\n if (edge) {\n edge.weight = weight;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Time Complexity: O(P), where P is the number of paths found (in the worst case, exploring all paths).\n * Space Complexity: O(P) - Linear space, where P is the number of paths found.\n *\n * The function `getAllPathsBetween` finds all paths between two vertexMap in a graph using depth-first search.\n * @param {VO | VertexKey} v1 - The parameter `v1` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).\n * It is the starting vertex for finding paths.\n * @param {VO | VertexKey} v2 - The parameter `v2` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).\n * @param limit - The count of limitation of result array.\n * @returns The function `getAllPathsBetween` returns an array of arrays of vertexMap (`VO[][]`).\n */\n getAllPathsBetween(v1: VO | VertexKey, v2: VO | VertexKey, limit = 1000): VO[][] {\n const paths: VO[][] = [];\n const vertex1 = this._getVertex(v1);\n const vertex2 = this._getVertex(v2);\n\n if (!(vertex1 && vertex2)) {\n return [];\n }\n\n const stack: { vertex: VO; path: VO[] }[] = [];\n stack.push({ vertex: vertex1, path: [vertex1] });\n\n while (stack.length > 0) {\n const { vertex, path } = stack.pop()!;\n\n if (vertex === vertex2) {\n paths.push(path);\n if (paths.length >= limit) return paths;\n }\n\n const neighbors = this.getNeighbors(vertex);\n for (const neighbor of neighbors) {\n if (!path.includes(neighbor)) {\n const newPath = [...path, neighbor];\n stack.push({ vertex: neighbor, path: newPath });\n }\n }\n }\n return paths;\n }\n\n /**\n * Time Complexity: O(L), where L is the length of the path.\n * Space Complexity: O(1) - Constant space.\n *\n * The function calculates the sum of weights along a given path.\n * @param {VO[]} path - An array of vertexMap (VO) representing a path in a graph.\n * @returns The function `getPathSumWeight` returns the sum of the weights of the edgeMap in the given path.\n */\n getPathSumWeight(path: VO[]): number {\n let sum = 0;\n for (let i = 0; i < path.length; i++) {\n sum += this.getEdge(path[i], path[i + 1])?.weight || 0;\n }\n return sum;\n }\n\n /**\n * Time Complexity: O(V + E) - Depends on the implementation (Dijkstra's algorithm).\n * Space Complexity: O(V + E) - Depends on the implementation (Dijkstra's algorithm).\n *\n * The function `getMinCostBetween` calculates the minimum cost between two vertexMap in a graph, either based on edge\n * weights or using a breadth-first search algorithm.\n * @param {VO | VertexKey} v1 - The parameter `v1` represents the starting vertex or its ID.\n * @param {VO | VertexKey} v2 - The parameter `v2` represents the destination vertex or its ID. It is the vertex to which\n * you want to find the minimum cost or weight from the source vertex `v1`.\n * @param {boolean} [isWeight] - isWeight is an optional parameter that indicates whether the graph edgeMap have weights.\n * If isWeight is set to true, the function will calculate the minimum cost between v1 and v2 based on the weights of\n * the edgeMap. If isWeight is set to false or not provided, the function will calculate the\n * @returns The function `getMinCostBetween` returns a number representing the minimum cost between two vertexMap (`v1`\n * and `v2`). If the `isWeight` parameter is `true`, it calculates the minimum weight among all paths between the\n * vertexMap. If `isWeight` is `false` or not provided, it uses a breadth-first search (BFS) algorithm to calculate the\n * minimum number of\n */\n getMinCostBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean): number | undefined {\n if (isWeight === undefined) isWeight = false;\n\n if (isWeight) {\n const allPaths = this.getAllPathsBetween(v1, v2);\n let min = Number.MAX_SAFE_INTEGER;\n for (const path of allPaths) {\n min = Math.min(this.getPathSumWeight(path), min);\n }\n return min;\n } else {\n // BFS\n const vertex2 = this._getVertex(v2);\n const vertex1 = this._getVertex(v1);\n if (!(vertex1 && vertex2)) {\n return undefined;\n }\n\n const visited: Map<VO, boolean> = new Map();\n const queue = new Queue<VO>([vertex1]);\n visited.set(vertex1, true);\n let cost = 0;\n while (queue.length > 0) {\n for (let i = 0; i < queue.length; i++) {\n const cur = queue.shift();\n if (cur === vertex2) {\n return cost;\n }\n // TODO consider optimizing to AbstractGraph\n if (cur !== undefined) {\n const neighbors = this.getNeighbors(cur);\n for (const neighbor of neighbors) {\n if (!visited.has(neighbor)) {\n visited.set(neighbor, true);\n queue.push(neighbor);\n }\n }\n }\n }\n cost++;\n }\n return undefined;\n }\n }\n\n /**\n * Time Complexity: O(V + E) - Depends on the implementation (Dijkstra's algorithm or DFS).\n * Space Complexity: O(V + E) - Depends on the implementation (Dijkstra's algorithm or DFS).\n *\n * The function `getMinPathBetween` returns the minimum path between two vertexMap in a graph, either based on weight or\n * using a breadth-first search algorithm.\n * @param {VO | VertexKey} v1 - The parameter `v1` represents the starting vertex of the path. It can be either a vertex\n * object (`VO`) or a vertex ID (`VertexKey`).\n * @param {VO | VertexKey} v2 - VO | VertexKey - The second vertex or vertex ID between which we want to find the minimum\n * path.\n * @param {boolean} [isWeight] - A boolean flag indicating whether to consider the weight of edgeMap in finding the\n * minimum path. If set to true, the function will use Dijkstra's algorithm to find the minimum weighted path. If set\n * to false, the function will use breadth-first search (BFS) to find the minimum path.\n * @param isDFS - If set to true, it enforces the use of getAllPathsBetween to first obtain all possible paths,\n * followed by iterative computation of the shortest path. This approach may result in exponential time complexity,\n * so the default method is to use the Dijkstra algorithm to obtain the shortest weighted path.\n * @returns The function `getMinPathBetween` returns an array of vertexMap (`VO[]`) representing the minimum path between\n * two vertexMap (`v1` and `v2`). If there is no path between the vertexMap, it returns `undefined`.\n */\n getMinPathBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean, isDFS = false): VO[] | undefined {\n if (isWeight === undefined) isWeight = false;\n\n if (isWeight) {\n if (isDFS) {\n const allPaths = this.getAllPathsBetween(v1, v2, 10000);\n let min = Number.MAX_SAFE_INTEGER;\n let minIndex = -1;\n let index = 0;\n for (const path of allPaths) {\n const pathSumWeight = this.getPathSumWeight(path);\n if (pathSumWeight < min) {\n min = pathSumWeight;\n minIndex = index;\n }\n index++;\n }\n return allPaths[minIndex] || undefined;\n } else {\n return this.dijkstra(v1, v2, true, true)?.minPath ?? [];\n }\n } else {\n // DFS\n let minPath: VO[] = [];\n const vertex1 = this._getVertex(v1);\n const vertex2 = this._getVertex(v2);\n if (!(vertex1 && vertex2)) return [];\n\n const dfs = (cur: VO, dest: VO, visiting: Set<VO>, path: VO[]) => {\n visiting.add(cur);\n if (cur === dest) {\n minPath = [vertex1, ...path];\n return;\n }\n\n const neighbors = this.getNeighbors(cur);\n for (const neighbor of neighbors) {\n if (!visiting.has(neighbor)) {\n path.push(neighbor);\n dfs(neighbor, dest, visiting, path);\n path.pop();\n }\n }\n\n visiting.delete(cur);\n };\n\n dfs(vertex1, vertex2, new Set<VO>(), []);\n return minPath;\n }\n }\n\n /**\n * Time Complexity: O(V^2 + E) - Quadratic time in the worst case (no heap optimization).\n * Space Complexity: O(V + E) - Depends on the implementation (Dijkstra's algorithm).\n *\n * The function `dijkstraWithoutHeap` implements Dijkstra's algorithm to find the shortest path between two vertexMap in\n * a graph without using a heap data structure.\n * @param {VO | VertexKey} src - The source vertex from which to start the Dijkstra's algorithm. It can be either a\n * vertex object or a vertex ID.\n * @param {VO | VertexKey | undefined} [dest] - The `dest` parameter in the `dijkstraWithoutHeap` function is an optional\n * parameter that specifies the destination vertex for the Dijkstra algorithm. It can be either a vertex object or its\n * identifier. If no destination is provided, the value is set to `undefined`.\n * @param {boolean} [getMinDist] - The `getMinDist` parameter is a boolean flag that determines whether the minimum\n * distance from the source vertex to the destination vertex should be calculated and returned in the result. If\n * `getMinDist` is set to `true`, the `minDist` property in the result will contain the minimum distance\n * @param {boolean} [genPaths] - The `genPaths` parameter is a boolean flag that determines whether or not to generate\n * paths in the Dijkstra algorithm. If `genPaths` is set to `true`, the algorithm will calculate and return the\n * shortest paths from the source vertex to all other vertexMap in the graph. If `genPaths\n * @returns The function `dijkstraWithoutHeap` returns an object of type `DijkstraResult<VO>`.\n */\n dijkstraWithoutHeap(\n src: VO | VertexKey,\n dest: VO | VertexKey | undefined = undefined,\n getMinDist: boolean = false,\n genPaths: boolean = false\n ): DijkstraResult<VO> {\n let minDist = Number.MAX_SAFE_INTEGER;\n let minDest: VO | undefined = undefined;\n let minPath: VO[] = [];\n const paths: VO[][] = [];\n\n const vertexMap = this._vertexMap;\n const distMap: Map<VO, number> = new Map();\n const seen: Set<VO> = new Set();\n const preMap: Map<VO, VO | undefined> = new Map(); // predecessor\n const srcVertex = this._getVertex(src);\n\n const destVertex = dest ? this._getVertex(dest) : undefined;\n\n if (!srcVertex) {\n return undefined;\n }\n\n for (const vertex of vertexMap) {\n const vertexOrKey = vertex[1];\n if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Number.MAX_SAFE_INTEGER);\n }\n distMap.set(srcVertex, 0);\n preMap.set(srcVertex, undefined);\n\n const getMinOfNoSeen = () => {\n let min = Number.MAX_SAFE_INTEGER;\n let minV: VO | undefined = undefined;\n for (const [key, value] of distMap) {\n if (!seen.has(key)) {\n if (value < min) {\n min = value;\n minV = key;\n }\n }\n }\n return minV;\n };\n\n const getPaths = (minV: VO | undefined) => {\n for (const vertex of vertexMap) {\n const vertexOrKey = vertex[1];\n\n if (vertexOrKey instanceof AbstractVertex) {\n const path: VO[] = [vertexOrKey];\n let parent = preMap.get(vertexOrKey);\n while (parent) {\n path.push(parent);\n parent = preMap.get(parent);\n }\n const reversed = path.reverse();\n if (vertex[1] === minV) minPath = reversed;\n paths.push(reversed);\n }\n }\n };\n\n for (let i = 1; i < vertexMap.size; i++) {\n const cur = getMinOfNoSeen();\n if (cur) {\n seen.add(cur);\n if (destVertex && destVertex === cur) {\n if (getMinDist) {\n minDist = distMap.get(destVertex) || Number.MAX_SAFE_INTEGER;\n }\n if (genPaths) {\n getPaths(destVertex);\n }\n return { distMap, preMap, seen, paths, minDist, minPath };\n }\n const neighbors = this.getNeighbors(cur);\n for (const neighbor of neighbors) {\n if (!seen.has(neighbor)) {\n const edge = this.getEdge(cur, neighbor);\n if (edge) {\n const curFromMap = distMap.get(cur);\n const neighborFromMap = distMap.get(neighbor);\n // TODO after no-non-undefined-assertion not ensure the logic\n if (curFromMap !== undefined && neighborFromMap !== undefined) {\n if (edge.weight + curFromMap < neighborFromMap) {\n distMap.set(neighbor, edge.weight + curFromMap);\n preMap.set(neighbor, cur);\n }\n }\n }\n }\n }\n }\n }\n\n if (getMinDist)\n distMap.forEach((d, v) => {\n if (v !== srcVertex) {\n if (d < minDist) {\n minDist = d;\n if (genPaths) minDest = v;\n }\n }\n });\n\n if (genPaths) getPaths(minDest);\n\n return { distMap, preMap, seen, paths, minDist, minPath };\n }\n\n /**\n * Time Complexity: O((V + E) * log(V)) - Depends on the implementation (using a binary heap).\n * Space Complexity: O(V + E) - Depends on the implementation (using a binary heap).\n *\n * Dijkstra's algorithm is used to find the shortest paths from a source node to all other nodes in a graph. Its basic idea is to repeatedly choose the node closest to the source node and update the distances of other nodes using this node as an intermediary. Dijkstra's algorithm requires that the edge weights in the graph are non-negative.\n * The `dijkstra` function implements Dijkstra's algorithm to find the shortest path between a source vertex and an\n * optional destination vertex, and optionally returns the minimum distance, the paths, and other information.\n * @param {VO | VertexKey} src - The `src` parameter represents the source vertex from which the Dijkstra algorithm will\n * start. It can be either a vertex object or a vertex ID.\n * @param {VO | VertexKey | undefined} [dest] - The `dest` parameter is the destination vertex or vertex ID. It specifies the\n * vertex to which the shortest path is calculated from the source vertex. If no destination is provided, the algorithm\n * will calculate the shortest paths to all other vertexMap from the source vertex.\n * @param {boolean} [getMinDist] - The `getMinDist` parameter is a boolean flag that determines whether the minimum\n * distance from the source vertex to the destination vertex should be calculated and returned in the result. If\n * `getMinDist` is set to `true`, the `minDist` property in the result will contain the minimum distance\n * @param {boolean} [genPaths] - The `genPaths` parameter is a boolean flag that determines whether or not to generate\n * paths in the Dijkstra algorithm. If `genPaths` is set to `true`, the algorithm will calculate and return the\n * shortest paths from the source vertex to all other vertexMap in the graph. If `genPaths\n * @returns The function `dijkstra` returns an object of type `DijkstraResult<VO>`.\n */\n dijkstra(\n src: VO | VertexKey,\n dest: VO | VertexKey | undefined = undefined,\n getMinDist: boolean = false,\n genPaths: boolean = false\n ): DijkstraResult<VO> {\n let minDist = Number.MAX_SAFE_INTEGER;\n let minDest: VO | undefined = undefined;\n let minPath: VO[] = [];\n const paths: VO[][] = [];\n const vertexMap = this._vertexMap;\n const distMap: Map<VO, number> = new Map();\n const seen: Set<VO> = new Set();\n const preMap: Map<VO, VO | undefined> = new Map(); // predecessor\n\n const srcVertex = this._getVertex(src);\n const destVertex = dest ? this._getVertex(dest) : undefined;\n\n if (!srcVertex) return undefined;\n\n for (const vertex of vertexMap) {\n const vertexOrKey = vertex[1];\n if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Number.MAX_SAFE_INTEGER);\n }\n\n const heap = new Heap<{ key: number; value: VO }>([], { comparator: (a, b) => a.key - b.key });\n heap.add({ key: 0, value: srcVertex });\n\n distMap.set(srcVertex, 0);\n preMap.set(srcVertex, undefined);\n\n /**\n * The function `getPaths` retrieves all paths from vertexMap to a specified minimum vertex.\n * @param {VO | undefined} minV - The parameter `minV` is of type `VO | undefined`. It represents the minimum vertex value or\n * undefined.\n */\n const getPaths = (minV: VO | undefined) => {\n for (const vertex of vertexMap) {\n const vertexOrKey = vertex[1];\n if (vertexOrKey instanceof AbstractVertex) {\n const path: VO[] = [vertexOrKey];\n let parent = preMap.get(vertexOrKey);\n while (parent) {\n path.push(parent);\n parent = preMap.get(parent);\n }\n const reversed = path.reverse();\n if (vertex[1] === minV) minPath = reversed;\n paths.push(reversed);\n }\n }\n };\n\n while (heap.size > 0) {\n const curHeapNode = heap.poll();\n const dist = curHeapNode?.key;\n const cur = curHeapNode?.value;\n if (dist !== undefined) {\n if (cur) {\n seen.add(cur);\n if (destVertex && destVertex === cur) {\n if (getMinDist) {\n minDist = distMap.get(destVertex) || Number.MAX_SAFE_INTEGER;\n }\n if (genPaths) {\n getPaths(destVertex);\n }\n return { distMap, preMap, seen, paths, minDist, minPath };\n }\n const neighbors = this.getNeighbors(cur);\n for (const neighbor of neighbors) {\n if (!seen.has(neighbor)) {\n const weight = this.getEdge(cur, neighbor)?.weight;\n if (typeof weight === 'number') {\n const distSrcToNeighbor = distMap.get(neighbor);\n if (distSrcToNeighbor) {\n if (dist + weight < distSrcToNeighbor) {\n heap.add({ key: dist + weight, value: neighbor });\n preMap.set(neighbor, cur);\n distMap.set(neighbor, dist + weight);\n }\n }\n }\n }\n }\n }\n }\n }\n\n if (getMinDist) {\n distMap.forEach((d, v) => {\n if (v !== srcVertex) {\n if (d < minDist) {\n minDist = d;\n if (genPaths) minDest = v;\n }\n }\n });\n }\n\n if (genPaths) {\n getPaths(minDest);\n }\n\n return { distMap, preMap, seen, paths, minDist, minPath };\n }\n\n /**\n * Time Complexity: O(V * E) - Quadratic time in the worst case (Bellman-Ford algorithm).\n * Space Complexity: O(V + E) - Depends on the implementation (Bellman-Ford algorithm).\n *\n * one to rest pairs\n * The Bellman-Ford algorithm is also used to find the shortest paths from a source node to all other nodes in a graph. Unlike Dijkstra's algorithm, it can handle edge weights that are negative. Its basic idea involves iterative relaxation of all edgeMap for several rounds to gradually approximate the shortest paths. Due to its ability to handle negative-weight edgeMap, the Bellman-Ford algorithm is more flexible in some scenarios.\n * The `bellmanFord` function implements the Bellman-Ford algorithm to find the shortest path from a source vertex to\n * all other vertexMap in a graph, and optionally detects negative cycles and generates the minimum path.\n * @param {VO | VertexKey} src - The `src` parameter is the source vertex from which the Bellman-Ford algorithm will\n * start calculating the shortest paths. It can be either a vertex object or a vertex ID.\n * @param {boolean} [scanNegativeCycle] - A boolean flag indicating whether to scan for negative cycles in the graph.\n * @param {boolean} [getMin] - The `getMin` parameter is a boolean flag that determines whether the algorithm should\n * calculate the minimum distance from the source vertex to all other vertexMap in the graph. If `getMin` is set to\n * `true`, the algorithm will find the minimum distance and update the `min` variable with the minimum\n * @param {boolean} [genPath] - A boolean flag indicating whether to generate paths for all vertexMap from the source\n * vertex.\n * @returns The function `bellmanFord` returns an object with the following properties:\n */\n bellmanFord(src: VO | VertexKey, scanNegativeCycle?: boolean, getMin?: boolean, genPath?: boolean) {\n if (getMin === undefined) getMin = false;\n if (genPath === undefined) genPath = false;\n\n const srcVertex = this._getVertex(src);\n const paths: VO[][] = [];\n const distMap: Map<VO, number> = new Map();\n const preMap: Map<VO, VO> = new Map(); // predecessor\n let min = Number.MAX_SAFE_INTEGER;\n let minPath: VO[] = [];\n // TODO\n let hasNegativeCycle: boolean | undefined;\n if (scanNegativeCycle) hasNegativeCycle = false;\n if (!srcVertex) return { hasNegativeCycle, distMap, preMap, paths, min, minPath };\n\n const vertexMap = this._vertexMap;\n const numOfVertices = vertexMap.size;\n const edgeMap = this.edgeSet();\n const numOfEdges = edgeMap.length;\n\n this._vertexMap.forEach(vertex => {\n distMap.set(vertex, Number.MAX_SAFE_INTEGER);\n });\n\n distMap.set(srcVertex, 0);\n\n for (let i = 1; i < numOfVertices; ++i) {\n for (let j = 0; j < numOfEdges; ++j) {\n const ends = this.getEndsOfEdge(edgeMap[j]);\n if (ends) {\n const [s, d] = ends;\n const weight = edgeMap[j].weight;\n const sWeight = distMap.get(s);\n const dWeight = distMap.get(d);\n if (sWeight !== undefined && dWeight !== undefined) {\n if (distMap.get(s) !== Number.MAX_SAFE_INTEGER && sWeight + weight < dWeight) {\n distMap.set(d, sWeight + weight);\n if (genPath) preMap.set(d, s);\n }\n }\n }\n }\n }\n\n let minDest: VO | undefined = undefined;\n if (getMin) {\n distMap.forEach((d, v) => {\n if (v !== srcVertex) {\n if (d < min) {\n min = d;\n if (genPath) minDest = v;\n }\n }\n });\n }\n\n if (genPath) {\n for (const vertex of vertexMap) {\n const vertexOrKey = vertex[1];\n if (vertexOrKey instanceof AbstractVertex) {\n const path: VO[] = [vertexOrKey];\n let parent = preMap.get(vertexOrKey);\n while (parent !== undefined) {\n path.push(parent);\n parent = preMap.get(parent);\n }\n const reversed = path.reverse();\n if (vertex[1] === minDest) minPath = reversed;\n paths.push(reversed);\n }\n }\n }\n\n for (let j = 0; j < numOfEdges; ++j) {\n const ends = this.getEndsOfEdge(edgeMap[j]);\n if (ends) {\n const [s] = ends;\n const weight = edgeMap[j].weight;\n const sWeight = distMap.get(s);\n if (sWeight) {\n if (sWeight !== Number.MAX_SAFE_INTEGER && sWeight + weight < sWeight) hasNegativeCycle = true;\n }\n }\n }\n\n return { hasNegativeCycle, distMap, preMap, paths, min, minPath };\n }\n\n /**\n * Dijkstra algorithm time: O(logVE) space: O(VO + EO)\n */\n\n /**\n * Dijkstra algorithm time: O(logVE) space: O(VO + EO)\n * Dijkstra's algorithm is used to find the shortest paths from a source node to all other nodes in a graph. Its basic idea is to repeatedly choose the node closest to the source node and update the distances of other nodes using this node as an intermediary. Dijkstra's algorithm requires that the edge weights in the graph are non-negative.\n */\n\n /**\n * BellmanFord time:O(VE) space:O(VO)\n * one to rest pairs\n * The Bellman-Ford algorithm is also used to find the shortest paths from a source node to all other nodes in a graph. Unlike Dijkstra's algorithm, it can handle edge weights that are negative. Its basic idea involves iterative relaxation of all edgeMap for several rounds to gradually approximate the shortest paths. Due to its ability to handle negative-weight edgeMap, the Bellman-Ford algorithm is more flexible in some scenarios.\n * The `bellmanFord` function implements the Bellman-Ford algorithm to find the shortest path from a source vertex to\n */\n\n /**\n * Time Complexity: O(V^3) - Cubic time (Floyd-Warshall algorithm).\n * Space Complexity: O(V^2) - Quadratic space (Floyd-Warshall algorithm).\n *\n * Not support graph with negative weight cycle\n * all pairs\n * The Floyd-Warshall algorithm is used to find the shortest paths between all pairs of nodes in a graph. It employs dynamic programming to compute the shortest paths from any node to any other node. The Floyd-Warshall algorithm's advantage lies in its ability to handle graphs with negative-weight edgeMap, and it can simultaneously compute shortest paths between any two nodes.\n * The function implements the Floyd-Warshall algorithm to find the shortest path between all pairs of vertexMap in a\n * graph.\n * @returns The function `floydWarshall()` returns an object with two properties: `costs` and `predecessor`. The `costs`\n * property is a 2D array of numbers representing the shortest path costs between vertexMap in a graph. The\n * `predecessor` property is a 2D array of vertexMap (or `undefined`) representing the predecessor vertexMap in the shortest\n * path between vertexMap in the\n */\n floydWarshall(): { costs: number[][]; predecessor: (VO | undefined)[][] } {\n const idAndVertices = [...this._vertexMap];\n const n = idAndVertices.length;\n\n const costs: number[][] = [];\n const predecessor: (VO | undefined)[][] = [];\n // successors\n\n for (let i = 0; i < n; i++) {\n costs[i] = [];\n predecessor[i] = [];\n for (let j = 0; j < n; j++) {\n predecessor[i][j] = undefined;\n }\n }\n\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n costs[i][j] = this.getEdge(idAndVertices[i][1], idAndVertices[j][1])?.weight || Number.MAX_SAFE_INTEGER;\n }\n }\n\n for (let k = 0; k < n; k++) {\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n if (costs[i][j] > costs[i][k] + costs[k][j]) {\n costs[i][j] = costs[i][k] + costs[k][j];\n predecessor[i][j] = idAndVertices[k][1];\n }\n }\n }\n }\n return { costs, predecessor };\n }\n\n /**\n * O(V+E+C)\n * O(V+C)\n */\n getCycles(isInclude2Cycle: boolean = false): VertexKey[][] {\n const cycles: VertexKey[][] = [];\n const visited: Set<VO> = new Set();\n\n const dfs = (vertex: VO, currentPath: VertexKey[], visited: Set<VO>) => {\n if (visited.has(vertex)) {\n if (\n ((!isInclude2Cycle && currentPath.length > 2) || (isInclude2Cycle && currentPath.length >= 2)) &&\n currentPath[0] === vertex.key\n ) {\n cycles.push([...currentPath]);\n }\n return;\n }\n\n visited.add(vertex);\n currentPath.push(vertex.key);\n\n for (const neighbor of this.getNeighbors(vertex)) {\n if (neighbor) dfs(neighbor, currentPath, visited);\n }\n\n visited.delete(vertex);\n currentPath.pop();\n };\n\n for (const vertex of this.vertexMap.values()) {\n dfs(vertex, [], visited);\n }\n\n // Use a set to eliminate duplicate cycles\n const uniqueCycles = new Map<string, VertexKey[]>();\n\n for (const cycle of cycles) {\n const sorted = [...cycle].sort().toString();\n\n if (uniqueCycles.has(sorted)) continue;\n else {\n uniqueCycles.set(sorted, cycle);\n }\n }\n\n // Convert the unique cycles back to an array\n return [...uniqueCycles].map(cycleString => cycleString[1]);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function iterates over key-value pairs in a data structure and returns an array of\n * pairs that satisfy a given predicate.\n * @param predicate - The `predicate` parameter is a callback function that takes four arguments:\n * `value`, `key`, `index`, and `this`. It is used to determine whether an element should be included\n * in the filtered array. The callback function should return `true` if the element should be\n * included, and `\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the `predicate` function. It is used when you want to bind a\n * specific object as the context for the `predicate` function. If `thisArg` is provided, it will be\n * @returns The `filter` method returns an array of key-value pairs `[VertexKey, V | undefined][]`\n * that satisfy the given predicate function.\n */\n filter(predicate: EntryCallback<VertexKey, V | undefined, boolean>, thisArg?: any): [VertexKey, V | undefined][] {\n const filtered: [VertexKey, V | undefined][] = [];\n let index = 0;\n for (const [key, value] of this) {\n if (predicate.call(thisArg, key, value, index, this)) {\n filtered.push([key, value]);\n }\n index++;\n }\n return filtered;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function iterates over the elements of a collection and applies a callback function to\n * each element, returning an array of the results.\n * @param callback - The callback parameter is a function that will be called for each element in the\n * map. It takes four arguments:\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. If `thisArg` is provided, it will be\n * used as the `this` value when calling the callback function. If `thisArg` is not provided, `\n * @returns The `map` function is returning an array of type `T[]`.\n */\n map<T>(callback: EntryCallback<VertexKey, V | undefined, T>, thisArg?: any): T[] {\n const mapped: T[] = [];\n let index = 0;\n for (const [key, value] of this) {\n mapped.push(callback.call(thisArg, key, value, index, this));\n index++;\n }\n return mapped;\n }\n\n protected *_getIterator(): IterableIterator<[VertexKey, V | undefined]> {\n for (const vertex of this._vertexMap.values()) {\n yield [vertex.key, vertex.value];\n }\n }\n\n protected abstract _addEdge(edge: EO): boolean;\n\n protected _addVertex(newVertex: VO): boolean {\n if (this.hasVertex(newVertex)) {\n return false;\n // throw (new Error('Duplicated vertex key is not allowed'));\n }\n this._vertexMap.set(newVertex.key, newVertex);\n return true;\n }\n\n protected _getVertex(vertexOrKey: VertexKey | VO): VO | undefined {\n const vertexKey = this._getVertexKey(vertexOrKey);\n return this._vertexMap.get(vertexKey) || undefined;\n }\n\n protected _getVertexKey(vertexOrKey: VO | VertexKey): VertexKey {\n return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { TopologicalStatus, VertexKey } from '../../types';\nimport { AbstractEdge, AbstractGraph, AbstractVertex } from './abstract-graph';\nimport { IGraph } from '../../interfaces';\nimport { arrayRemove } from '../../utils';\n\nexport class DirectedVertex<V = any> extends AbstractVertex<V> {\n /**\n * The constructor function initializes a vertex with an optional value.\n * @param {VertexKey} key - The `key` parameter is of type `VertexKey` and represents the identifier of the vertex. It is\n * used to uniquely identify the vertex within a graph or data structure.\n * @param {V} [value] - The \"value\" parameter is an optional parameter of type V. It is used to initialize the value of the\n * vertex. If no value is provided, the vertex will be initialized with a default value.\n */\n constructor(key: VertexKey, value?: V) {\n super(key, value);\n }\n}\n\nexport class DirectedEdge<E = any> extends AbstractEdge<E> {\n src: VertexKey;\n dest: VertexKey;\n\n /**\n * The constructor function initializes the source and destination vertexMap of an edge, along with an optional weight\n * and value.\n * @param {VertexKey} src - The `src` parameter is the source vertex ID. It represents the starting point of an edge in\n * a graph.\n * @param {VertexKey} dest - The `dest` parameter represents the destination vertex of an edge. It is of type\n * `VertexKey`, which is likely a unique identifier for a vertex in a graph.\n * @param {number} [weight] - The weight parameter is an optional number that represents the weight of the edge.\n * @param {E} [value] - The `value` parameter is an optional parameter of type `E`. It represents the value associated with\n * the edge.\n */\n constructor(src: VertexKey, dest: VertexKey, weight?: number, value?: E) {\n super(weight, value);\n this.src = src;\n this.dest = dest;\n }\n}\n\n/**\n *\n */\nexport class DirectedGraph<\n V = any,\n E = any,\n VO extends DirectedVertex<V> = DirectedVertex<V>,\n EO extends DirectedEdge<E> = DirectedEdge<E>\n >\n extends AbstractGraph<V, E, VO, EO>\n implements IGraph<V, E, VO, EO>\n{\n /**\n * The constructor function initializes an instance of a class.\n */\n constructor() {\n super();\n }\n\n protected _outEdgeMap: Map<VO, EO[]> = new Map<VO, EO[]>();\n\n get outEdgeMap(): Map<VO, EO[]> {\n return this._outEdgeMap;\n }\n\n set outEdgeMap(v: Map<VO, EO[]>) {\n this._outEdgeMap = v;\n }\n\n protected _inEdgeMap: Map<VO, EO[]> = new Map<VO, EO[]>();\n\n get inEdgeMap(): Map<VO, EO[]> {\n return this._inEdgeMap;\n }\n\n set inEdgeMap(v: Map<VO, EO[]>) {\n this._inEdgeMap = v;\n }\n\n /**\n * The function creates a new vertex with an optional value and returns it.\n * @param {VertexKey} key - The `key` parameter is the unique identifier for the vertex. It is of type `VertexKey`, which\n * could be a number or a string depending on how you want to identify your vertexMap.\n * @param [value] - The 'value' parameter is an optional value that can be assigned to the vertex. If a value is provided,\n * it will be assigned to the 'value' property of the vertex. If no value is provided, the 'value' property will be\n * assigned the same value as the 'key' parameter\n * @returns a new instance of a DirectedVertex object, casted as type VO.\n */\n createVertex(key: VertexKey, value?: V): VO {\n return new DirectedVertex(key, value) as VO;\n }\n\n /**\n * The function creates a directed edge between two vertexMap with an optional weight and value.\n * @param {VertexKey} src - The source vertex ID of the edge. It represents the starting point of the edge.\n * @param {VertexKey} dest - The `dest` parameter is the identifier of the destination vertex for the edge.\n * @param {number} [weight] - The weight parameter is an optional number that represents the weight of the edge. If no\n * weight is provided, it defaults to 1.\n * @param [value] - The 'value' parameter is an optional value that can be assigned to the edge. It can be of any type and\n * is used to store additional information or data associated with the edge.\n * @returns a new instance of a DirectedEdge object, casted as type EO.\n */\n createEdge(src: VertexKey, dest: VertexKey, weight?: number, value?: E): EO {\n return new DirectedEdge(src, dest, weight ?? 1, value) as EO;\n }\n\n /**\n * Time Complexity: O(|V|) where |V| is the number of vertexMap\n * Space Complexity: O(1)\n *\n * The `getEdge` function retrieves an edge between two vertexMap based on their source and destination IDs.\n * @param {VO | VertexKey | undefined} srcOrKey - The source vertex or its ID. It can be either a vertex object or a vertex ID.\n * @param {VO | VertexKey | undefined} destOrKey - The `destOrKey` parameter in the `getEdge` function represents the\n * destination vertex of the edge. It can be either a vertex object (`VO`), a vertex ID (`VertexKey`), or `undefined` if the\n * destination is not specified.\n * @returns the first edge found between the source and destination vertexMap, or undefined if no such edge is found.\n */\n getEdge(srcOrKey: VO | VertexKey | undefined, destOrKey: VO | VertexKey | undefined): EO | undefined {\n let edgeMap: EO[] = [];\n\n if (srcOrKey !== undefined && destOrKey !== undefined) {\n const src: VO | undefined = this._getVertex(srcOrKey);\n const dest: VO | undefined = this._getVertex(destOrKey);\n\n if (src && dest) {\n const srcOutEdges = this._outEdgeMap.get(src);\n if (srcOutEdges) {\n edgeMap = srcOutEdges.filter(edge => edge.dest === dest.key);\n }\n }\n }\n\n return edgeMap[0] || undefined;\n }\n\n /**\n * Time Complexity: O(|E|) where |E| is the number of edgeMap\n * Space Complexity: O(1)\n *\n * The function removes an edge between two vertexMap in a graph and returns the removed edge.\n * @param {VO | VertexKey} srcOrKey - The source vertex or its ID.\n * @param {VO | VertexKey} destOrKey - The `destOrKey` parameter represents the destination vertex or its ID.\n * @returns the removed edge (EO) if it exists, or undefined if either the source or destination vertex does not exist.\n */\n deleteEdgeSrcToDest(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | undefined {\n const src: VO | undefined = this._getVertex(srcOrKey);\n const dest: VO | undefined = this._getVertex(destOrKey);\n let removed: EO | undefined = undefined;\n if (!src || !dest) {\n return undefined;\n }\n\n const srcOutEdges = this._outEdgeMap.get(src);\n if (srcOutEdges) {\n arrayRemove<EO>(srcOutEdges, (edge: EO) => edge.dest === dest.key);\n }\n\n const destInEdges = this._inEdgeMap.get(dest);\n if (destInEdges) {\n removed = arrayRemove<EO>(destInEdges, (edge: EO) => edge.src === src.key)[0] || undefined;\n }\n return removed;\n }\n\n /**\n * Time Complexity: O(E) where E is the number of edgeMap\n * Space Complexity: O(1)\n *\n * The `deleteEdge` function removes an edge from a graph and returns the removed edge.\n * @param {EO | VertexKey} edgeOrSrcVertexKey - The `edge` parameter can be either an `EO` object (edge object) or\n * a `VertexKey` (key of a vertex).\n * @param {VertexKey} [destVertexKey] - The `destVertexKey` parameter is an optional parameter that\n * represents the key of the destination vertex of the edge. It is used to specify the destination\n * vertex when the `edge` parameter is a vertex key. If `destVertexKey` is not provided, the function\n * assumes that the `edge`\n * @returns the removed edge (EO) or undefined if no edge was removed.\n */\n deleteEdge(edgeOrSrcVertexKey: EO | VertexKey, destVertexKey?: VertexKey): EO | undefined {\n let removed: EO | undefined = undefined;\n let src: VO | undefined, dest: VO | undefined;\n if (this.isVertexKey(edgeOrSrcVertexKey)) {\n if (this.isVertexKey(destVertexKey)) {\n src = this._getVertex(edgeOrSrcVertexKey);\n dest = this._getVertex(destVertexKey);\n } else {\n return;\n }\n } else {\n src = this._getVertex(edgeOrSrcVertexKey.src);\n dest = this._getVertex(edgeOrSrcVertexKey.dest);\n }\n\n if (src && dest) {\n const srcOutEdges = this._outEdgeMap.get(src);\n if (srcOutEdges && srcOutEdges.length > 0) {\n arrayRemove(srcOutEdges, (edge: EO) => edge.src === src!.key && edge.dest === dest?.key);\n }\n\n const destInEdges = this._inEdgeMap.get(dest);\n if (destInEdges && destInEdges.length > 0) {\n removed = arrayRemove(destInEdges, (edge: EO) => edge.src === src!.key && edge.dest === dest!.key)[0];\n }\n }\n\n return removed;\n }\n\n /**\n * Time Complexity: O(1) - Constant time for Map operations.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n *\n * The `deleteVertex` function removes a vertex from a graph by its ID or by the vertex object itself.\n * @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can be either a vertex object (`VO`) or a vertex ID\n * (`VertexKey`).\n * @returns The method is returning a boolean value.\n */\n deleteVertex(vertexOrKey: VO | VertexKey): boolean {\n let vertexKey: VertexKey;\n let vertex: VO | undefined;\n if (this.isVertexKey(vertexOrKey)) {\n vertex = this.getVertex(vertexOrKey);\n vertexKey = vertexOrKey;\n } else {\n vertex = vertexOrKey;\n vertexKey = this._getVertexKey(vertexOrKey);\n }\n\n if (vertex) {\n const neighbors = this.getNeighbors(vertex);\n for (const neighbor of neighbors) {\n // this._inEdgeMap.delete(neighbor);\n this.deleteEdgeSrcToDest(vertex, neighbor);\n }\n this._outEdgeMap.delete(vertex);\n this._inEdgeMap.delete(vertex);\n }\n\n return this._vertexMap.delete(vertexKey);\n }\n\n /**\n * Time Complexity: O(|E|) where |E| is the number of edgeMap\n * Space Complexity: O(1)\n *\n * The function removes edgeMap between two vertexMap and returns the removed edgeMap.\n * @param {VertexKey | VO} v1 - The parameter `v1` can be either a `VertexKey` or a `VO`. A `VertexKey` represents the\n * unique identifier of a vertex in a graph, while `VO` represents the actual vertex object.\n * @param {VertexKey | VO} v2 - The parameter `v2` represents either a `VertexKey` or a `VO` object. It is used to specify\n * the second vertex in the edge that needs to be removed.\n * @returns an array of removed edgeMap (EO[]).\n */\n deleteEdgesBetween(v1: VertexKey | VO, v2: VertexKey | VO): EO[] {\n const removed: EO[] = [];\n\n if (v1 && v2) {\n const v1ToV2 = this.deleteEdgeSrcToDest(v1, v2);\n const v2ToV1 = this.deleteEdgeSrcToDest(v2, v1);\n\n if (v1ToV2) removed.push(v1ToV2);\n if (v2ToV1) removed.push(v2ToV1);\n }\n\n return removed;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `incomingEdgesOf` returns an array of incoming edgeMap for a given vertex or vertex ID.\n * @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can be either a vertex object (`VO`) or a vertex ID\n * (`VertexKey`).\n * @returns The method `incomingEdgesOf` returns an array of edgeMap (`EO[]`).\n */\n incomingEdgesOf(vertexOrKey: VO | VertexKey): EO[] {\n const target = this._getVertex(vertexOrKey);\n if (target) {\n return this.inEdgeMap.get(target) || [];\n }\n return [];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `outgoingEdgesOf` returns an array of outgoing edgeMap from a given vertex or vertex ID.\n * @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can accept either a vertex object (`VO`) or a vertex ID\n * (`VertexKey`).\n * @returns The method `outgoingEdgesOf` returns an array of edgeMap (`EO[]`).\n */\n outgoingEdgesOf(vertexOrKey: VO | VertexKey): EO[] {\n const target = this._getVertex(vertexOrKey);\n if (target) {\n return this._outEdgeMap.get(target) || [];\n }\n return [];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"degreeOf\" returns the total degree of a vertex, which is the sum of its out-degree and in-degree.\n * @param {VertexKey | VO} vertexOrKey - The parameter `vertexOrKey` can be either a `VertexKey` or a `VO`.\n * @returns The sum of the out-degree and in-degree of the specified vertex or vertex ID.\n */\n degreeOf(vertexOrKey: VertexKey | VO): number {\n return this.outDegreeOf(vertexOrKey) + this.inDegreeOf(vertexOrKey);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"inDegreeOf\" returns the number of incoming edgeMap for a given vertex.\n * @param {VertexKey | VO} vertexOrKey - The parameter `vertexOrKey` can be either a `VertexKey` or a `VO`.\n * @returns The number of incoming edgeMap of the specified vertex or vertex ID.\n */\n inDegreeOf(vertexOrKey: VertexKey | VO): number {\n return this.incomingEdgesOf(vertexOrKey).length;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `outDegreeOf` returns the number of outgoing edgeMap from a given vertex.\n * @param {VertexKey | VO} vertexOrKey - The parameter `vertexOrKey` can be either a `VertexKey` or a `VO`.\n * @returns The number of outgoing edgeMap from the specified vertex or vertex ID.\n */\n outDegreeOf(vertexOrKey: VertexKey | VO): number {\n return this.outgoingEdgesOf(vertexOrKey).length;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"edgesOf\" returns an array of both outgoing and incoming edgeMap of a given vertex or vertex ID.\n * @param {VertexKey | VO} vertexOrKey - The parameter `vertexOrKey` can be either a `VertexKey` or a `VO`.\n * @returns The function `edgesOf` returns an array of edgeMap.\n */\n edgesOf(vertexOrKey: VertexKey | VO): EO[] {\n return [...this.outgoingEdgesOf(vertexOrKey), ...this.incomingEdgesOf(vertexOrKey)];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"getEdgeSrc\" returns the source vertex of an edge, or undefined if the edge does not exist.\n * @param {EO} e - The parameter \"e\" is of type EO, which represents an edge in a graph.\n * @returns either a vertex object (VO) or undefined.\n */\n getEdgeSrc(e: EO): VO | undefined {\n return this._getVertex(e.src);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"getEdgeDest\" returns the destination vertex of an edge.\n * @param {EO} e - The parameter \"e\" is of type \"EO\", which represents an edge in a graph.\n * @returns either a vertex object of type VO or undefined.\n */\n getEdgeDest(e: EO): VO | undefined {\n return this._getVertex(e.dest);\n }\n\n /**\n * Time Complexity: O(|E|) where |E| is the number of edgeMap\n * Space Complexity: O(1)\n *\n * The function `getDestinations` returns an array of destination vertexMap connected to a given vertex.\n * @param {VO | VertexKey | undefined} vertex - The `vertex` parameter represents the starting vertex from which we want to\n * find the destinations. It can be either a `VO` object, a `VertexKey` value, or `undefined`.\n * @returns an array of vertexMap (VO[]).\n */\n getDestinations(vertex: VO | VertexKey | undefined): VO[] {\n if (vertex === undefined) {\n return [];\n }\n const destinations: VO[] = [];\n const outgoingEdges = this.outgoingEdgesOf(vertex);\n for (const outEdge of outgoingEdges) {\n const child = this.getEdgeDest(outEdge);\n if (child) {\n destinations.push(child);\n }\n }\n return destinations;\n }\n\n /**\n * Time Complexity: O(|V| + |E|) where |V| is the number of vertexMap and |E| is the number of edgeMap\n * Space Complexity: O(|V|)\n *\n * The `topologicalSort` function performs a topological sort on a graph and returns an array of vertexMap or vertex IDs\n * in the sorted order, or undefined if the graph contains a cycle.\n * @param {'vertex' | 'key'} [propertyName] - The `propertyName` parameter is an optional parameter that specifies the\n * property to use for sorting the vertexMap. It can have two possible values: 'vertex' or 'key'. If 'vertex' is\n * specified, the vertexMap themselves will be used for sorting. If 'key' is specified, the ids of\n * @returns an array of vertexMap or vertex IDs in topological order. If there is a cycle in the graph, it returns undefined.\n */\n topologicalSort(propertyName?: 'vertex' | 'key'): Array<VO | VertexKey> | undefined {\n propertyName = propertyName ?? 'key';\n // When judging whether there is a cycle in the undirected graph, all nodes with degree of **<= 1** are enqueued\n // When judging whether there is a cycle in the directed graph, all nodes with **in degree = 0** are enqueued\n const statusMap: Map<VO | VertexKey, TopologicalStatus> = new Map<VO | VertexKey, TopologicalStatus>();\n for (const entry of this.vertexMap) {\n statusMap.set(entry[1], 0);\n }\n\n let sorted: (VO | VertexKey)[] = [];\n let hasCycle = false;\n const dfs = (cur: VO | VertexKey) => {\n statusMap.set(cur, 1);\n const children = this.getDestinations(cur);\n for (const child of children) {\n const childStatus = statusMap.get(child);\n if (childStatus === 0) {\n dfs(child);\n } else if (childStatus === 1) {\n hasCycle = true;\n }\n }\n statusMap.set(cur, 2);\n sorted.push(cur);\n };\n\n for (const entry of this.vertexMap) {\n if (statusMap.get(entry[1]) === 0) {\n dfs(entry[1]);\n }\n }\n\n if (hasCycle) return undefined;\n\n if (propertyName === 'key') sorted = sorted.map(vertex => (vertex instanceof DirectedVertex ? vertex.key : vertex));\n return sorted.reverse();\n }\n\n /**\n * Time Complexity: O(|E|) where |E| is the number of edgeMap\n * Space Complexity: O(|E|)\n *\n * The `edgeSet` function returns an array of all the edgeMap in the graph.\n * @returns The `edgeSet()` method returns an array of edgeMap (`EO[]`).\n */\n edgeSet(): EO[] {\n let edgeMap: EO[] = [];\n this._outEdgeMap.forEach(outEdges => {\n edgeMap = [...edgeMap, ...outEdges];\n });\n return edgeMap;\n }\n\n /**\n * Time Complexity: O(|E|) where |E| is the number of edgeMap\n * Space Complexity: O(1)\n *\n * The function `getNeighbors` returns an array of neighboring vertexMap of a given vertex or vertex ID in a graph.\n * @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can be either a vertex object (`VO`) or a vertex ID\n * (`VertexKey`).\n * @returns an array of vertexMap (VO[]).\n */\n getNeighbors(vertexOrKey: VO | VertexKey): VO[] {\n const neighbors: VO[] = [];\n const vertex = this._getVertex(vertexOrKey);\n if (vertex) {\n const outEdges = this.outgoingEdgesOf(vertex);\n for (const outEdge of outEdges) {\n const neighbor = this._getVertex(outEdge.dest);\n // TODO after no-non-undefined-assertion not ensure the logic\n if (neighbor) {\n neighbors.push(neighbor);\n }\n }\n }\n return neighbors;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"getEndsOfEdge\" returns the source and destination vertexMap of an edge if it exists in the graph,\n * otherwise it returns undefined.\n * @param {EO} edge - The parameter `edge` is of type `EO`, which represents an edge in a graph.\n * @returns The function `getEndsOfEdge` returns an array containing two vertexMap `[VO, VO]` if the edge exists in the\n * graph. If the edge does not exist, it returns `undefined`.\n */\n getEndsOfEdge(edge: EO): [VO, VO] | undefined {\n if (!this.hasEdge(edge.src, edge.dest)) {\n return undefined;\n }\n const v1 = this._getVertex(edge.src);\n const v2 = this._getVertex(edge.dest);\n if (v1 && v2) {\n return [v1, v2];\n } else {\n return undefined;\n }\n }\n\n /**\n * The isEmpty function checks if the graph is empty.\n *\n * @return A boolean value\n */\n isEmpty(): boolean {\n return this.vertexMap.size === 0 && this.inEdgeMap.size === 0 && this.outEdgeMap.size === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear function resets the vertex map, in-edge map, and out-edge map.\n */\n clear() {\n this._vertexMap = new Map<VertexKey, VO>();\n this._inEdgeMap = new Map<VO, EO[]>();\n this._outEdgeMap = new Map<VO, EO[]>();\n }\n\n /**\n * The clone function creates a new DirectedGraph object with the same vertices and edges as the original.\n *\n * @return A new instance of the directedgraph class\n */\n clone(): DirectedGraph<V, E, VO, EO> {\n const cloned = new DirectedGraph<V, E, VO, EO>();\n cloned.vertexMap = new Map<VertexKey, VO>(this.vertexMap);\n cloned.inEdgeMap = new Map<VO, EO[]>(this.inEdgeMap);\n cloned.outEdgeMap = new Map<VO, EO[]>(this.outEdgeMap);\n return cloned;\n }\n\n /**\n * Time Complexity: O(V + E)\n * Space Complexity: O(V)\n * Tarjan is an algorithm based on dfs,which is used to solve the connectivity problem of graphs.\n * Tarjan can find the SSC(strongly connected components), articulation points, and bridges of directed graphs.\n *\n * The function `tarjan` implements the Tarjan's algorithm to find strongly connected components in a\n * graph.\n * @returns The function `tarjan()` returns an object with three properties: `dfnMap`, `lowMap`, and\n * `SCCs`.\n */\n tarjan(): { dfnMap: Map<VO, number>; lowMap: Map<VO, number>; SCCs: Map<number, VO[]> } {\n const dfnMap = new Map<VO, number>();\n const lowMap = new Map<VO, number>();\n const SCCs = new Map<number, VO[]>();\n\n let time = 0;\n\n const stack: VO[] = [];\n const inStack: Set<VO> = new Set();\n\n const dfs = (vertex: VO) => {\n dfnMap.set(vertex, time);\n lowMap.set(vertex, time);\n time++;\n\n stack.push(vertex);\n inStack.add(vertex);\n\n const neighbors = this.getNeighbors(vertex);\n for (const neighbor of neighbors) {\n if (!dfnMap.has(neighbor)) {\n dfs(neighbor);\n lowMap.set(vertex, Math.min(lowMap.get(vertex)!, lowMap.get(neighbor)!));\n } else if (inStack.has(neighbor)) {\n lowMap.set(vertex, Math.min(lowMap.get(vertex)!, dfnMap.get(neighbor)!));\n }\n }\n\n if (dfnMap.get(vertex) === lowMap.get(vertex)) {\n const SCC: VO[] = [];\n let poppedVertex: VO | undefined;\n\n do {\n poppedVertex = stack.pop();\n inStack.delete(poppedVertex!);\n SCC.push(poppedVertex!);\n } while (poppedVertex !== vertex);\n\n SCCs.set(SCCs.size, SCC);\n }\n };\n\n for (const vertex of this.vertexMap.values()) {\n if (!dfnMap.has(vertex)) {\n dfs(vertex);\n }\n }\n\n return { dfnMap, lowMap, SCCs };\n }\n\n /**\n * Time Complexity: O(V + E) - Depends on the implementation (Tarjan's algorithm).\n * Space Complexity: O(V) - Depends on the implementation (Tarjan's algorithm).\n *\n * The function returns a map that associates each vertex object with its corresponding depth-first\n * number.\n * @returns A Map object with keys of type VO and values of type number.\n */\n getDFNMap(): Map<VO, number> {\n return this.tarjan().dfnMap;\n }\n\n /**\n * The function returns a Map object that contains the low values of each vertex in a Tarjan\n * algorithm.\n * @returns The method `getLowMap()` is returning a `Map` object with keys of type `VO` and values of\n * type `number`.\n */\n getLowMap(): Map<VO, number> {\n return this.tarjan().lowMap;\n }\n\n /**\n * The function \"getSCCs\" returns a map of strongly connected components (SCCs) using the Tarjan\n * algorithm.\n * @returns a map where the keys are numbers and the values are arrays of VO objects.\n */\n getSCCs(): Map<number, VO[]> {\n return this.tarjan().SCCs;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_addEdge` adds an edge to a graph if the source and destination vertexMap exist.\n * @param {EO} edge - The parameter `edge` is of type `EO`, which represents an edge in a graph. It is the edge that\n * needs to be added to the graph.\n * @returns a boolean value. It returns true if the edge was successfully added to the graph, and false if either the\n * source or destination vertex does not exist in the graph.\n */\n protected _addEdge(edge: EO): boolean {\n if (!(this.hasVertex(edge.src) && this.hasVertex(edge.dest))) {\n return false;\n }\n\n const srcVertex = this._getVertex(edge.src);\n const destVertex = this._getVertex(edge.dest);\n\n // TODO after no-non-undefined-assertion not ensure the logic\n if (srcVertex && destVertex) {\n const srcOutEdges = this._outEdgeMap.get(srcVertex);\n if (srcOutEdges) {\n srcOutEdges.push(edge);\n } else {\n this._outEdgeMap.set(srcVertex, [edge]);\n }\n\n const destInEdges = this._inEdgeMap.get(destVertex);\n if (destInEdges) {\n destInEdges.push(edge);\n } else {\n this._inEdgeMap.set(destVertex, [edge]);\n }\n return true;\n } else {\n return false;\n }\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { VertexKey } from '../../types';\nimport { IGraph } from '../../interfaces';\nimport { AbstractEdge, AbstractGraph, AbstractVertex } from './abstract-graph';\nimport { arrayRemove } from '../../utils';\n\nexport class UndirectedVertex<V = any> extends AbstractVertex<V> {\n /**\n * The constructor function initializes a vertex with an optional value.\n * @param {VertexKey} key - The `key` parameter is of type `VertexKey` and represents the identifier of the vertex. It is\n * used to uniquely identify the vertex within a graph or network.\n * @param {V} [value] - The \"value\" parameter is an optional parameter of type V. It is used to initialize the value of the\n * vertex. If no value is provided, the vertex will be initialized with a default value.\n */\n constructor(key: VertexKey, value?: V) {\n super(key, value);\n }\n}\n\nexport class UndirectedEdge<E = number> extends AbstractEdge<E> {\n endpoints: [VertexKey, VertexKey];\n\n /**\n * The constructor function creates an instance of a class with two vertex IDs, an optional weight, and an optional\n * value.\n * @param {VertexKey} v1 - The first vertex ID of the edge.\n * @param {VertexKey} v2 - The parameter `v2` is a `VertexKey`, which represents the identifier of the second vertex in a\n * graph edge.\n * @param {number} [weight] - The weight parameter is an optional number that represents the weight of the edge.\n * @param {E} [value] - The \"value\" parameter is an optional parameter of type E. It is used to store a value associated\n * with the edge.\n */\n constructor(v1: VertexKey, v2: VertexKey, weight?: number, value?: E) {\n super(weight, value);\n this.endpoints = [v1, v2];\n }\n}\n\n/**\n *\n */\nexport class UndirectedGraph<\n V = any,\n E = any,\n VO extends UndirectedVertex<V> = UndirectedVertex<V>,\n EO extends UndirectedEdge<E> = UndirectedEdge<E>\n >\n extends AbstractGraph<V, E, VO, EO>\n implements IGraph<V, E, VO, EO>\n{\n /**\n * The constructor initializes a new Map object to store edgeMap.\n */\n constructor() {\n super();\n this._edgeMap = new Map<VO, EO[]>();\n }\n\n protected _edgeMap: Map<VO, EO[]>;\n\n get edgeMap(): Map<VO, EO[]> {\n return this._edgeMap;\n }\n\n set edgeMap(v: Map<VO, EO[]>) {\n this._edgeMap = v;\n }\n\n /**\n * The function creates a new vertex with an optional value and returns it.\n * @param {VertexKey} key - The `key` parameter is the unique identifier for the vertex. It is used to distinguish one\n * vertex from another in the graph.\n * @param [value] - The `value` parameter is an optional value that can be assigned to the vertex. If a value is provided,\n * it will be used as the value of the vertex. If no value is provided, the `key` parameter will be used as the value of\n * the vertex.\n * @returns The method is returning a new instance of the `UndirectedVertex` class, casted as type `VO`.\n */\n override createVertex(key: VertexKey, value?: VO['value']): VO {\n return new UndirectedVertex(key, value ?? key) as VO;\n }\n\n /**\n * The function creates an undirected edge between two vertexMap with an optional weight and value.\n * @param {VertexKey} v1 - The parameter `v1` represents the first vertex of the edge.\n * @param {VertexKey} v2 - The parameter `v2` represents the second vertex of the edge.\n * @param {number} [weight] - The `weight` parameter is an optional number that represents the weight of the edge. If\n * no weight is provided, it defaults to 1.\n * @param [value] - The `value` parameter is an optional value that can be assigned to the edge. It can be of any type and\n * is used to store additional information or data associated with the edge.\n * @returns a new instance of the `UndirectedEdge` class, which is casted as type `EO`.\n */\n override createEdge(v1: VertexKey, v2: VertexKey, weight?: number, value?: EO['value']): EO {\n return new UndirectedEdge(v1, v2, weight ?? 1, value) as EO;\n }\n\n /**\n * Time Complexity: O(|E|), where |E| is the number of edgeMap incident to the given vertex.\n * Space Complexity: O(1)\n *\n * The function `getEdge` returns the first edge that connects two endpoints, or undefined if no such edge exists.\n * @param {VO | VertexKey | undefined} v1 - The parameter `v1` represents a vertex or vertex ID. It can be of type `VO` (vertex\n * object), `undefined`, or `VertexKey` (a string or number representing the ID of a vertex).\n * @param {VO | VertexKey | undefined} v2 - The parameter `v2` represents a vertex or vertex ID. It can be of type `VO` (vertex\n * object), `undefined`, or `VertexKey` (vertex ID).\n * @returns an edge (EO) or undefined.\n */\n getEdge(v1: VO | VertexKey | undefined, v2: VO | VertexKey | undefined): EO | undefined {\n let edgeMap: EO[] | undefined = [];\n\n if (v1 !== undefined && v2 !== undefined) {\n const vertex1: VO | undefined = this._getVertex(v1);\n const vertex2: VO | undefined = this._getVertex(v2);\n\n if (vertex1 && vertex2) {\n edgeMap = this._edgeMap.get(vertex1)?.filter(e => e.endpoints.includes(vertex2.key));\n }\n }\n\n return edgeMap ? edgeMap[0] || undefined : undefined;\n }\n\n /**\n * Time Complexity: O(|E|), where |E| is the number of edgeMap incident to the given vertex.\n * Space Complexity: O(1)\n *\n * The function removes an edge between two vertexMap in a graph and returns the removed edge.\n * @param {VO | VertexKey} v1 - The parameter `v1` represents either a vertex object (`VO`) or a vertex ID (`VertexKey`).\n * @param {VO | VertexKey} v2 - VO | VertexKey - This parameter can be either a vertex object (VO) or a vertex ID\n * (VertexKey). It represents the second vertex of the edge that needs to be removed.\n * @returns the removed edge (EO) if it exists, or undefined if either of the endpoints (VO) does not exist.\n */\n deleteEdgeBetween(v1: VO | VertexKey, v2: VO | VertexKey): EO | undefined {\n const vertex1: VO | undefined = this._getVertex(v1);\n const vertex2: VO | undefined = this._getVertex(v2);\n\n if (!vertex1 || !vertex2) {\n return undefined;\n }\n\n const v1Edges = this._edgeMap.get(vertex1);\n let removed: EO | undefined = undefined;\n if (v1Edges) {\n removed = arrayRemove<EO>(v1Edges, (e: EO) => e.endpoints.includes(vertex2.key))[0] || undefined;\n }\n const v2Edges = this._edgeMap.get(vertex2);\n if (v2Edges) {\n arrayRemove<EO>(v2Edges, (e: EO) => e.endpoints.includes(vertex1.key));\n }\n return removed;\n }\n\n /**\n * Time Complexity: O(E), where E is the number of edgeMap incident to the given vertex.\n * Space Complexity: O(1)\n *\n * The function `deleteEdge` deletes an edge between two endpoints in a graph.\n * @param {EO | VertexKey} edgeOrOneSideVertexKey - The parameter `edgeOrOneSideVertexKey` can be\n * either an edge object or a vertex key.\n * @param {VertexKey} [otherSideVertexKey] - The parameter `otherSideVertexKey` is an optional\n * parameter that represents the key of the vertex on the other side of the edge. It is used when the\n * `edgeOrOneSideVertexKey` parameter is a vertex key, and it specifies the key of the vertex on the\n * other side of the\n * @returns The `deleteEdge` function returns either the deleted edge object (EO) or `undefined`.\n */\n deleteEdge(edgeOrOneSideVertexKey: EO | VertexKey, otherSideVertexKey?: VertexKey): EO | undefined {\n let oneSide: VO | undefined, otherSide: VO | undefined;\n if (this.isVertexKey(edgeOrOneSideVertexKey)) {\n if (this.isVertexKey(otherSideVertexKey)) {\n oneSide = this._getVertex(edgeOrOneSideVertexKey);\n otherSide = this._getVertex(otherSideVertexKey);\n } else {\n return;\n }\n } else {\n oneSide = this._getVertex(edgeOrOneSideVertexKey.endpoints[0]);\n otherSide = this._getVertex(edgeOrOneSideVertexKey.endpoints[1]);\n }\n\n if (oneSide && otherSide) {\n return this.deleteEdgeBetween(oneSide, otherSide);\n } else {\n return;\n }\n }\n\n /**\n * Time Complexity: O(1) - Constant time for Map operations.\n * Space Complexity: O(1) - Constant space, as it creates only a few variables.\n *\n * The `deleteVertex` function removes a vertex from a graph by its ID or by the vertex object itself.\n * @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can be either a vertex object (`VO`) or a vertex ID\n * (`VertexKey`).\n * @returns The method is returning a boolean value.\n */\n deleteVertex(vertexOrKey: VO | VertexKey): boolean {\n let vertexKey: VertexKey;\n let vertex: VO | undefined;\n if (this.isVertexKey(vertexOrKey)) {\n vertex = this.getVertex(vertexOrKey);\n vertexKey = vertexOrKey;\n } else {\n vertex = vertexOrKey;\n vertexKey = this._getVertexKey(vertexOrKey);\n }\n\n const neighbors = this.getNeighbors(vertexOrKey);\n\n if (vertex) {\n neighbors.forEach(neighbor => {\n const neighborEdges = this._edgeMap.get(neighbor);\n if (neighborEdges) {\n const restEdges = neighborEdges.filter(edge => {\n return !edge.endpoints.includes(vertexKey);\n });\n this._edgeMap.set(neighbor, restEdges);\n }\n });\n this._edgeMap.delete(vertex);\n }\n\n return this._vertexMap.delete(vertexKey);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `degreeOf` returns the degree of a vertex in a graph, which is the number of edgeMap connected to that\n * vertex.\n * @param {VertexKey | VO} vertexOrKey - The parameter `vertexOrKey` can be either a `VertexKey` or a `VO`.\n * @returns The function `degreeOf` returns the degree of a vertex in a graph. The degree of a vertex is the number of\n * edgeMap connected to that vertex.\n */\n degreeOf(vertexOrKey: VertexKey | VO): number {\n const vertex = this._getVertex(vertexOrKey);\n if (vertex) {\n return this._edgeMap.get(vertex)?.length || 0;\n } else {\n return 0;\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function returns the edgeMap of a given vertex or vertex ID.\n * @param {VertexKey | VO} vertexOrKey - The parameter `vertexOrKey` can be either a `VertexKey` or a `VO`. A `VertexKey` is a\n * unique identifier for a vertex in a graph, while `VO` represents the type of the vertex.\n * @returns an array of edgeMap.\n */\n edgesOf(vertexOrKey: VertexKey | VO): EO[] {\n const vertex = this._getVertex(vertexOrKey);\n if (vertex) {\n return this._edgeMap.get(vertex) || [];\n } else {\n return [];\n }\n }\n\n /**\n * Time Complexity: O(|V| + |E|), where |V| is the number of vertexMap and |E| is the number of edgeMap.\n * Space Complexity: O(|E|)\n *\n * The function \"edgeSet\" returns an array of unique edgeMap from a set of edgeMap.\n * @returns The method `edgeSet()` returns an array of type `EO[]`.\n */\n edgeSet(): EO[] {\n const edgeSet: Set<EO> = new Set();\n this._edgeMap.forEach(edgeMap => {\n edgeMap.forEach(edge => {\n edgeSet.add(edge);\n });\n });\n return [...edgeSet];\n }\n\n /**\n * Time Complexity: O(|V| + |E|), where |V| is the number of vertexMap and |E| is the number of edgeMap.\n * Space Complexity: O(|E|)\n *\n * The function \"getNeighbors\" returns an array of neighboring endpoints for a given vertex or vertex ID.\n * @param {VO | VertexKey} vertexOrKey - The parameter `vertexOrKey` can be either a vertex object (`VO`) or a vertex ID\n * (`VertexKey`).\n * @returns an array of vertexMap (VO[]).\n */\n getNeighbors(vertexOrKey: VO | VertexKey): VO[] {\n const neighbors: VO[] = [];\n const vertex = this._getVertex(vertexOrKey);\n if (vertex) {\n const neighborEdges = this.edgesOf(vertex);\n for (const edge of neighborEdges) {\n const neighbor = this._getVertex(edge.endpoints.filter(e => e !== vertex.key)[0]);\n if (neighbor) {\n neighbors.push(neighbor);\n }\n }\n }\n return neighbors;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"getEndsOfEdge\" returns the endpoints at the ends of an edge if the edge exists in the graph, otherwise\n * it returns undefined.\n * @param {EO} edge - The parameter \"edge\" is of type EO, which represents an edge in a graph.\n * @returns The function `getEndsOfEdge` returns an array containing two endpoints `[VO, VO]` if the edge exists in the\n * graph. If the edge does not exist, it returns `undefined`.\n */\n getEndsOfEdge(edge: EO): [VO, VO] | undefined {\n if (!this.hasEdge(edge.endpoints[0], edge.endpoints[1])) {\n return undefined;\n }\n const v1 = this._getVertex(edge.endpoints[0]);\n const v2 = this._getVertex(edge.endpoints[1]);\n if (v1 && v2) {\n return [v1, v2];\n } else {\n return undefined;\n }\n }\n\n /**\n * The isEmpty function checks if the graph is empty.\n * @return True if the graph is empty and false otherwise\n */\n isEmpty(): boolean {\n return this.vertexMap.size === 0 && this.edgeMap.size === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear function resets the vertex and edge maps to empty maps.\n */\n clear() {\n this._vertexMap = new Map<VertexKey, VO>();\n this._edgeMap = new Map<VO, EO[]>();\n }\n\n /**\n * The clone function creates a new UndirectedGraph object and copies the\n * vertexMap and edgeMap from this graph to the new one. This is done by\n * assigning each of these properties to their respective counterparts in the\n * cloned graph. The clone function returns a reference to this newly created,\n * cloned UndirectedGraph object.\n *\n * @return A new instance of the undirectedgraph class\n */\n clone(): UndirectedGraph<V, E, VO, EO> {\n const cloned = new UndirectedGraph<V, E, VO, EO>();\n cloned.vertexMap = new Map<VertexKey, VO>(this.vertexMap);\n cloned.edgeMap = new Map<VO, EO[]>(this.edgeMap);\n return cloned;\n }\n\n /**\n * Time Complexity: O(V + E)\n * Space Complexity: O(V)\n * Tarjan is an algorithm based on dfs,which is used to solve the connectivity problem of graphs.\n * 1. Tarjan can find the articulation points and bridges(critical edgeMap) of undirected graphs in linear time\n *\n * The function `tarjan` implements the Tarjan's algorithm to find bridges and cut vertices in a\n * graph.\n * @returns The function `tarjan()` returns an object with the following properties:\n */\n tarjan(): { dfnMap: Map<VO, number>; lowMap: Map<VO, number>; bridges: EO[]; cutVertices: VO[] } {\n const dfnMap = new Map<VO, number>();\n const lowMap = new Map<VO, number>();\n const bridges: EO[] = [];\n const cutVertices: VO[] = [];\n\n let time = 0;\n\n const dfs = (vertex: VO, parent: VO | undefined) => {\n dfnMap.set(vertex, time);\n lowMap.set(vertex, time);\n time++;\n\n const neighbors = this.getNeighbors(vertex);\n let childCount = 0;\n\n for (const neighbor of neighbors) {\n if (!dfnMap.has(neighbor)) {\n childCount++;\n dfs(neighbor, vertex);\n lowMap.set(vertex, Math.min(lowMap.get(vertex)!, lowMap.get(neighbor)!));\n\n if (lowMap.get(neighbor)! > dfnMap.get(vertex)!) {\n // Found a bridge\n const edge = this.getEdge(vertex, neighbor);\n if (edge) {\n bridges.push(edge);\n }\n }\n\n if (parent !== undefined && lowMap.get(neighbor)! >= dfnMap.get(vertex)!) {\n // Found an articulation point\n cutVertices.push(vertex);\n }\n } else if (neighbor !== parent) {\n lowMap.set(vertex, Math.min(lowMap.get(vertex)!, dfnMap.get(neighbor)!));\n }\n }\n\n if (parent === undefined && childCount > 1) {\n // Special case for root in DFS tree\n cutVertices.push(vertex);\n }\n };\n\n for (const vertex of this.vertexMap.values()) {\n if (!dfnMap.has(vertex)) {\n dfs(vertex, undefined);\n }\n }\n\n return {\n dfnMap,\n lowMap,\n bridges,\n cutVertices\n };\n }\n\n /**\n * The function \"getBridges\" returns an array of bridges in a graph using the Tarjan's algorithm.\n * @returns The function `getBridges()` is returning the bridges found using the Tarjan's algorithm.\n */\n getBridges() {\n return this.tarjan().bridges;\n }\n\n /**\n * The function \"getCutVertices\" returns an array of cut vertices using the Tarjan's algorithm.\n * @returns the cut vertices found using the Tarjan's algorithm.\n */\n getCutVertices() {\n return this.tarjan().cutVertices;\n }\n\n /**\n * The function returns the dfnMap property of the result of the tarjan() function.\n * @returns the `dfnMap` property of the result of calling the `tarjan()` function.\n */\n getDFNMap() {\n return this.tarjan().dfnMap;\n }\n\n /**\n * The function returns the lowMap property of the result of the tarjan() function.\n * @returns the lowMap property of the result of calling the tarjan() function.\n */\n getLowMap() {\n return this.tarjan().lowMap;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function adds an edge to the graph by updating the adjacency list with the vertexMap of the edge.\n * @param {EO} edge - The parameter \"edge\" is of type EO, which represents an edge in a graph.\n * @returns a boolean value.\n */\n protected _addEdge(edge: EO): boolean {\n for (const end of edge.endpoints) {\n const endVertex = this._getVertex(end);\n if (endVertex === undefined) return false;\n if (endVertex) {\n const edgeMap = this._edgeMap.get(endVertex);\n if (edgeMap) {\n edgeMap.push(edge);\n } else {\n this._edgeMap.set(endVertex, [edge]);\n }\n }\n }\n return true;\n }\n}\n","import type { MapGraphCoordinate, VertexKey } from '../../types';\nimport { DirectedEdge, DirectedGraph, DirectedVertex } from './directed-graph';\n\nexport class MapVertex<V = any> extends DirectedVertex<V> {\n lat: number;\n long: number;\n\n /**\n * The constructor function initializes an object with an key, latitude, longitude, and an optional value.\n * @param {VertexKey} key - The `key` parameter is of type `VertexKey` and represents the identifier of the vertex.\n * @param {number} lat - The \"lat\" parameter represents the latitude of a vertex. Latitude is a geographic coordinate\n * that specifies the north-south position of a point on the Earth's surface. It is measured in degrees, with positive\n * values representing points north of the equator and negative values representing points south of the equator.\n * @param {number} long - The \"long\" parameter represents the longitude of a location. Longitude is a geographic\n * coordinate that specifies the east-west position of a point on the Earth's surface. It is measured in degrees, with\n * values ranging from -180 to 180.\n * @param {V} [value] - The \"value\" parameter is an optional value of type V. It is not required to be provided when\n * creating an instance of the class.\n */\n constructor(key: VertexKey, value: V, lat: number, long: number) {\n super(key, value);\n this.lat = lat;\n this.long = long;\n }\n}\n\nexport class MapEdge<E = any> extends DirectedEdge<E> {\n /**\n * The constructor function initializes a new instance of a class with the given source, destination, weight, and\n * value.\n * @param {VertexKey} src - The `src` parameter is the source vertex ID. It represents the starting point of an edge in\n * a graph.\n * @param {VertexKey} dest - The `dest` parameter is the identifier of the destination vertex for an edge.\n * @param {number} [weight] - The weight parameter is an optional number that represents the weight of the edge.\n * @param {E} [value] - The \"value\" parameter is an optional parameter of type E. It is used to store additional\n * information or data associated with the edge.\n */\n constructor(src: VertexKey, dest: VertexKey, weight?: number, value?: E) {\n super(src, dest, weight, value);\n }\n}\n\n/**\n *\n */\nexport class MapGraph<\n V = any,\n E = any,\n VO extends MapVertex<V> = MapVertex<V>,\n EO extends MapEdge<E> = MapEdge<E>\n> extends DirectedGraph<V, E, VO, EO> {\n /**\n * The constructor function initializes the originCoord and bottomRight properties of a MapGraphCoordinate object.\n * @param {MapGraphCoordinate} originCoord - The `originCoord` parameter is a `MapGraphCoordinate` object that represents the\n * starting point or reference point of the map graph. It defines the coordinates of the top-left corner of the map\n * graph.\n * @param {MapGraphCoordinate} [bottomRight] - The `bottomRight` parameter is an optional parameter of type\n * `MapGraphCoordinate`. It represents the bottom right coordinate of a map graph. If this parameter is not provided,\n * it will default to `undefined`.\n */\n constructor(originCoord: MapGraphCoordinate, bottomRight?: MapGraphCoordinate) {\n super();\n this._originCoord = originCoord;\n this._bottomRight = bottomRight;\n }\n\n protected _originCoord: MapGraphCoordinate = [0, 0];\n\n get originCoord(): MapGraphCoordinate {\n return this._originCoord;\n }\n\n protected _bottomRight: MapGraphCoordinate | undefined;\n\n get bottomRight(): MapGraphCoordinate | undefined {\n return this._bottomRight;\n }\n\n /**\n * The function creates a new vertex with the given key, value, latitude, and longitude.\n * @param {VertexKey} key - The key parameter is the unique identifier for the vertex. It is of type VertexKey, which could\n * be a string or a number depending on how you define it in your code.\n * @param [value] - The `value` parameter is an optional value that can be assigned to the `value` property of the vertex. It\n * is of type `V`, which means it should be of the same type as the `value` property of the vertex class `VO`.\n * @param {number} lat - The `lat` parameter represents the latitude of the vertex. It is a number that specifies the\n * position of the vertex on the Earth's surface in the north-south direction.\n * @param {number} long - The `long` parameter represents the longitude coordinate of the vertex.\n * @returns The method is returning a new instance of the `MapVertex` class, casted as type `VO`.\n */\n override createVertex(\n key: VertexKey,\n value?: V,\n lat: number = this.originCoord[0],\n long: number = this.originCoord[1]\n ): VO {\n return new MapVertex(key, value, lat, long) as VO;\n }\n\n /**\n * The function creates a new instance of a MapEdge with the given source, destination, weight, and value.\n * @param {VertexKey} src - The source vertex ID of the edge. It represents the starting point of the edge.\n * @param {VertexKey} dest - The `dest` parameter is the identifier of the destination vertex for the edge being\n * created.\n * @param {number} [weight] - The `weight` parameter is an optional number that represents the weight of the edge. It\n * is used to assign a numerical value to the edge, which can be used in algorithms such as shortest path algorithms.\n * If the weight is not provided, it can be set to a default value or left undefined.\n * @param [value] - The `value` parameter is an optional value that can be assigned to the edge. It can be of any type,\n * depending on the specific implementation of the `MapEdge` class.\n * @returns a new instance of the `MapEdge` class, cast as type `EO`.\n */\n override createEdge(src: VertexKey, dest: VertexKey, weight?: number, value?: E): EO {\n return new MapEdge(src, dest, weight, value) as EO;\n }\n\n /**\n * The override function is used to override the default behavior of a function.\n * In this case, we are overriding the clone() function from Graph&lt;V, E&gt;.\n * The clone() function returns a new graph that is an exact copy of the original graph.\n *\n * @return A mapgraph&lt;v, e, vo, eo&gt;\n */\n override clone(): MapGraph<V, E, VO, EO> {\n const cloned = new MapGraph<V, E, VO, EO>(this.originCoord, this.bottomRight);\n cloned.vertexMap = new Map<VertexKey, VO>(this.vertexMap);\n cloned.inEdgeMap = new Map<VO, EO[]>(this.inEdgeMap);\n cloned.outEdgeMap = new Map<VO, EO[]>(this.outEdgeMap);\n return cloned;\n }\n}\n","import { isComparable } from '../utils';\n\nexport enum DFSOperation {\n VISIT = 0,\n PROCESS = 1\n}\n\nexport class Range<K> {\n constructor(\n public low: K,\n public high: K,\n public includeLow: boolean = true,\n public includeHigh: boolean = true\n ) {\n if (!(isComparable(low) && isComparable(high))) throw new RangeError('low or high is not comparable');\n if (low > high) throw new RangeError('low must be less than or equal to high');\n }\n\n // Determine whether a key is within the range\n isInRange(key: K, comparator: (a: K, b: K) => number): boolean {\n const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;\n const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;\n return lowCheck && highCheck;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n\nimport type {\n BinaryTreeDeleteResult,\n BinaryTreeOptions,\n BinaryTreePrintOptions,\n BTNEntry,\n DFSOrderPattern,\n DFSStackItem,\n EntryCallback,\n FamilyPosition,\n IterationType,\n NodeCallback,\n NodeDisplayLayout,\n NodePredicate,\n OptNodeOrNull,\n RBTNColor, Thunk,\n ToEntryFn\n} from '../../types';\nimport { IBinaryTree } from '../../interfaces';\nimport { isComparable, trampoline } from '../../utils';\nimport { Queue } from '../queue';\nimport { IterableEntryBase } from '../base';\nimport { DFSOperation, Range } from '../../common';\n\n/**\n * Represents a node in a binary tree.\n * @template V - The type of data stored in the node.\n * @template BinaryTreeNode<K, V> - The type of the family relationship in the binary tree.\n */\nexport class BinaryTreeNode<K = any, V = any> {\n key: K;\n value?: V;\n parent?: BinaryTreeNode<K, V> = undefined;\n\n /**\n * The constructor function initializes an object with a key and an optional value in TypeScript.\n * @param {K} key - The `key` parameter in the constructor function is used to store the key value\n * for the key-value pair.\n * @param {V} [value] - The `value` parameter in the constructor is optional, meaning it does not\n * have to be provided when creating an instance of the class. If a `value` is not provided, it will\n * default to `undefined`.\n */\n constructor(key: K, value?: V) {\n this.key = key;\n this.value = value;\n }\n\n _left?: BinaryTreeNode<K, V> | null | undefined = undefined;\n\n get left(): BinaryTreeNode<K, V> | null | undefined {\n return this._left;\n }\n\n set left(v: BinaryTreeNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this as unknown as BinaryTreeNode<K, V>;\n }\n this._left = v;\n }\n\n _right?: BinaryTreeNode<K, V> | null | undefined = undefined;\n\n get right(): BinaryTreeNode<K, V> | null | undefined {\n return this._right;\n }\n\n set right(v: BinaryTreeNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n\n _height: number = 0;\n\n get height(): number {\n return this._height;\n }\n\n set height(value: number) {\n this._height = value;\n }\n\n _color: RBTNColor = 'BLACK';\n\n get color(): RBTNColor {\n return this._color;\n }\n\n set color(value: RBTNColor) {\n this._color = value;\n }\n\n _count: number = 1;\n\n get count(): number {\n return this._count;\n }\n\n set count(value: number) {\n this._count = value;\n }\n\n get familyPosition(): FamilyPosition {\n if (!this.parent) {\n return this.left || this.right ? 'ROOT' : 'ISOLATED';\n }\n\n if (this.parent.left === this) {\n return this.left || this.right ? 'ROOT_LEFT' : 'LEFT';\n } else if (this.parent.right === this) {\n return this.left || this.right ? 'ROOT_RIGHT' : 'RIGHT';\n }\n\n return 'MAL_NODE';\n }\n}\n\n/**\n * 1. Two Children Maximum: Each node has at most two children.\n * 2. Left and Right Children: Nodes have distinct left and right children.\n * 3. Depth and Height: Depth is the number of edges from the root to a node; height is the maximum depth in the tree.\n * 4. Subtrees: Each child of a node forms the root of a subtree.\n * 5. Leaf Nodes: Nodes without children are leaves.\n * @example\n * // determine loan approval using a decision tree\n * // Decision tree structure\n * const loanDecisionTree = new BinaryTree<string>(\n * ['stableIncome', 'goodCredit', 'Rejected', 'Approved', 'Rejected'],\n * { isDuplicate: true }\n * );\n *\n * function determineLoanApproval(\n * node?: BinaryTreeNode<string> | null,\n * conditions?: { [key: string]: boolean }\n * ): string {\n * if (!node) throw new Error('Invalid node');\n *\n * // If it's a leaf node, return the decision result\n * if (!node.left && !node.right) return node.key;\n *\n * // Check if a valid condition exists for the current node's key\n * return conditions?.[node.key]\n * ? determineLoanApproval(node.left, conditions)\n * : determineLoanApproval(node.right, conditions);\n * }\n *\n * // Test case 1: Stable income and good credit score\n * console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: true, goodCredit: true })); // 'Approved'\n *\n * // Test case 2: Stable income but poor credit score\n * console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: true, goodCredit: false })); // 'Rejected'\n *\n * // Test case 3: No stable income\n * console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: false, goodCredit: true })); // 'Rejected'\n *\n * // Test case 4: No stable income and poor credit score\n * console.log(determineLoanApproval(loanDecisionTree.root, { stableIncome: false, goodCredit: false })); // 'Rejected'\n * @example\n * // evaluate the arithmetic expression represented by the binary tree\n * const expressionTree = new BinaryTree<number | string>(['+', 3, '*', null, null, 5, '-', null, null, 2, 8]);\n *\n * function evaluate(node?: BinaryTreeNode<number | string> | null): number {\n * if (!node) return 0;\n *\n * if (typeof node.key === 'number') return node.key;\n *\n * const leftValue = evaluate(node.left); // Evaluate the left subtree\n * const rightValue = evaluate(node.right); // Evaluate the right subtree\n *\n * // Perform the operation based on the current node's operator\n * switch (node.key) {\n * case '+':\n * return leftValue + rightValue;\n * case '-':\n * return leftValue - rightValue;\n * case '*':\n * return leftValue * rightValue;\n * case '/':\n * return rightValue !== 0 ? leftValue / rightValue : 0; // Handle division by zero\n * default:\n * throw new Error(`Unsupported operator: ${node.key}`);\n * }\n * }\n *\n * console.log(evaluate(expressionTree.root)); // -27\n */\nexport class BinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends IterableEntryBase<K, V | undefined>\n implements IBinaryTree<K, V, R, MK, MV, MR>\n{\n iterationType: IterationType = 'ITERATIVE';\n\n /**\n * This TypeScript constructor function initializes a binary tree with optional options and adds\n * elements based on the provided input.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an\n * iterable that can contain either objects of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It\n * is used to initialize the binary tree with keys, nodes, entries, or raw data.\n * @param [options] - The `options` parameter in the constructor is an optional object that can\n * contain the following properties:\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n > = [],\n options?: BinaryTreeOptions<K, V, R>\n ) {\n super();\n if (options) {\n const { iterationType, toEntryFn, isMapMode, isDuplicate } = options;\n if (iterationType) this.iterationType = iterationType;\n if (isMapMode !== undefined) this._isMapMode = isMapMode;\n if (isDuplicate !== undefined) this._isDuplicate = isDuplicate;\n if (typeof toEntryFn === 'function') this._toEntryFn = toEntryFn;\n else if (toEntryFn) throw TypeError('toEntryFn must be a function type');\n }\n\n if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);\n }\n\n protected _isMapMode = true;\n\n get isMapMode() {\n return this._isMapMode;\n }\n\n protected _isDuplicate = false;\n\n get isDuplicate() {\n return this._isDuplicate;\n }\n\n protected _store = new Map<K, V | undefined>();\n\n get store() {\n return this._store;\n }\n\n protected _root?: BinaryTreeNode<K, V> | null | undefined;\n\n get root(): BinaryTreeNode<K, V> | null | undefined {\n return this._root;\n }\n\n protected _size: number = 0;\n\n get size(): number {\n return this._size;\n }\n\n protected _NIL: BinaryTreeNode<K, V> = new BinaryTreeNode<K, V>(NaN as K) as unknown as BinaryTreeNode<K, V>;\n\n get NIL(): BinaryTreeNode<K, V> {\n return this._NIL;\n }\n\n protected _toEntryFn?: ToEntryFn<K, V, R>;\n\n get toEntryFn() {\n return this._toEntryFn;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a new binary tree node with a specified key and optional value.\n * @param {K} key - The `key` parameter is the key of the node being created in the binary tree.\n * @param {V} [value] - The `value` parameter in the `createNode` function is optional, meaning it is\n * not required to be provided when calling the function. If a `value` is provided, it should be of\n * type `V`, which is the type of the value associated with the node.\n * @returns A new BinaryTreeNode instance with the provided key and value is being returned, casted\n * as BinaryTreeNode<K, V>.\n */\n createNode(key: K, value?: V): BinaryTreeNode<K, V> {\n return new BinaryTreeNode<K, V>(key, this._isMapMode ? undefined : value);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a binary tree with the specified options.\n * @param [options] - The `options` parameter in the `createTree` function is an optional parameter\n * that allows you to provide partial configuration options for creating a binary tree. It is of type\n * `Partial<BinaryTreeOptions<K, V, R>>`, which means you can pass in an object containing a subset\n * of properties\n * @returns A new instance of a binary tree with the specified options is being returned.\n */\n createTree(options?: BinaryTreeOptions<K, V, R>) {\n return new BinaryTree<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n isMapMode: this._isMapMode,\n toEntryFn: this._toEntryFn,\n ...options\n });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The function `ensureNode` in TypeScript checks if a given input is a node, entry, key, or raw\n * value and returns the corresponding node or null.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`\n * parameter in the `ensureNode` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It\n * is used to determine whether the input is a key, node, entry, or raw data. The\n * @param {IterationType} iterationType - The `iterationType` parameter in the `ensureNode` function\n * is used to specify the type of iteration to be performed. It has a default value of\n * `this.iterationType` if not explicitly provided.\n * @returns The `ensureNode` function returns either a node, `null`, or `undefined` based on the\n * conditions specified in the code snippet.\n */\n ensureNode(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType: IterationType = this.iterationType\n ): BinaryTreeNode<K, V> | null | undefined {\n if (keyNodeOrEntry === null) return null;\n if (keyNodeOrEntry === undefined) return;\n if (keyNodeOrEntry === this._NIL) return;\n\n if (this.isNode(keyNodeOrEntry)) return keyNodeOrEntry;\n\n if (this.isEntry(keyNodeOrEntry)) {\n const key = keyNodeOrEntry[0];\n if (key === null) return null;\n if (key === undefined) return;\n return this.getNode(key, this._root, iterationType);\n }\n\n return this.getNode(keyNodeOrEntry, this._root, iterationType);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function isNode checks if the input is an instance of BinaryTreeNode.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be either a key, a node, an entry, or raw data. The function is\n * checking if the input is an instance of a `BinaryTreeNode` and returning a boolean value\n * accordingly.\n * @returns The function `isNode` is checking if the input `keyNodeOrEntry` is an instance of\n * `BinaryTreeNode`. If it is, the function returns `true`, indicating that the input is a node. If\n * it is not an instance of `BinaryTreeNode`, the function returns `false`, indicating that the input\n * is not a node.\n */\n isNode(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is BinaryTreeNode<K, V> {\n return keyNodeOrEntry instanceof BinaryTreeNode;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `isRaw` checks if the input parameter is of type `R` by verifying if it is an object.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R} keyNodeEntryOrRaw - K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n * @returns The function `isRaw` is checking if the `keyNodeEntryOrRaw` parameter is of type `R` by\n * checking if it is an object. If the parameter is an object, the function will return `true`,\n * indicating that it is of type `R`.\n */\n isRaw(\n keyNodeEntryOrRaw: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n ): keyNodeEntryOrRaw is R {\n return this._toEntryFn !== undefined && typeof keyNodeEntryOrRaw === 'object';\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `isRealNode` checks if a given input is a valid node in a binary tree.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`\n * parameter in the `isRealNode` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`.\n * The function checks if the input parameter is a `BinaryTreeNode<K, V>` type by verifying if it is not equal\n * @returns The function `isRealNode` is checking if the input `keyNodeOrEntry` is a valid\n * node by comparing it to `this._NIL`, `null`, and `undefined`. If the input is not one of these\n * values, it then calls the `isNode` method to further determine if the input is a node. The\n * function will return a boolean value indicating whether the\n */\n isRealNode(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is BinaryTreeNode<K, V> {\n if (keyNodeOrEntry === this._NIL || keyNodeOrEntry === null || keyNodeOrEntry === undefined) return false;\n return this.isNode(keyNodeOrEntry);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if a given input is a valid node or null.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` in the `isRealNodeOrNull` function can be of type `BTNRep<K,\n * V, BinaryTreeNode<K, V>>` or `R`. It is a union type that can either be a key, a node, an entry, or\n * @returns The function `isRealNodeOrNull` is returning a boolean value. It checks if the input\n * `keyNodeOrEntry` is either `null` or a real node, and returns `true` if it is a node or\n * `null`, and `false` otherwise.\n */\n isRealNodeOrNull(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is BinaryTreeNode<K, V> | null {\n return keyNodeOrEntry === null || this.isRealNode(keyNodeOrEntry);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function isNIL checks if a given key, node, entry, or raw value is equal to the _NIL value.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - BTNRep<K, V,\n * BinaryTreeNode<K, V>>\n * @returns The function is checking if the `keyNodeOrEntry` parameter is equal to the `_NIL`\n * property of the current object and returning a boolean value based on that comparison.\n */\n isNIL(keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): boolean {\n return keyNodeOrEntry === this._NIL;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `isRange` checks if the input parameter is an instance of the `Range` class.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>> | Range<K>} keyNodeEntryOrPredicate\n * - The `keyNodeEntryOrPredicate` parameter in the `isRange` function can be\n * of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `, `NodePredicate<BinaryTreeNode<K, V>>`, or\n * `Range<K>`. The function checks if the `keyNodeEntry\n * @returns The `isRange` function is checking if the `keyNodeEntryOrPredicate` parameter is an\n * instance of the `Range` class. If it is an instance of `Range`, the function will return `true`,\n * indicating that the parameter is a `Range<K>`. If it is not an instance of `Range`, the function\n * will return `false`.\n */\n isRange(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V>>\n | Range<K>\n ): keyNodeEntryOrPredicate is Range<K> {\n return keyNodeEntryOrPredicate instanceof Range;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function determines whether a given key, node, entry, or raw data is a leaf node in a binary\n * tree.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It represents a\n * key, node, entry, or raw data in a binary tree structure. The function `isLeaf` checks whether the\n * provided\n * @returns The function `isLeaf` returns a boolean value indicating whether the input\n * `keyNodeOrEntry` is a leaf node in a binary tree.\n */\n isLeaf(keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): boolean {\n keyNodeOrEntry = this.ensureNode(keyNodeOrEntry);\n if (keyNodeOrEntry === undefined) return false;\n if (keyNodeOrEntry === null) return true;\n return !this.isRealNode(keyNodeOrEntry.left) && !this.isRealNode(keyNodeOrEntry.right);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `isEntry` checks if the input is a BTNEntry object by verifying if it is an array\n * with a length of 2.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`\n * parameter in the `isEntry` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or type `R`.\n * The function checks if the provided `keyNodeOrEntry` is of type `BTN\n * @returns The `isEntry` function is checking if the `keyNodeOrEntry` parameter is an array\n * with a length of 2. If it is, then it returns `true`, indicating that the parameter is of type\n * `BTNEntry<K, V>`. If the condition is not met, it returns `false`.\n */\n isEntry(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is BTNEntry<K, V> {\n return Array.isArray(keyNodeOrEntry) && keyNodeOrEntry.length === 2;\n }\n\n /**\n * Time Complexity O(1)\n * Space Complexity O(1)\n *\n * The function `isValidKey` checks if a given key is comparable.\n * @param {any} key - The `key` parameter is of type `any`, which means it can be any data type in\n * TypeScript.\n * @returns The function `isValidKey` is checking if the `key` parameter is `null` or if it is comparable.\n * If the `key` is `null`, the function returns `true`. Otherwise, it returns the result of the\n * `isComparable` function, which is not provided in the code snippet.\n */\n isValidKey(key: any): key is K {\n if (key === null) return true;\n return isComparable(key);\n }\n\n /**\n * Time Complexity O(n)\n * Space Complexity O(1)\n *\n * The `add` function in TypeScript adds a new node to a binary tree while handling duplicate keys\n * and finding the correct insertion position.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `add` method you provided\n * seems to be for adding a new node to a binary tree structure. The `keyNodeOrEntry`\n * parameter in the method can accept different types of values:\n * @param {V} [value] - The `value` parameter in the `add` method represents the value associated\n * with the key that you want to add to the binary tree. When adding a key-value pair to the binary\n * tree, you provide the key and its corresponding value. The `add` method then creates a new node\n * with this\n * @returns The `add` method returns a boolean value. It returns `true` if the insertion of the new\n * node was successful, and `false` if the insertion position could not be found or if a duplicate\n * key was found and the node was replaced instead of inserted.\n */\n add(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V\n ): boolean {\n const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);\n if (newNode === undefined) return false;\n\n // If the tree is empty, directly set the new node as the root node\n if (!this._root) {\n this._setRoot(newNode);\n if (this._isMapMode) this._setValue(newNode?.key, newValue);\n this._size = 1;\n return true;\n }\n\n const queue = new Queue<BinaryTreeNode<K, V>>([this._root]);\n let potentialParent: BinaryTreeNode<K, V> | undefined; // Record the parent node of the potential insertion location\n\n while (queue.length > 0) {\n const cur = queue.shift();\n\n if (!cur) continue;\n\n if (!this._isDuplicate) {\n // Check for duplicate keys when newNode is not null\n if (newNode !== null && cur.key === newNode.key) {\n this._replaceNode(cur, newNode);\n if (this._isMapMode) this._setValue(cur.key, newValue);\n return true; // If duplicate keys are found, no insertion is performed\n }\n }\n\n // Record the first possible insertion location found\n if (potentialParent === undefined && (cur.left === undefined || cur.right === undefined)) {\n potentialParent = cur;\n }\n\n // Continue traversing the left and right subtrees\n if (cur.left !== null) {\n if (cur.left) queue.push(cur.left);\n }\n if (cur.right !== null) {\n if (cur.right) queue.push(cur.right);\n }\n }\n\n // At the end of the traversal, if the insertion position is found, insert\n if (potentialParent) {\n if (potentialParent.left === undefined) {\n potentialParent.left = newNode;\n } else if (potentialParent.right === undefined) {\n potentialParent.right = newNode;\n }\n if (this._isMapMode) this._setValue(newNode?.key, newValue);\n this._size++;\n return true;\n }\n\n return false; // If the insertion position cannot be found, return undefined\n }\n\n /**\n * Time Complexity: O(k * n)\n * Space Complexity: O(k)\n *\n * The `addMany` function takes in multiple keys or nodes or entries or raw values along with\n * optional values, and adds them to a data structure while returning an array indicating whether\n * each insertion was successful.\n * @param keysNodesEntriesOrRaws - `keysNodesEntriesOrRaws` is an iterable that can contain a\n * mix of keys, nodes, entries, or raw values. Each element in this iterable can be of type\n * `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`.\n * @param [values] - The `values` parameter in the `addMany` function is an optional parameter that\n * accepts an iterable of values. These values correspond to the keys or nodes being added in the\n * `keysNodesEntriesOrRaws` parameter. If provided, the function will iterate over the values and\n * assign them\n * @returns The `addMany` method returns an array of boolean values indicating whether each key,\n * node, entry, or raw value was successfully added to the data structure. Each boolean value\n * corresponds to the success of adding the corresponding key or value in the input iterable.\n */\n addMany(\n keysNodesEntriesOrRaws: Iterable<\n K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n >,\n values?: Iterable<V | undefined>\n ): boolean[] {\n // TODO not sure addMany not be run multi times\n const inserted: boolean[] = [];\n\n let valuesIterator: Iterator<V | undefined> | undefined;\n if (values) {\n valuesIterator = values[Symbol.iterator]();\n }\n\n for (let keyNodeEntryOrRaw of keysNodesEntriesOrRaws) {\n let value: V | undefined | null = undefined;\n\n if (valuesIterator) {\n const valueResult = valuesIterator.next();\n if (!valueResult.done) {\n value = valueResult.value;\n }\n }\n if (this.isRaw(keyNodeEntryOrRaw)) keyNodeEntryOrRaw = this._toEntryFn!(keyNodeEntryOrRaw);\n inserted.push(this.add(keyNodeEntryOrRaw, value));\n }\n\n return inserted;\n }\n\n /**\n * Time Complexity: O(k * n)\n * Space Complexity: O(1)\n *\n * The `merge` function in TypeScript merges another binary tree into the current tree by adding all\n * elements from the other tree.\n * @param anotherTree - BinaryTree<K, V, R, MK, MV, MR>\n */\n merge(anotherTree: BinaryTree<K, V, R, MK, MV, MR>) {\n this.addMany(anotherTree, []);\n }\n\n /**\n * Time Complexity: O(k * n)\n * Space Complexity: O(1)\n *\n * The `refill` function clears the existing data structure and then adds new key-value pairs based\n * on the provided input.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the `refill`\n * method can accept an iterable containing a mix of `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` objects or `R`\n * objects.\n * @param [values] - The `values` parameter in the `refill` method is an optional parameter that\n * accepts an iterable of values of type `V` or `undefined`.\n */\n refill(\n keysNodesEntriesOrRaws: Iterable<\n K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n >,\n values?: Iterable<V | undefined>\n ): void {\n this.clear();\n this.addMany(keysNodesEntriesOrRaws, values);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `delete` in TypeScript implements the deletion of a node in a binary tree and returns\n * the deleted node along with information for tree balancing.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry\n * - The `delete` method you provided is used to delete a node from a binary tree based on the key,\n * node, entry or raw data. The method returns an array of\n * `BinaryTreeDeleteResult` objects containing information about the deleted node and whether\n * balancing is needed.\n * @returns The `delete` method returns an array of `BinaryTreeDeleteResult` objects. Each object in\n * the array contains information about the node that was deleted (`deleted`) and the node that may\n * need to be balanced (`needBalanced`).\n */\n delete(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] {\n const deletedResult: BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[] = [];\n if (!this._root) return deletedResult;\n\n const curr = this.getNode(keyNodeOrEntry);\n if (!curr) return deletedResult;\n\n const parent: BinaryTreeNode<K, V> | undefined = curr?.parent;\n let needBalanced: BinaryTreeNode<K, V> | undefined;\n let orgCurrent: BinaryTreeNode<K, V> | undefined = curr;\n\n if (!curr.left && !curr.right && !parent) {\n this._setRoot(undefined);\n } else if (curr.left) {\n const leftSubTreeRightMost = this.getRightMost(node => node, curr.left);\n if (leftSubTreeRightMost) {\n const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;\n orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);\n if (parentOfLeftSubTreeMax) {\n if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)\n parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;\n else parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;\n needBalanced = parentOfLeftSubTreeMax;\n }\n }\n } else if (parent) {\n const { familyPosition: fp } = curr;\n if (fp === 'LEFT' || fp === 'ROOT_LEFT') {\n parent.left = curr.right;\n } else if (fp === 'RIGHT' || fp === 'ROOT_RIGHT') {\n parent.right = curr.right;\n }\n needBalanced = parent;\n } else {\n this._setRoot(curr.right);\n curr.right = undefined;\n }\n\n this._size = this._size - 1;\n\n deletedResult.push({ deleted: orgCurrent, needBalanced });\n if (this._isMapMode && orgCurrent) this._store.delete(orgCurrent.key);\n return deletedResult;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(k + log n)\n *\n * The `search` function in TypeScript performs a depth-first or breadth-first search on a tree\n * structure based on a given predicate or key, with options to return multiple results or just one.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The\n * `keyNodeEntryOrPredicate` parameter in the `search` function can accept three types of values:\n * @param [onlyOne=false] - The `onlyOne` parameter in the `search` function is a boolean flag that\n * determines whether the search should stop after finding the first matching node. If `onlyOne` is\n * set to `true`, the search will return as soon as a matching node is found. If `onlyOne` is\n * @param {C} callback - The `callback` parameter in the `search` function is a callback function\n * that will be called on each node that matches the search criteria. It is of type `C`, which\n * extends `NodeCallback<BinaryTreeNode<K, V> | null>`. The default value for `callback` is `this._DEFAULT_NODE_CALLBACK` if\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `search` function is\n * used to specify the node from which the search operation should begin. It represents the starting\n * point in the binary tree where the search will be performed. If no specific `startNode` is\n * provided, the search operation will start from the root\n * @param {IterationType} iterationType - The `iterationType` parameter in the `search` function\n * specifies the type of iteration to be used when searching for nodes in a binary tree. It can have\n * two possible values:\n * @returns The `search` function returns an array of values that match the provided criteria based\n * on the search algorithm implemented within the function.\n */\n search<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V> | null>,\n onlyOne = false,\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C>[] {\n if (keyNodeEntryOrPredicate === undefined) return [];\n if (keyNodeEntryOrPredicate === null) return [];\n startNode = this.ensureNode(startNode);\n if (!startNode) return [];\n const predicate = this._ensurePredicate(keyNodeEntryOrPredicate);\n\n const ans: ReturnType<C>[] = [];\n\n if (iterationType === 'RECURSIVE') {\n const dfs = (cur: BinaryTreeNode<K, V>) => {\n if (predicate(cur)) {\n ans.push(callback(cur));\n if (onlyOne) return;\n }\n if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;\n if (this.isRealNode(cur.left)) dfs(cur.left);\n if (this.isRealNode(cur.right)) dfs(cur.right);\n };\n\n dfs(startNode);\n } else {\n const stack = [startNode];\n while (stack.length > 0) {\n const cur = stack.pop();\n if (this.isRealNode(cur)) {\n if (predicate(cur)) {\n ans.push(callback(cur));\n if (onlyOne) return ans;\n }\n if (this.isRealNode(cur.left)) stack.push(cur.left);\n if (this.isRealNode(cur.right)) stack.push(cur.right);\n }\n }\n }\n\n return ans;\n }\n\n getNodes(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V>>,\n onlyOne?: boolean,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType\n ): BinaryTreeNode<K, V>[];\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(k + log n)\n *\n * The function `getNodes` retrieves nodes from a binary tree based on a key, node, entry, raw data,\n * or predicate, with options for recursive or iterative traversal.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate\n * - The `getNodes` function you provided takes several parameters:\n * @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` function is a boolean flag that\n * determines whether to return only the first node that matches the criteria specified by the\n * `keyNodeEntryOrPredicate` parameter. If `onlyOne` is set to `true`, the function will\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `getNodes` function is used to specify the starting point for traversing the binary tree. It\n * represents the root node of the binary tree or the node from which the traversal should begin. If\n * not provided, the default value is set to `this._root\n * @param {IterationType} iterationType - The `iterationType` parameter in the `getNodes` function\n * determines the type of iteration to be performed when traversing the nodes of a binary tree. It\n * can have two possible values:\n * @returns The `getNodes` function returns an array of nodes that satisfy the provided condition\n * based on the input parameters and the iteration type specified.\n */\n getNodes(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V> | null>,\n onlyOne = false,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): (BinaryTreeNode<K, V> | null)[] {\n return this.search(keyNodeEntryOrPredicate, onlyOne, node => node, startNode, iterationType);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The `getNode` function retrieves a node based on the provided key, node, entry, raw data, or\n * predicate.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate\n * - The `keyNodeEntryOrPredicate` parameter in the `getNode` function can accept a key,\n * node, entry, raw data, or a predicate function.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `getNode` function is used to specify the starting point for searching for a node in a binary\n * tree. If no specific starting point is provided, the default value is set to `this._root`, which\n * is typically the root node of the binary tree.\n * @param {IterationType} iterationType - The `iterationType` parameter in the `getNode` method is\n * used to specify the type of iteration to be performed when searching for a node. It has a default\n * value of `this.iterationType`, which means it will use the iteration type defined in the current\n * context if no specific value is provided\n * @returns The `getNode` function is returning the first node that matches the specified criteria,\n * or `null` if no matching node is found.\n */\n getNode(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V> | null>,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): BinaryTreeNode<K, V> | null | undefined {\n return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType)[0];\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * This function overrides the `get` method to retrieve the value associated with a specified key,\n * node, entry, raw data, or predicate in a data structure.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate\n * - The `keyNodeEntryOrPredicate` parameter in the `get` method can accept one of the\n * following types:\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `get`\n * method is used to specify the starting point for searching for a key or node in the binary tree.\n * If no specific starting point is provided, the default starting point is the root of the binary\n * tree (`this._root`).\n * @param {IterationType} iterationType - The `iterationType` parameter in the `get` method is used\n * to specify the type of iteration to be performed when searching for a key in the binary tree. It\n * is an optional parameter with a default value of `this.iterationType`, which means it will use the\n * iteration type defined in the\n * @returns The `get` method is returning the value associated with the specified key, node, entry,\n * raw data, or predicate in the binary tree map. If the specified key or node is found in the tree,\n * the method returns the corresponding value. If the key or node is not found, it returns\n * `undefined`.\n */\n override get(\n keyNodeEntryOrPredicate: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): V | undefined {\n if (this._isMapMode) {\n const key = this._extractKey(keyNodeEntryOrPredicate);\n if (key === null || key === undefined) return;\n return this._store.get(key);\n }\n return this.getNode(keyNodeEntryOrPredicate, startNode, iterationType)?.value;\n }\n\n override has(\n keyNodeEntryOrPredicate?:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V>>,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType\n ): boolean;\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The `has` function in TypeScript checks if a specified key, node, entry, raw data, or predicate\n * exists in the data structure.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate\n * - The `keyNodeEntryOrPredicate` parameter in the `override has` method can accept one of\n * the following types:\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `override` method is used to specify the starting point for the search operation within the data\n * structure. It defaults to `this._root` if not provided explicitly.\n * @param {IterationType} iterationType - The `iterationType` parameter in the `override has` method\n * is used to specify the type of iteration to be performed. It has a default value of\n * `this.iterationType`, which means it will use the iteration type defined in the current context if\n * no value is provided when calling the method.\n * @returns The `override has` method is returning a boolean value. It checks if there are any nodes\n * that match the provided key, node, entry, raw data, or predicate in the tree structure. If there\n * are matching nodes, it returns `true`, indicating that the tree contains the specified element.\n * Otherwise, it returns `false`.\n */\n override has(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V> | null>,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): boolean {\n return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType).length > 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear function removes nodes and values in map mode.\n */\n clear() {\n this._clearNodes();\n if (this._isMapMode) this._clearValues();\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `isEmpty` function in TypeScript checks if a data structure has no elements and returns a\n * boolean value.\n * @returns The `isEmpty()` method is returning a boolean value, specifically `true` if the `_size`\n * property is equal to 0, indicating that the data structure is empty, and `false` otherwise.\n */\n isEmpty(): boolean {\n return this._size === 0;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The function checks if a binary tree is perfectly balanced by comparing its minimum height with\n * its height.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting\n * point for checking if the binary tree is perfectly balanced. It represents the root node of the\n * binary tree or a specific node from which the balance check should begin.\n * @returns The method `isPerfectlyBalanced` is returning a boolean value, which indicates whether\n * the tree starting from the `startNode` node is perfectly balanced or not. The return value is\n * determined by comparing the minimum height of the tree with the height of the tree. If the minimum\n * height plus 1 is greater than or equal to the height of the tree, then it is considered perfectly\n * balanced and\n */\n isPerfectlyBalanced(\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root\n ): boolean {\n return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The function `isBST` in TypeScript checks if a binary search tree is valid using either recursive\n * or iterative methods.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `isBST`\n * function represents the starting point for checking whether a binary search tree (BST) is valid.\n * It can be a node in the BST or a reference to the root of the BST. If no specific node is\n * provided, the function will default to\n * @param {IterationType} iterationType - The `iterationType` parameter in the `isBST` function\n * determines whether the function should use a recursive approach or an iterative approach to check\n * if the binary search tree (BST) is valid.\n * @returns The `isBST` method is returning a boolean value, which indicates whether the binary\n * search tree (BST) represented by the given root node is a valid BST or not. The method checks if\n * the tree satisfies the BST property, where for every node, all nodes in its left subtree have keys\n * less than the node's key, and all nodes in its right subtree have keys greater than the node's\n */\n isBST(\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): boolean {\n // TODO there is a bug\n startNode = this.ensureNode(startNode);\n if (!startNode) return true;\n\n if (iterationType === 'RECURSIVE') {\n const dfs = (cur: BinaryTreeNode<K, V> | null | undefined, min: number, max: number): boolean => {\n if (!this.isRealNode(cur)) return true;\n const numKey = Number(cur.key);\n if (numKey <= min || numKey >= max) return false;\n return dfs(cur.left, min, numKey) && dfs(cur.right, numKey, max);\n };\n\n const isStandardBST = dfs(startNode, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);\n const isInverseBST = dfs(startNode, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);\n return isStandardBST || isInverseBST;\n } else {\n const checkBST = (checkMax = false) => {\n const stack = [];\n let prev = checkMax ? Number.MAX_SAFE_INTEGER : Number.MIN_SAFE_INTEGER;\n // @ts-ignore\n let curr: BinaryTreeNode<K, V> | null | undefined = startNode;\n while (this.isRealNode(curr) || stack.length > 0) {\n while (this.isRealNode(curr)) {\n stack.push(curr);\n curr = curr.left;\n }\n curr = stack.pop()!;\n const numKey = Number(curr.key);\n if (!this.isRealNode(curr) || (!checkMax && prev >= numKey) || (checkMax && prev <= numKey)) return false;\n prev = numKey;\n curr = curr.right;\n }\n return true;\n };\n const isStandardBST = checkBST(false),\n isInverseBST = checkBST(true);\n return isStandardBST || isInverseBST;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The `getDepth` function calculates the depth between two nodes in a binary tree.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } dist - The `dist` parameter in the `getDepth`\n * function represents the node or entry in a binary tree map, or a reference to a node in the tree.\n * It is the target node for which you want to calculate the depth from the `startNode` node.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `getDepth` function represents the starting point from which you want to calculate the depth of a\n * given node or entry in a binary tree. If no specific starting point is provided, the default value\n * for `startNode` is set to the root of the binary\n * @returns The `getDepth` method returns the depth of a given node `dist` relative to the\n * `startNode` node in a binary tree. If the `dist` node is not found in the path to the `startNode`\n * node, it returns the depth of the `dist` node from the root of the tree.\n */\n getDepth(\n dist: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root\n ): number {\n let distEnsured = this.ensureNode(dist);\n const beginRootEnsured = this.ensureNode(startNode);\n let depth = 0;\n while (distEnsured?.parent) {\n if (distEnsured === beginRootEnsured) {\n return depth;\n }\n depth++;\n distEnsured = distEnsured.parent;\n }\n return depth;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The `getHeight` function calculates the maximum height of a binary tree using either a recursive\n * or iterative approach in TypeScript.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting\n * point from which the height of the binary tree will be calculated. It can be a node in the binary\n * tree or a reference to the root of the tree. If not provided, it defaults to the root of the\n * binary tree data structure.\n * @param {IterationType} iterationType - The `iterationType` parameter is used to determine the type\n * of iteration to be performed while calculating the height of the binary tree. It can have two\n * possible values:\n * @returns The `getHeight` method returns the height of the binary tree starting from the specified\n * root node. The height is calculated based on the maximum depth of the tree, considering either a\n * recursive approach or an iterative approach depending on the `iterationType` parameter.\n */\n getHeight(\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): number {\n startNode = this.ensureNode(startNode);\n if (!this.isRealNode(startNode)) return -1;\n\n if (iterationType === 'RECURSIVE') {\n const _getMaxHeight = (cur: BinaryTreeNode<K, V> | null | undefined): number => {\n if (!this.isRealNode(cur)) return -1;\n const leftHeight = _getMaxHeight(cur.left);\n const rightHeight = _getMaxHeight(cur.right);\n return Math.max(leftHeight, rightHeight) + 1;\n };\n\n return _getMaxHeight(startNode);\n } else {\n const stack: { node: BinaryTreeNode<K, V>; depth: number }[] = [{ node: startNode, depth: 0 }];\n let maxHeight = 0;\n\n while (stack.length > 0) {\n const { node, depth } = stack.pop()!;\n\n if (this.isRealNode(node.left)) stack.push({ node: node.left, depth: depth + 1 });\n if (this.isRealNode(node.right)) stack.push({ node: node.right, depth: depth + 1 });\n\n maxHeight = Math.max(maxHeight, depth);\n }\n\n return maxHeight;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The `getMinHeight` function calculates the minimum height of a binary tree using either a\n * recursive or iterative approach in TypeScript.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `getMinHeight` function represents the starting node from which the minimum height of the binary\n * tree will be calculated. It is either a node in the binary tree or a reference to the root of the\n * tree. If not provided, the default value is the root\n * @param {IterationType} iterationType - The `iterationType` parameter in the `getMinHeight` method\n * specifies the type of iteration to use when calculating the minimum height of a binary tree. It\n * can have two possible values:\n * @returns The `getMinHeight` method returns the minimum height of the binary tree starting from the\n * specified root node. The height is calculated based on the shortest path from the root node to a\n * leaf node in the tree. The method uses either a recursive approach or an iterative approach (using\n * a stack) based on the `iterationType` parameter.\n */\n getMinHeight(\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): number {\n startNode = this.ensureNode(startNode);\n if (!startNode) return -1;\n\n if (iterationType === 'RECURSIVE') {\n const _getMinHeight = (cur: BinaryTreeNode<K, V> | null | undefined): number => {\n if (!this.isRealNode(cur)) return 0;\n if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return 0;\n const leftMinHeight = _getMinHeight(cur.left);\n const rightMinHeight = _getMinHeight(cur.right);\n return Math.min(leftMinHeight, rightMinHeight) + 1;\n };\n\n return _getMinHeight(startNode);\n } else {\n const stack: BinaryTreeNode<K, V>[] = [];\n let node: BinaryTreeNode<K, V> | null | undefined = startNode,\n last: BinaryTreeNode<K, V> | null | undefined = null;\n const depths: Map<BinaryTreeNode<K, V>, number> = new Map();\n\n while (stack.length > 0 || node) {\n if (this.isRealNode(node)) {\n stack.push(node);\n node = node.left;\n } else {\n node = stack[stack.length - 1];\n if (!this.isRealNode(node.right) || last === node.right) {\n node = stack.pop();\n if (this.isRealNode(node)) {\n const leftMinHeight = this.isRealNode(node.left) ? depths.get(node.left)! : -1;\n const rightMinHeight = this.isRealNode(node.right) ? depths.get(node.right)! : -1;\n depths.set(node, 1 + Math.min(leftMinHeight, rightMinHeight));\n last = node;\n node = null;\n }\n } else node = node.right;\n }\n }\n\n return depths.get(startNode)!;\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `getPathToRoot` in TypeScript retrieves the path from a given node to the root of a\n * tree structure, applying a specified callback function along the way.\n * @param {C} callback - The `callback` parameter is a function that is used to process each node in\n * the path to the root. It is expected to be a function that takes a node as an argument and returns\n * a value based on that node. The return type of the callback function is determined by the generic\n * type `C\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } beginNode - The `beginNode` parameter in the\n * `getPathToRoot` function can be either a key, a node, an entry, or any other value of type `R`.\n * @param [isReverse=true] - The `isReverse` parameter in the `getPathToRoot` function determines\n * whether the resulting path from the given `beginNode` to the root should be in reverse order or\n * not. If `isReverse` is set to `true`, the path will be reversed before being returned. If `is\n * @returns The function `getPathToRoot` returns an array of the return values of the callback\n * function `callback` applied to each node in the path from the `beginNode` to the root node. The\n * array is either in reverse order or in the original order based on the value of the `isReverse`\n * parameter.\n */\n getPathToRoot<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(\n beginNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n isReverse = false\n ): ReturnType<C>[] {\n const result: ReturnType<C>[] = [];\n let beginNodeEnsured = this.ensureNode(beginNode);\n\n if (!beginNodeEnsured) return result;\n\n while (beginNodeEnsured.parent) {\n // Array.push + Array.reverse is more efficient than Array.unshift\n result.push(callback(beginNodeEnsured));\n beginNodeEnsured = beginNodeEnsured.parent;\n }\n result.push(callback(beginNodeEnsured));\n return isReverse ? result.reverse() : result;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `getLeftMost` retrieves the leftmost node in a binary tree using either recursive or\n * tail-recursive iteration.\n * @param {C} callback - The `callback` parameter is a function that will be called with the leftmost\n * node of a binary tree or with `undefined` if the tree is empty. It is provided with a default\n * value of `_DEFAULT_NODE_CALLBACK` if not specified.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `getLeftMost` function represents the starting point for finding the leftmost node in a binary\n * tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific\n * starting point is provided, the function will default\n * @param {IterationType} iterationType - The `iterationType` parameter in the `getLeftMost` function\n * specifies the type of iteration to be used when traversing the binary tree nodes. It can have two\n * possible values:\n * @returns The `getLeftMost` function returns the result of the callback function `C` applied to the\n * leftmost node in the binary tree starting from the `startNode` node. If the `startNode` node is\n * `NIL`, it returns the result of the callback function applied to `undefined`. If the `startNode`\n * node is not a real node, it returns the result of the callback\n */\n getLeftMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C> {\n if (this.isNIL(startNode)) return callback(undefined);\n startNode = this.ensureNode(startNode);\n\n if (!this.isRealNode(startNode)) return callback(startNode);\n\n if (iterationType === 'RECURSIVE') {\n const dfs = (cur: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> => {\n if (!this.isRealNode(cur.left)) return cur;\n return dfs(cur.left);\n };\n\n return callback(dfs(startNode));\n } else {\n // Indirect implementation of iteration using tail recursion optimization\n const dfs = (cur: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> | Thunk<BinaryTreeNode<K, V>> => {\n if (!this.isRealNode(cur.left)) return cur;\n return () => dfs(cur.left!);\n };\n\n return callback(trampoline(() => dfs(startNode)));\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `getRightMost` retrieves the rightmost node in a binary tree using either recursive\n * or iterative traversal methods.\n * @param {C} callback - The `callback` parameter is a function that will be called with the result\n * of finding the rightmost node in a binary tree. It is of type `NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>`,\n * which means it is a callback function that can accept either an optional binary tree node or null\n * as\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `getRightMost` function represents the starting point for finding the rightmost node in a binary\n * tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific\n * starting point is provided, the function will default\n * @param {IterationType} iterationType - The `iterationType` parameter in the `getRightMost`\n * function specifies the type of iteration to be used when traversing the binary tree nodes. It can\n * have two possible values:\n * @returns The `getRightMost` function returns the result of the callback function `C`, which is\n * passed as a parameter to the function. The callback function is called with the rightmost node in\n * the binary tree structure, determined based on the specified iteration type ('RECURSIVE' or\n * other).\n */\n getRightMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C> {\n if (this.isNIL(startNode)) return callback(undefined);\n startNode = this.ensureNode(startNode);\n if (!startNode) return callback(startNode);\n\n if (iterationType === 'RECURSIVE') {\n const dfs = (cur: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> => {\n if (!this.isRealNode(cur.right)) return cur;\n return dfs(cur.right);\n };\n\n return callback(dfs(startNode));\n } else {\n const dfs = (cur: BinaryTreeNode<K, V>) => {\n if (!this.isRealNode(cur.right)) return cur;\n return () => dfs(cur.right!) as Thunk<BinaryTreeNode<K, V>>;\n };\n\n return callback(trampoline(() => dfs(startNode)));\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `getPredecessor` in TypeScript returns the predecessor node of a given node in a\n * binary tree.\n * @param {BinaryTreeNode<K, V>} node - The `getPredecessor` function you provided seems to be attempting to find the\n * predecessor of a given node in a binary tree. However, there seems to be a logical issue in the\n * while loop condition that might cause an infinite loop.\n * @returns The `getPredecessor` function returns the predecessor node of the input `BinaryTreeNode<K, V>` parameter.\n * If the left child of the input node exists, it traverses to the rightmost node of the left subtree\n * to find the predecessor. If the left child does not exist, it returns the input node itself.\n */\n getPredecessor(node: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> {\n if (this.isRealNode(node.left)) {\n let predecessor: BinaryTreeNode<K, V> | null | undefined = node.left;\n while (!this.isRealNode(predecessor) || (this.isRealNode(predecessor.right) && predecessor.right !== node)) {\n if (this.isRealNode(predecessor)) {\n predecessor = predecessor.right;\n }\n }\n return predecessor;\n } else {\n return node;\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `getSuccessor` in TypeScript returns the next node in an in-order traversal of a\n * binary tree.\n * @param {K | BinaryTreeNode<K, V> | null} [x] - The `getSuccessor` function takes a parameter `x`, which can be of\n * type `K`, `BinaryTreeNode<K, V>`, or `null`.\n * @returns The `getSuccessor` function returns the successor node of the input node `x`. If `x` has\n * a right child, the function returns the leftmost node in the right subtree of `x`. If `x` does not\n * have a right child, the function traverses up the parent nodes until it finds a node that is not\n * the right child of its parent, and returns that node\n */\n getSuccessor(x?: K | BinaryTreeNode<K, V> | null): BinaryTreeNode<K, V> | null | undefined {\n x = this.ensureNode(x);\n if (!this.isRealNode(x)) return undefined;\n\n if (this.isRealNode(x.right)) {\n return this.getLeftMost(node => node, x.right);\n }\n\n let y: BinaryTreeNode<K, V> | null | undefined = x.parent;\n while (this.isRealNode(y) && x === y.right) {\n x = y;\n y = y.parent;\n }\n return y;\n }\n\n dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(\n callback?: C,\n pattern?: DFSOrderPattern,\n onlyOne?: boolean,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType\n ): ReturnType<C>[];\n\n dfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback?: C,\n pattern?: DFSOrderPattern,\n onlyOne?: boolean,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType,\n includeNull?: boolean\n ): ReturnType<C>[];\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The function performs a depth-first search on a binary tree structure based on the specified\n * parameters.\n * @param {C} callback - The `callback` parameter is a function that will be called for each node\n * visited during the depth-first search. It should accept a `BinaryTreeNode` as an argument and\n * return an optional node or null. The default value for this parameter is `_DEFAULT_NODE_CALLBACK`.\n * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `dfs` function specifies\n * the order in which the nodes are visited during a depth-first search traversal. The possible\n * values for the `pattern` parameter are:\n * @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `dfs` function is a boolean flag\n * that determines whether the depth-first search should stop after finding the first matching node\n * or continue searching for all matching nodes. If `onlyOne` is set to `true`, the search will stop\n * after finding the first matching node\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined}\n * startNode - The `startNode` parameter in the `dfs` function can be one of the following types:\n * @param {IterationType} iterationType - The `iterationType` parameter in the `dfs` function\n * specifies the type of iteration to be performed during the Depth-First Search traversal. It is\n * used to determine the order in which nodes are visited during the traversal. The possible values\n * for `iterationType` are typically defined as an enum or a\n * @param [includeNull=false] - The `includeNull` parameter in the `dfs` function determines whether\n * null nodes should be included in the depth-first search traversal. If `includeNull` is set to\n * `true`, null nodes will be included in the traversal process. If it is set to `false`, null nodes\n * will be skipped\n * @returns The `dfs` method is returning an array of the return type of the callback function `C`.\n */\n dfs<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n pattern: DFSOrderPattern = 'IN',\n onlyOne: boolean = false,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType,\n includeNull = false\n ): ReturnType<C>[] {\n startNode = this.ensureNode(startNode);\n if (!startNode) return [];\n return this._dfs(callback, pattern, onlyOne, startNode, iterationType, includeNull);\n }\n\n bfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(\n callback?: C,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType,\n includeNull?: false\n ): ReturnType<C>[];\n\n bfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback?: C,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType,\n includeNull?: true\n ): ReturnType<C>[];\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `bfs` function performs a breadth-first search traversal on a binary tree or binary search\n * tree, executing a specified callback function on each node visited.\n * @param {C} callback - The `callback` parameter in the `bfs` function is a function that will be\n * called on each node visited during the breadth-first search traversal. It is a generic type `C`\n * that extends the `NodeCallback` type, which takes a parameter of type `BinaryTreeNode<K, V>` or `null`.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `bfs`\n * function represents the starting point for the breadth-first search traversal in a binary tree. It\n * can be specified as a key, node, or entry in the binary tree structure. If not provided, the\n * default value is the root node of the binary\n * @param {IterationType} iterationType - The `iterationType` parameter in the `bfs` function\n * determines the type of iteration to be performed on the binary tree nodes. It can have two\n * possible values:\n * @param [includeNull=false] - The `includeNull` parameter in the `bfs` function determines whether\n * to include `null` values in the breadth-first search traversal of a binary tree. If `includeNull`\n * is set to `true`, the traversal will include `null` values for nodes that do not have children\n * (left\n * @returns The `bfs` function returns an array of values that are the result of applying the\n * provided callback function to each node in the binary tree in a breadth-first search manner.\n */\n bfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType,\n includeNull = false\n ): ReturnType<C>[] {\n startNode = this.ensureNode(startNode);\n if (!startNode) return [];\n\n const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];\n\n if (iterationType === 'RECURSIVE') {\n const queue: Queue<OptNodeOrNull<BinaryTreeNode<K, V>>> = new Queue<OptNodeOrNull<BinaryTreeNode<K, V>>>([\n startNode\n ]);\n\n const dfs = (level: number) => {\n if (queue.length === 0) return;\n\n const current = queue.shift()!;\n ans.push(callback(current));\n\n if (includeNull) {\n if (current && this.isRealNodeOrNull(current.left)) queue.push(current.left);\n if (current && this.isRealNodeOrNull(current.right)) queue.push(current.right);\n } else {\n if (this.isRealNode(current.left)) queue.push(current.left);\n if (this.isRealNode(current.right)) queue.push(current.right);\n }\n\n dfs(level + 1);\n };\n\n dfs(0);\n } else {\n const queue = new Queue<OptNodeOrNull<BinaryTreeNode<K, V>>>([startNode]);\n while (queue.length > 0) {\n const levelSize = queue.length;\n\n for (let i = 0; i < levelSize; i++) {\n const current = queue.shift()!;\n ans.push(callback(current));\n\n if (includeNull) {\n if (current && this.isRealNodeOrNull(current.left)) queue.push(current.left);\n if (current && this.isRealNodeOrNull(current.right)) queue.push(current.right);\n } else {\n if (this.isRealNode(current.left)) queue.push(current.left);\n if (this.isRealNode(current.right)) queue.push(current.right);\n }\n }\n }\n }\n return ans;\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `leaves` function in TypeScript returns an array of values from leaf nodes in a binary tree\n * structure based on a specified callback and iteration type.\n * @param {C} callback - The `callback` parameter is a function that will be called on each leaf node\n * in the binary tree. It is optional and defaults to a default callback function if not provided.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `leaves`\n * method is used to specify the starting point for finding and processing the leaves of a binary\n * tree. It can be provided as either a key, a node, or an entry in the binary tree structure. If not\n * explicitly provided, the default value\n * @param {IterationType} iterationType - The `iterationType` parameter in the `leaves` method\n * specifies the type of iteration to be performed when collecting the leaves of a binary tree. It\n * can have two possible values:\n * @returns The `leaves` method returns an array of values that are the result of applying the\n * provided callback function to each leaf node in the binary tree.\n */\n leaves<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C>[] {\n startNode = this.ensureNode(startNode);\n const leaves: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];\n if (!this.isRealNode(startNode)) return [];\n\n if (iterationType === 'RECURSIVE') {\n const dfs = (cur: BinaryTreeNode<K, V>) => {\n if (this.isLeaf(cur)) {\n leaves.push(callback(cur));\n }\n if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right)) return;\n if (this.isRealNode(cur.left)) dfs(cur.left);\n if (this.isRealNode(cur.right)) dfs(cur.right);\n };\n\n dfs(startNode);\n } else {\n const queue = new Queue([startNode]);\n while (queue.length > 0) {\n const cur = queue.shift();\n if (this.isRealNode(cur)) {\n if (this.isLeaf(cur)) {\n leaves.push(callback(cur));\n }\n if (this.isRealNode(cur.left)) queue.push(cur.left);\n if (this.isRealNode(cur.right)) queue.push(cur.right);\n }\n }\n }\n\n return leaves;\n }\n\n listLevels<C extends NodeCallback<BinaryTreeNode<K, V>>>(\n callback?: C,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType,\n includeNull?: false\n ): ReturnType<C>[][];\n\n listLevels<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback?: C,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType,\n includeNull?: true\n ): ReturnType<C>[][];\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `listLevels` function in TypeScript generates a list of nodes at each level of a binary tree,\n * using either recursive or iterative traversal based on the specified iteration type.\n * @param {C} callback - The `callback` parameter is a function that will be applied to each node in\n * the binary tree during the traversal. It is used to process each node and determine what\n * information to include in the output for each level of the tree.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `listLevels` function represents the starting point for traversing the binary tree. It can be\n * either a key, a node, or an entry in the binary tree. If not provided, the default value is the\n * root of the binary tree.\n * @param {IterationType} iterationType - The `iterationType` parameter in the `listLevels` function\n * determines the type of iteration to be performed on the binary tree nodes. It can have two\n * possible values:\n * @param [includeNull=false] - The `includeNull` parameter in the `listLevels` method determines\n * whether or not to include null nodes in the traversal of the binary tree. If `includeNull` is set\n * to `true`, the traversal will include null nodes in the levels of the tree. If set to `false`,\n * null\n * @returns The `listLevels` method returns an array of arrays, where each inner array represents a\n * level in a binary tree. Each inner array contains the return value of the provided callback\n * function applied to the nodes at that level.\n */\n listLevels<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType,\n includeNull = false\n ): ReturnType<C>[][] {\n startNode = this.ensureNode(startNode);\n const levelsNodes: ReturnType<C>[][] = [];\n if (!startNode) return levelsNodes;\n\n if (iterationType === 'RECURSIVE') {\n const _recursive = (node: BinaryTreeNode<K, V> | null, level: number) => {\n if (!levelsNodes[level]) levelsNodes[level] = [];\n levelsNodes[level].push(callback(node));\n if (includeNull) {\n if (node && this.isRealNodeOrNull(node.left)) _recursive(node.left, level + 1);\n if (node && this.isRealNodeOrNull(node.right)) _recursive(node.right, level + 1);\n } else {\n if (node && node.left) _recursive(node.left, level + 1);\n if (node && node.right) _recursive(node.right, level + 1);\n }\n };\n\n _recursive(startNode, 0);\n } else {\n const stack: [BinaryTreeNode<K, V> | null, number][] = [[startNode, 0]];\n\n while (stack.length > 0) {\n const head = stack.pop()!;\n const [node, level] = head;\n\n if (!levelsNodes[level]) levelsNodes[level] = [];\n levelsNodes[level].push(callback(node));\n\n if (includeNull) {\n if (node && this.isRealNodeOrNull(node.right)) stack.push([node.right, level + 1]);\n if (node && this.isRealNodeOrNull(node.left)) stack.push([node.left, level + 1]);\n } else {\n if (node && node.right) stack.push([node.right, level + 1]);\n if (node && node.left) stack.push([node.left, level + 1]);\n }\n }\n }\n\n return levelsNodes;\n }\n\n morris<C extends NodeCallback<BinaryTreeNode<K, V>>>(\n callback?: C,\n pattern?: DFSOrderPattern,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): ReturnType<C>[];\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `morris` function in TypeScript performs a Depth-First Search traversal on a binary tree using\n * Morris Traversal algorithm with different order patterns.\n * @param {C} callback - The `callback` parameter in the `morris` function is a function that will be\n * called on each node in the binary tree during the traversal. It is of type `C`, which extends the\n * `NodeCallback<BinaryTreeNode<K, V> | null>` type. The default value for `callback` is `this._DEFAULT\n * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `morris` function specifies\n * the type of Depth-First Search (DFS) order pattern to traverse the binary tree. The possible\n * values for the `pattern` parameter are:\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `morris`\n * function is the starting point for the Morris traversal algorithm. It represents the root node of\n * the binary tree or the node from which the traversal should begin. It can be provided as either a\n * key, a node, an entry, or a reference\n * @returns The `morris` function is returning an array of values that are the result of applying the\n * provided callback function to each node in the binary tree in the specified order pattern (IN,\n * PRE, or POST).\n */\n morris<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n pattern: DFSOrderPattern = 'IN',\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root\n ): ReturnType<C>[] {\n startNode = this.ensureNode(startNode);\n if (!startNode) return [];\n const ans: ReturnType<NodeCallback<BinaryTreeNode<K, V> | null>>[] = [];\n\n let cur: BinaryTreeNode<K, V> | null | undefined = startNode;\n const _reverseEdge = (node: BinaryTreeNode<K, V> | null | undefined) => {\n let pre: BinaryTreeNode<K, V> | null | undefined = null;\n let next: BinaryTreeNode<K, V> | null | undefined = null;\n while (node) {\n next = node.right;\n node.right = pre;\n pre = node;\n node = next;\n }\n return pre;\n };\n const _printEdge = (node: BinaryTreeNode<K, V> | null | undefined) => {\n const tail: BinaryTreeNode<K, V> | null | undefined = _reverseEdge(node);\n let cur: BinaryTreeNode<K, V> | null | undefined = tail;\n while (cur) {\n ans.push(callback(cur));\n cur = cur.right;\n }\n _reverseEdge(tail);\n };\n switch (pattern) {\n case 'IN':\n while (cur) {\n if (cur.left) {\n const predecessor = this.getPredecessor(cur);\n if (!predecessor.right) {\n predecessor.right = cur;\n cur = cur.left;\n continue;\n } else {\n predecessor.right = null;\n }\n }\n ans.push(callback(cur));\n cur = cur.right;\n }\n break;\n case 'PRE':\n while (cur) {\n if (cur.left) {\n const predecessor = this.getPredecessor(cur);\n if (!predecessor.right) {\n predecessor.right = cur;\n ans.push(callback(cur));\n cur = cur.left;\n continue;\n } else {\n predecessor.right = null;\n }\n } else {\n ans.push(callback(cur));\n }\n cur = cur.right;\n }\n break;\n case 'POST':\n while (cur) {\n if (cur.left) {\n const predecessor = this.getPredecessor(cur);\n if (predecessor.right === null) {\n predecessor.right = cur;\n cur = cur.left;\n continue;\n } else {\n predecessor.right = null;\n _printEdge(cur.left);\n }\n }\n cur = cur.right;\n }\n _printEdge(startNode);\n break;\n }\n return ans;\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `clone` function creates a deep copy of a tree structure by traversing it using breadth-first\n * search.\n * @returns The `clone()` method is returning a cloned copy of the tree with the same structure and\n * values as the original tree. The method creates a new tree, iterates over the nodes of the\n * original tree using breadth-first search (bfs), and adds the nodes to the new tree. If a node in\n * the original tree is null, a null node is added to the cloned tree. If a node\n */\n clone() {\n const cloned = this.createTree();\n this._clone(cloned);\n return cloned;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function iterates over key-value pairs in a tree data structure and creates a new\n * tree with elements that satisfy a given predicate.\n * @param predicate - The `predicate` parameter in the `filter` method is a function that will be\n * called with four arguments: the `value` of the current entry, the `key` of the current entry, the\n * `index` of the current entry in the iteration, and the reference to the tree itself (`\n * @param {any} [thisArg] - The `thisArg` parameter in the `filter` method allows you to specify the\n * value of `this` that should be used when executing the `predicate` function. This is useful when\n * the `predicate` function relies on the context of a specific object or value. By providing a\n * `thisArg\n * @returns The `filter` method is returning a new tree that contains entries that pass the provided\n * predicate function.\n */\n filter(predicate: EntryCallback<K, V | undefined, boolean>, thisArg?: any) {\n const newTree = this.createTree();\n let index = 0;\n for (const [key, value] of this) {\n if (predicate.call(thisArg, key, value, index++, this)) {\n newTree.add([key, value]);\n }\n }\n return newTree;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function in TypeScript creates a new BinaryTree by applying a callback function to each\n * entry in the original BinaryTree.\n * @param callback - A function that will be called for each entry in the current binary tree. It\n * takes the key, value (which can be undefined), and an array containing the mapped key and value as\n * arguments.\n * @param [options] - The `options` parameter in the `map` method is of type `BinaryTreeOptions<MK,\n * MV, MR>`. It is an optional parameter that allows you to specify additional options for the binary\n * tree being created during the mapping process. These options could include things like custom\n * comparators, initial\n * @param {any} [thisArg] - The `thisArg` parameter in the `map` method is used to specify the value\n * of `this` when executing the `callback` function. It allows you to set the context (value of\n * `this`) within the callback function. If `thisArg` is provided, it will be passed\n * @returns The `map` function is returning a new `BinaryTree` instance filled with entries that are\n * the result of applying the provided `callback` function to each entry in the original tree.\n */\n map(\n callback: EntryCallback<K, V | undefined, [MK, MV]>,\n options?: BinaryTreeOptions<MK, MV, MR>,\n thisArg?: any\n ): BinaryTree<MK, MV, MR> {\n const newTree = new BinaryTree<MK, MV, MR>([], options);\n let index = 0;\n for (const [key, value] of this) {\n newTree.add(callback.call(thisArg, key, value, index++, this));\n }\n return newTree;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `toVisual` in TypeScript overrides the visual representation of a binary tree with\n * customizable options for displaying undefined, null, and sentinel nodes.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `toVisual` method is used to specify the starting point for visualizing the binary tree structure.\n * It can be a node, key, entry, or the root of the tree. If no specific starting point is provided,\n * the default is set to the root\n * @param {BinaryTreePrintOptions} [options] - The `options` parameter in the `toVisual` method is an\n * object that contains the following properties:\n * @returns The `override toVisual` method returns a string that represents the visual display of the\n * binary tree based on the provided options for showing undefined, null, and Red-Black NIL nodes.\n * The method constructs the visual representation by calling the `_displayAux` method and appending\n * the lines to the output string. The final output string contains the visual representation of the\n * binary tree with the specified options.\n */\n override toVisual(\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n options?: BinaryTreePrintOptions\n ): string {\n const opts = { isShowUndefined: false, isShowNull: true, isShowRedBlackNIL: false, ...options };\n startNode = this.ensureNode(startNode);\n let output = '';\n if (!startNode) return output;\n\n if (opts.isShowUndefined) output += `U for undefined\\n`;\n if (opts.isShowNull) output += `N for null\\n`;\n if (opts.isShowRedBlackNIL) output += `S for Sentinel Node(NIL)\\n`;\n\n const display = (root: BinaryTreeNode<K, V> | null | undefined): void => {\n const [lines] = this._displayAux(root, opts);\n let paragraph = '';\n for (const line of lines) {\n paragraph += line + '\\n';\n }\n output += paragraph;\n };\n\n display(startNode);\n return output;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `print` in TypeScript overrides the default print behavior to log a visual\n * representation of the binary tree to the console.\n * @param {BinaryTreePrintOptions} [options] - The `options` parameter is used to specify the\n * printing options for the binary tree. It is an optional parameter that allows you to customize how\n * the binary tree is printed, such as choosing between different traversal orders or formatting\n * options.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the\n * `override print` method is used to specify the starting point for printing the binary tree. It can\n * be either a key, a node, an entry, or the root of the tree. If no specific starting point is\n * provided, the default value is set to\n */\n override print(\n options?: BinaryTreePrintOptions,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root\n ) {\n console.log(this.toVisual(startNode, options));\n }\n\n protected _clone(cloned: BinaryTree<K, V, R, MK, MV, MR>) {\n this.bfs(\n node => {\n if (node === null) cloned.add(null);\n else {\n if (this._isMapMode) cloned.add([node.key, this._store.get(node.key)]);\n else cloned.add([node.key, node.value]);\n }\n },\n this._root,\n this.iterationType,\n true\n );\n if (this._isMapMode) cloned._store = this._store;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `keyValueNodeEntryRawToNodeAndValue` converts various input types into a node object\n * or returns null.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The\n * `keyValueNodeEntryRawToNodeAndValue` function takes in a parameter `keyNodeOrEntry`, which\n * can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. This parameter represents either a key, a\n * node, an entry\n * @param {V} [value] - The `value` parameter in the `keyValueNodeEntryRawToNodeAndValue` function is\n * an optional parameter of type `V`. It represents the value associated with the key in the node\n * being created. If a `value` is provided, it will be used when creating the node. If\n * @returns The `keyValueNodeEntryRawToNodeAndValue` function returns an optional node\n * (`BinaryTreeNode<K, V> | null | undefined`) based on the input parameters provided. The function checks the type of the\n * input parameter (`keyNodeOrEntry`) and processes it accordingly to return a node or null\n * value.\n */\n protected _keyValueNodeOrEntryToNodeAndValue(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V\n ): [BinaryTreeNode<K, V> | null | undefined, V | undefined] {\n if (keyNodeOrEntry === undefined) return [undefined, undefined];\n if (keyNodeOrEntry === null) return [null, undefined];\n\n if (this.isNode(keyNodeOrEntry)) return [keyNodeOrEntry, value];\n\n if (this.isEntry(keyNodeOrEntry)) {\n const [key, entryValue] = keyNodeOrEntry;\n if (key === undefined) return [undefined, undefined];\n else if (key === null) return [null, undefined];\n const finalValue = value ?? entryValue;\n return [this.createNode(key, finalValue), finalValue];\n }\n\n return [this.createNode(keyNodeOrEntry, value), value];\n }\n\n protected _dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(\n callback: C,\n pattern?: DFSOrderPattern,\n onlyOne?: boolean,\n startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType?: IterationType,\n includeNull?: boolean,\n shouldVisitLeft?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean,\n shouldVisitRight?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean,\n shouldVisitRoot?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean,\n shouldProcessRoot?: (node: BinaryTreeNode<K, V> | null | undefined) => boolean\n ): ReturnType<C>[];\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `_dfs` function performs a depth-first search traversal on a binary tree, with customizable\n * options for traversal order and node processing.\n * @param {C} callback - The `callback` parameter in the `_dfs` method is a function that will be\n * called on each node visited during the depth-first search traversal. It is a generic type `C` that\n * extends `NodeCallback<BinaryTreeNode<K, V> | null>`. The default value for `callback`\n * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the\n * order in which the nodes are visited during a depth-first search traversal. It can have one of the\n * following values:\n * @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `_dfs` method is a boolean flag\n * that determines whether the traversal should stop after processing a single node. If `onlyOne` is\n * set to `true`, the traversal will return as soon as a single node is processed. If it is set to\n * `false\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined}\n * startNode - The `startNode` parameter in the `_dfs` method is used to specify the starting node\n * for the depth-first search traversal. It can be provided in different forms:\n * @param {IterationType} iterationType - The `iterationType` parameter in the `_dfs` method\n * specifies whether the traversal should be done recursively or iteratively. It can have two\n * possible values:\n * @param [includeNull=false] - The `includeNull` parameter in the `_dfs` method determines whether\n * null nodes should be included in the traversal process. If `includeNull` is set to `true`, the\n * method will consider null nodes as valid nodes to visit or process. If `includeNull` is set to\n * `false`,\n * @param shouldVisitLeft - The `shouldVisitLeft` parameter in the `_dfs` method is a function that\n * determines whether the left child of a node should be visited during the Depth-First Search\n * traversal. By default, it checks if the node is not null or undefined before visiting the left\n * child. You can customize this behavior\n * @param shouldVisitRight - The `shouldVisitRight` parameter in the `_dfs` method is a function that\n * determines whether to visit the right child node of the current node during a depth-first search\n * traversal. The default implementation of this function checks if the node is not null or undefined\n * before deciding to visit it.\n * @param shouldVisitRoot - The `shouldVisitRoot` parameter in the `_dfs` method is a function that\n * determines whether a given node should be visited during the depth-first search traversal. The\n * function takes a node as an argument and returns a boolean value indicating whether the node\n * should be visited.\n * @param shouldProcessRoot - The `shouldProcessRoot` parameter in the `_dfs` method is a function\n * that determines whether the root node should be processed during the Depth-First Search traversal.\n * It takes a node (BinaryTreeNode<K, V> | null | undefined) as input and returns a boolean value. If\n * the function\n * @returns The `_dfs` method returns an array of the return type of the provided callback function\n * `C`.\n */\n protected _dfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n pattern: DFSOrderPattern = 'IN',\n onlyOne: boolean = false,\n startNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType,\n includeNull = false,\n shouldVisitLeft: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => !!node,\n shouldVisitRight: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => !!node,\n shouldVisitRoot: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => {\n if (includeNull) return this.isRealNodeOrNull(node);\n return this.isRealNode(node);\n },\n shouldProcessRoot: (node: BinaryTreeNode<K, V> | null | undefined) => boolean = node => this.isRealNodeOrNull(node)\n ): ReturnType<C>[] {\n startNode = this.ensureNode(startNode);\n if (!startNode) return [];\n const ans: ReturnType<C>[] = [];\n\n if (iterationType === 'RECURSIVE') {\n const dfs = (node: BinaryTreeNode<K, V> | null) => {\n if (!shouldVisitRoot(node)) return;\n\n const visitLeft = () => {\n if (shouldVisitLeft(node) && node?.left !== undefined) dfs(node?.left);\n };\n const visitRight = () => {\n if (shouldVisitRight(node) && node?.right !== undefined) dfs(node?.right);\n };\n\n switch (pattern) {\n case 'IN':\n visitLeft();\n if (shouldProcessRoot(node)) {\n ans.push(callback(node));\n if (onlyOne) return;\n }\n visitRight();\n break;\n case 'PRE':\n if (shouldProcessRoot(node)) {\n ans.push(callback(node));\n if (onlyOne) return;\n }\n visitLeft();\n visitRight();\n break;\n case 'POST':\n visitLeft();\n visitRight();\n if (shouldProcessRoot(node)) {\n ans.push(callback(node));\n if (onlyOne) return;\n }\n break;\n }\n };\n\n dfs(startNode);\n } else {\n const stack: DFSStackItem<BinaryTreeNode<K, V>>[] = [{ opt: DFSOperation.VISIT, node: startNode }];\n\n const pushLeft = (cur: DFSStackItem<BinaryTreeNode<K, V>>) => {\n if (shouldVisitLeft(cur.node)) stack.push({ opt: DFSOperation.VISIT, node: cur.node?.left });\n };\n const pushRight = (cur: DFSStackItem<BinaryTreeNode<K, V>>) => {\n if (shouldVisitRight(cur.node)) stack.push({ opt: DFSOperation.VISIT, node: cur.node?.right });\n };\n const pushRoot = (cur: DFSStackItem<BinaryTreeNode<K, V>>) => {\n if (shouldVisitRoot(cur.node)) stack.push({ opt: DFSOperation.PROCESS, node: cur.node });\n };\n\n while (stack.length > 0) {\n const cur = stack.pop();\n if (cur === undefined) continue;\n if (!shouldVisitRoot(cur.node)) continue;\n if (cur.opt === DFSOperation.PROCESS) {\n if (shouldProcessRoot(cur.node) && cur.node !== undefined) {\n ans.push(callback(cur.node));\n if (onlyOne) return ans;\n }\n } else {\n switch (pattern) {\n case 'IN':\n pushRight(cur);\n pushRoot(cur);\n pushLeft(cur);\n break;\n case 'PRE':\n pushRight(cur);\n pushLeft(cur);\n pushRoot(cur);\n break;\n case 'POST':\n pushRoot(cur);\n pushRight(cur);\n pushLeft(cur);\n break;\n }\n }\n }\n }\n\n return ans;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_getIterator` returns an iterable iterator for a binary tree data structure, either\n * using an iterative approach or a recursive approach based on the specified iteration type.\n * @param node - The `node` parameter in the `_getIterator` method represents the current node being\n * processed during iteration. It is initially set to the root node of the data structure (or the\n * node passed as an argument), and then it is traversed through the data structure based on the\n * iteration type specified (`ITER\n * @returns The `_getIterator` method returns an IterableIterator containing key-value pairs of nodes\n * in a binary tree structure. The method uses an iterative approach to traverse the tree based on\n * the `iterationType` property. If the `iterationType` is set to 'ITERATIVE', the method uses a\n * stack to perform an in-order traversal of the tree. If the `iterationType` is not 'ITERATIVE\n */\n protected *_getIterator(node = this._root): IterableIterator<[K, V | undefined]> {\n if (!node) return;\n\n if (this.iterationType === 'ITERATIVE') {\n const stack: (BinaryTreeNode<K, V> | null | undefined)[] = [];\n let current: BinaryTreeNode<K, V> | null | undefined = node;\n\n while (current || stack.length > 0) {\n while (this.isRealNode(current)) {\n stack.push(current);\n current = current.left;\n }\n\n current = stack.pop();\n\n if (this.isRealNode(current)) {\n if (this._isMapMode) yield [current.key, this._store.get(current.key)];\n else yield [current.key, current.value];\n current = current.right;\n }\n }\n } else {\n if (node.left && this.isRealNode(node)) {\n yield* this[Symbol.iterator](node.left);\n }\n if (this._isMapMode) yield [node.key, this._store.get(node.key)];\n else yield [node.key, node.value];\n if (node.right && this.isRealNode(node)) {\n yield* this[Symbol.iterator](node.right);\n }\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `_displayAux` in TypeScript is responsible for generating the display layout of nodes\n * in a binary tree based on specified options.\n * @param node - The `node` parameter in the `_displayAux` function represents a node in a binary\n * tree. It can be either a valid node containing a key or a special type of node like null,\n * undefined, or a Red-Black tree NIL node. The function checks the type of the node and its\n * @param {BinaryTreePrintOptions} options - The `options` parameter in the `_displayAux` function\n * contains the following properties:\n * @returns The `_displayAux` function returns a `NodeDisplayLayout`, which is an array containing\n * information about how to display a node in a binary tree. The `NodeDisplayLayout` consists of four\n * elements:\n */\n protected _displayAux(\n node: BinaryTreeNode<K, V> | null | undefined,\n options: BinaryTreePrintOptions\n ): NodeDisplayLayout {\n const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;\n const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];\n\n // Check if node is null or undefined or key is NaN\n if (node === null && !isShowNull) {\n return emptyDisplayLayout;\n } else if (node === undefined && !isShowUndefined) {\n return emptyDisplayLayout;\n } else if (this.isNIL(node) && !isShowRedBlackNIL) {\n return emptyDisplayLayout;\n } else if (node !== null && node !== undefined) {\n // Display logic of normal nodes\n\n const key = node.key,\n line = this.isNIL(node) ? 'S' : String(key),\n width = line.length;\n\n return _buildNodeDisplay(\n line,\n width,\n this._displayAux(node.left, options),\n this._displayAux(node.right, options)\n );\n } else {\n // For cases where none of the conditions are met, null, undefined, and NaN nodes are not displayed\n const line = node === undefined ? 'U' : 'N',\n width = line.length;\n\n return _buildNodeDisplay(line, width, [[''], 1, 0, 0], [[''], 1, 0, 0]);\n }\n\n function _buildNodeDisplay(line: string, width: number, left: NodeDisplayLayout, right: NodeDisplayLayout) {\n const [leftLines, leftWidth, leftHeight, leftMiddle] = left;\n const [rightLines, rightWidth, rightHeight, rightMiddle] = right;\n const firstLine =\n ' '.repeat(Math.max(0, leftMiddle + 1)) +\n '_'.repeat(Math.max(0, leftWidth - leftMiddle - 1)) +\n line +\n '_'.repeat(Math.max(0, rightMiddle)) +\n ' '.repeat(Math.max(0, rightWidth - rightMiddle));\n\n const secondLine =\n (leftHeight > 0\n ? ' '.repeat(leftMiddle) + '/' + ' '.repeat(leftWidth - leftMiddle - 1)\n : ' '.repeat(leftWidth)) +\n ' '.repeat(width) +\n (rightHeight > 0\n ? ' '.repeat(rightMiddle) + '\\\\' + ' '.repeat(rightWidth - rightMiddle - 1)\n : ' '.repeat(rightWidth));\n\n const mergedLines = [firstLine, secondLine];\n\n for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {\n const leftLine = i < leftHeight ? leftLines[i] : ' '.repeat(leftWidth);\n const rightLine = i < rightHeight ? rightLines[i] : ' '.repeat(rightWidth);\n mergedLines.push(leftLine + ' '.repeat(width) + rightLine);\n }\n\n return <NodeDisplayLayout>[\n mergedLines,\n leftWidth + width + rightWidth,\n Math.max(leftHeight, rightHeight) + 2,\n leftWidth + Math.floor(width / 2)\n ];\n }\n }\n\n protected _DEFAULT_NODE_CALLBACK = (node: BinaryTreeNode<K, V> | null | undefined) => (node ? node.key : undefined);\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The _swapProperties function swaps key and value properties between two nodes in a binary tree.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } srcNode - The `srcNode` parameter in the\n * `_swapProperties` method can be either a BTNRep object containing key and value\n * properties, or it can be of type R.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } destNode - The `destNode` parameter in the\n * `_swapProperties` method represents the node or entry where the properties will be swapped with\n * the `srcNode`. It can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. The method ensures that\n * both `srcNode\n * @returns The `_swapProperties` method returns either the `destNode` with its key and value swapped\n * with the `srcNode`, or `undefined` if either `srcNode` or `destNode` is falsy.\n */\n protected _swapProperties(\n srcNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n destNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): BinaryTreeNode<K, V> | undefined {\n srcNode = this.ensureNode(srcNode);\n destNode = this.ensureNode(destNode);\n\n if (srcNode && destNode) {\n const { key, value } = destNode;\n const tempNode = this.createNode(key, value);\n\n if (tempNode) {\n destNode.key = srcNode.key;\n if (!this._isMapMode) destNode.value = srcNode.value;\n\n srcNode.key = tempNode.key;\n if (!this._isMapMode) srcNode.value = tempNode.value;\n }\n\n return destNode;\n }\n return undefined;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The _replaceNode function replaces an old node with a new node in a binary tree structure.\n * @param {BinaryTreeNode<K, V>} oldNode - The `oldNode` parameter represents the node that you want to replace in a\n * tree data structure.\n * @param {BinaryTreeNode<K, V>} newNode - The `newNode` parameter in the `_replaceNode` function represents the node\n * that will replace the `oldNode` in a tree data structure. This function is responsible for\n * updating the parent, left child, right child, and root (if necessary) references when replacing a\n * node in the tree.\n * @returns The method `_replaceNode` is returning the `newNode` that was passed as a parameter after\n * replacing the `oldNode` with it in the binary tree structure.\n */\n protected _replaceNode(oldNode: BinaryTreeNode<K, V>, newNode: BinaryTreeNode<K, V>): BinaryTreeNode<K, V> {\n if (oldNode.parent) {\n if (oldNode.parent.left === oldNode) {\n oldNode.parent.left = newNode;\n } else if (oldNode.parent.right === oldNode) {\n oldNode.parent.right = newNode;\n }\n }\n newNode.left = oldNode.left;\n newNode.right = oldNode.right;\n newNode.parent = oldNode.parent;\n if (this._root === oldNode) {\n this._setRoot(newNode);\n }\n\n return newNode;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function _setRoot sets the root node of a data structure while updating the parent reference\n * of the previous root node.\n * @param v - The parameter `v` in the `_setRoot` method is of type `BinaryTreeNode<K, V> | null | undefined`, which means\n * it can either be an optional `BinaryTreeNode<K, V>` type or `null`.\n */\n protected _setRoot(v: BinaryTreeNode<K, V> | null | undefined) {\n if (v) {\n v.parent = undefined;\n }\n this._root = v;\n }\n\n protected _ensurePredicate(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V>>\n ): NodePredicate<BinaryTreeNode<K, V>>;\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_ensurePredicate` in TypeScript ensures that the input is converted into a valid\n * predicate function for a binary tree node.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The\n * `_ensurePredicate` method in the provided code snippet is responsible for ensuring that the input\n * parameter `keyNodeEntryOrPredicate` is transformed into a valid predicate function that can be\n * used for filtering nodes in a binary tree.\n * @returns A NodePredicate<BinaryTreeNode<K, V>> function is being returned.\n */\n protected _ensurePredicate(\n keyNodeEntryOrPredicate:\n | K\n | BinaryTreeNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BinaryTreeNode<K, V> | null>\n ): NodePredicate<BinaryTreeNode<K, V> | null> {\n if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined)\n return (node: BinaryTreeNode<K, V> | null | undefined) => (node ? false : false);\n\n if (this._isPredicate(keyNodeEntryOrPredicate)) return keyNodeEntryOrPredicate;\n\n if (this.isRealNode(keyNodeEntryOrPredicate))\n return (node: BinaryTreeNode<K, V> | null) => node === keyNodeEntryOrPredicate;\n\n if (this.isEntry(keyNodeEntryOrPredicate)) {\n const [key] = keyNodeEntryOrPredicate;\n return (node: BinaryTreeNode<K, V> | null) => {\n if (!node) return false;\n return node.key === key;\n };\n }\n\n return (node: BinaryTreeNode<K, V> | null) => {\n if (!node) return false;\n return node.key === keyNodeEntryOrPredicate;\n };\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_isPredicate` checks if a given parameter is a function.\n * @param {any} p - The parameter `p` is a variable of type `any`, which means it can hold any type\n * of value. In this context, the function `_isPredicate` is checking if `p` is a function that\n * satisfies the type `NodePredicate<BinaryTreeNode<K, V>>`.\n * @returns The function is checking if the input `p` is a function and returning a boolean value\n * based on that check. If `p` is a function, it will return `true`, indicating that `p` is a\n * predicate function for a binary tree node. If `p` is not a function, it will return `false`.\n */\n protected _isPredicate(p: any): p is NodePredicate<BinaryTreeNode<K, V>> {\n return typeof p === 'function';\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_extractKey` in TypeScript returns the key from a given input, which can be a node,\n * entry, raw data, or null/undefined.\n * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `_extractKey` method you provided is a\n * TypeScript method that takes in a parameter `keyNodeOrEntry` of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `,\n * where `BTNRep` is a generic type with keys `K`, `V`, and `BinaryTreeNode<K, V>`, and `\n * @returns The `_extractKey` method returns the key value extracted from the `keyNodeOrEntry`\n * parameter. The return value can be a key value of type `K`, `null`, or `undefined`, depending on\n * the conditions checked in the method.\n */\n protected _extractKey(\n keyNodeOrEntry: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): K | null | undefined {\n if (keyNodeOrEntry === null) return null;\n if (keyNodeOrEntry === undefined) return;\n if (keyNodeOrEntry === this._NIL) return;\n if (this.isNode(keyNodeOrEntry)) return keyNodeOrEntry.key;\n\n if (this.isEntry(keyNodeOrEntry)) return keyNodeOrEntry[0];\n\n return keyNodeOrEntry;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_setValue` sets a value in a store based on a key, handling cases where the key or\n * value is null or undefined.\n * @param {K | null | undefined} key - The `key` parameter can be of type `K`, `null`, or\n * `undefined`.\n * @param {V | undefined} value - The `value` parameter in the `_setValue` method can be of type `V`\n * or `undefined`.\n * @returns The method `_setValue` returns `false` if either the `key` is `null` or `undefined`, or\n * if the `value` is `undefined`. Otherwise, it returns the result of calling the `set` method on the\n * `_store` object with the `key` and `value` arguments.\n */\n protected _setValue(key: K | null | undefined, value: V | undefined) {\n if (key === null || key === undefined) return false;\n if (value === undefined) return false;\n return this._store.set(key, value);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The _clearNodes function sets the root node to undefined and resets the size to 0.\n */\n protected _clearNodes() {\n this._setRoot(undefined);\n this._size = 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The _clearValues function clears all values stored in the _store object.\n */\n protected _clearValues() {\n this._store.clear();\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type {\n BSTNOptKeyOrNode,\n BSTOptions,\n BTNRep,\n Comparable,\n Comparator,\n CP,\n DFSOrderPattern,\n EntryCallback,\n IterationType,\n NodeCallback,\n NodePredicate,\n OptNode\n} from '../../types';\nimport { BinaryTree, BinaryTreeNode } from './binary-tree';\nimport { IBinaryTree } from '../../interfaces';\nimport { Queue } from '../queue';\nimport { isComparable } from '../../utils';\nimport { Range } from '../../common';\n\nexport class BSTNode<K = any, V = any> extends BinaryTreeNode<K, V> {\n override parent?: BSTNode<K, V> = undefined;\n\n /**\n * This TypeScript constructor function initializes an instance with a key and an optional value.\n * @param {K} key - The `key` parameter is typically used to uniquely identify an object or element\n * within a data structure. It serves as a reference or identifier for accessing or manipulating the\n * associated value.\n * @param {V} [value] - The `value` parameter in the constructor is optional, meaning it does not\n * have to be provided when creating an instance of the class. If a value is not provided, it will\n * default to `undefined`.\n */\n constructor(key: K, value?: V) {\n super(key, value);\n }\n\n override _left?: BSTNode<K, V> | null | undefined = undefined;\n\n override get left(): BSTNode<K, V> | null | undefined {\n return this._left;\n }\n\n override set left(v: BSTNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._left = v;\n }\n\n override _right?: BSTNode<K, V> | null | undefined = undefined;\n\n override get right(): BSTNode<K, V> | null | undefined {\n return this._right;\n }\n\n override set right(v: BSTNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n}\n\n/**\n * 1. Node Order: Each node's left child has a lesser value, and the right child has a greater value.\n * 2. Unique Keys: No duplicate keys in a standard BST.\n * 3. Efficient Search: Enables quick search, minimum, and maximum operations.\n * 4. Inorder Traversal: Yields nodes in ascending order.\n * 5. Logarithmic Operations: Ideal operations like insertion, deletion, and searching are O(log n) time-efficient.\n * 6. Balance Variability: Can become unbalanced; special types maintain balance.\n * 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.\n * @example\n * // Merge 3 sorted datasets\n * const dataset1 = new BST<number, string>([\n * [1, 'A'],\n * [7, 'G']\n * ]);\n * const dataset2 = [\n * [2, 'B'],\n * [6, 'F']\n * ];\n * const dataset3 = new BST<number, string>([\n * [3, 'C'],\n * [5, 'E'],\n * [4, 'D']\n * ]);\n *\n * // Merge datasets into a single BinarySearchTree\n * const merged = new BST<number, string>(dataset1);\n * merged.addMany(dataset2);\n * merged.merge(dataset3);\n *\n * // Verify merged dataset is in sorted order\n * console.log([...merged.values()]); // ['A', 'B', 'C', 'D', 'E', 'F', 'G']\n * @example\n * // Find elements in a range\n * const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);\n * console.log(bst.search(new Range(5, 10))); // [5, 7, 10]\n * console.log(bst.rangeSearch([4, 12], node => node.key.toString())); // ['5', '7', '10', '12']\n * console.log(bst.search(new Range(4, 12, true, false))); // [5, 7, 10]\n * console.log(bst.rangeSearch([15, 20])); // [15, 18]\n * console.log(bst.search(new Range(15, 20, false))); // [18]\n * @example\n * // Find lowest common ancestor\n * const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);\n *\n * // LCA helper function\n * const findLCA = (num1: number, num2: number): number | undefined => {\n * const path1 = bst.getPathToRoot(num1);\n * const path2 = bst.getPathToRoot(num2);\n * // Find the first common ancestor\n * return findFirstCommon(path1, path2);\n * };\n *\n * function findFirstCommon(arr1: number[], arr2: number[]): number | undefined {\n * for (const num of arr1) {\n * if (arr2.indexOf(num) !== -1) {\n * return num;\n * }\n * }\n * return undefined;\n * }\n *\n * // Assertions\n * console.log(findLCA(3, 10)); // 7\n * console.log(findLCA(5, 35)); // 15\n * console.log(findLCA(20, 30)); // 25\n */\nexport class BST<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends BinaryTree<K, V, R, MK, MV, MR>\n implements IBinaryTree<K, V, R, MK, MV, MR>\n{\n /**\n * This TypeScript constructor initializes a binary search tree with optional options and adds\n * elements if provided.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an\n * iterable that can contain elements of type `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It is used to\n * initialize the binary search tree with keys, nodes, entries, or raw data.\n * @param [options] - The `options` parameter is an optional object that can contain the following\n * properties:\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n > = [],\n options?: BSTOptions<K, V, R>\n ) {\n super([], options);\n\n if (options) {\n const { specifyComparable, isReverse } = options;\n if (typeof specifyComparable === 'function') this._specifyComparable = specifyComparable;\n if (isReverse !== undefined) this._isReverse = isReverse;\n }\n\n if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);\n }\n\n protected override _root?: BSTNode<K, V> = undefined;\n\n override get root(): OptNode<BSTNode<K, V>> {\n return this._root;\n }\n\n protected _isReverse: boolean = false;\n\n get isReverse(): boolean {\n return this._isReverse;\n }\n\n protected _comparator: Comparator<K> = (a: K, b: K): number => {\n if (isComparable(a) && isComparable(b)) {\n if (a > b) return 1;\n if (a < b) return -1;\n return 0;\n }\n if (this._specifyComparable) {\n if (this._specifyComparable(a) > this._specifyComparable(b)) return 1;\n if (this._specifyComparable(a) < this._specifyComparable(b)) return -1;\n return 0;\n }\n if (typeof a === 'object' || typeof b === 'object') {\n throw TypeError(\n `When comparing object types, a custom specifyComparable must be defined in the constructor's options parameter.`\n );\n }\n\n return 0;\n };\n\n get comparator() {\n return this._comparator;\n }\n\n protected _specifyComparable?: (key: K) => Comparable;\n\n get specifyComparable() {\n return this._specifyComparable;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a new BSTNode with the given key and value and returns it.\n * @param {K} key - The key parameter is of type K, which represents the type of the key for the node\n * being created.\n * @param {V} [value] - The \"value\" parameter is an optional parameter of type V. It represents the\n * value associated with the key in the node being created.\n * @returns The method is returning a new instance of the BSTNode class, casted as the BSTNode<K, V> type.\n */\n override createNode(key: K, value?: V): BSTNode<K, V> {\n return new BSTNode<K, V>(key, this._isMapMode ? undefined : value);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a new binary search tree with the specified options.\n * @param [options] - The `options` parameter is an optional object that allows you to customize the\n * behavior of the `createTree` method. It accepts a partial `BSTOptions` object, which has the\n * following properties:\n * @returns a new instance of the BST class with the provided options.\n */\n override createTree(options?: BSTOptions<K, V, R>) {\n return new BST<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n isMapMode: this._isMapMode,\n specifyComparable: this._specifyComparable,\n toEntryFn: this._toEntryFn,\n isReverse: this._isReverse,\n ...options\n });\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function ensures the existence of a node in a data structure and returns it, or undefined if\n * it doesn't exist.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can accept a value of type `R`, which represents the key, node,\n * entry, or raw element that needs to be ensured in the tree.\n * @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional\n * parameter that specifies the type of iteration to be used when ensuring a node. It has a default\n * value of `'ITERATIVE'`.\n * @returns The method is returning either the node that was ensured or `undefined` if the node could\n * not be ensured.\n */\n override ensureNode(\n keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n iterationType: IterationType = this.iterationType\n ): OptNode<BSTNode<K, V>> {\n return super.ensureNode(keyNodeOrEntry, iterationType) ?? undefined;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if the input is an instance of the BSTNode class.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be of type `R` or `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.\n * @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is\n * an instance of the `BSTNode` class.\n */\n override isNode(\n keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is BSTNode<K, V> {\n return keyNodeOrEntry instanceof BSTNode;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function \"override isValidKey\" checks if a key is comparable based on a given comparator.\n * @param {any} key - The `key` parameter is a value that will be checked to determine if it is of\n * type `K`.\n * @returns The `override isValidKey(key: any): key is K` function is returning a boolean value based on\n * the result of the `isComparable` function with the condition `this._compare !==\n * this._DEFAULT_COMPARATOR`.\n */\n override isValidKey(key: any): key is K {\n return isComparable(key, this._specifyComparable !== undefined);\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The `add` function in TypeScript adds a new node to a binary search tree based on the key value.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can accept a value of type `R` or `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.\n * @param {V} [value] - The `value` parameter is an optional value that can be associated with the\n * key in the binary search tree. If provided, it will be stored in the node along with the key.\n * @returns a boolean value.\n */\n override add(\n keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V\n ): boolean {\n const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);\n if (newNode === undefined) return false;\n\n if (this._root === undefined) {\n this._setRoot(newNode);\n if (this._isMapMode) this._setValue(newNode?.key, newValue);\n this._size++;\n return true;\n }\n\n let current = this._root;\n while (current !== undefined) {\n if (this._compare(current.key, newNode.key) === 0) {\n this._replaceNode(current, newNode);\n if (this._isMapMode) this._setValue(current.key, newValue);\n return true;\n } else if (this._compare(current.key, newNode.key) > 0) {\n if (current.left === undefined) {\n current.left = newNode;\n if (this._isMapMode) this._setValue(newNode?.key, newValue);\n this._size++;\n return true;\n }\n if (current.left !== null) current = current.left;\n } else {\n if (current.right === undefined) {\n current.right = newNode;\n if (this._isMapMode) this._setValue(newNode?.key, newValue);\n this._size++;\n return true;\n }\n if (current.right !== null) current = current.right;\n }\n }\n\n return false;\n }\n\n /**\n * Time Complexity: O(k log n)\n * Space Complexity: O(k + log n)\n *\n * The `addMany` function in TypeScript adds multiple keys or nodes to a data structure and returns\n * an array indicating whether each key or node was successfully inserted.\n * @param keysNodesEntriesOrRaws - An iterable containing keys, nodes, entries, or raw\n * elements to be added to the data structure.\n * @param [values] - An optional iterable of values to be associated with the keys or nodes being\n * added. If provided, the values will be assigned to the corresponding keys or nodes in the same\n * order. If not provided, undefined will be assigned as the value for each key or node.\n * @param [isBalanceAdd=true] - A boolean flag indicating whether the tree should be balanced after\n * adding the elements. If set to true, the tree will be balanced using a binary search tree\n * algorithm. If set to false, the elements will be added without balancing the tree. The default\n * value is true.\n * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that\n * specifies the type of iteration to use when adding multiple keys or nodes to the binary search\n * tree. It can have two possible values:\n * @returns The function `addMany` returns an array of booleans indicating whether each element was\n * successfully inserted into the data structure.\n */\n override addMany(\n keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, BSTNode<K, V>>>,\n values?: Iterable<V | undefined>,\n isBalanceAdd = true,\n iterationType: IterationType = this.iterationType\n ): boolean[] {\n const inserted: boolean[] = [];\n\n let valuesIterator: Iterator<V | undefined> | undefined;\n\n if (values) {\n valuesIterator = values[Symbol.iterator]();\n }\n\n if (!isBalanceAdd) {\n for (let kve of keysNodesEntriesOrRaws) {\n const value = valuesIterator?.next().value;\n if (this.isRaw(kve)) kve = this._toEntryFn!(kve);\n inserted.push(this.add(kve, value));\n }\n return inserted;\n }\n\n const realBTNExemplars: {\n key: R | K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined;\n value: V | undefined;\n orgIndex: number;\n }[] = [];\n\n let i = 0;\n for (const kve of keysNodesEntriesOrRaws) {\n realBTNExemplars.push({ key: kve, value: valuesIterator?.next().value, orgIndex: i });\n i++;\n }\n\n let sorted: {\n key: R | K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined;\n value: V | undefined;\n orgIndex: number;\n }[] = [];\n\n sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => {\n let keyA: K | undefined | null, keyB: K | undefined | null;\n if (this.isRaw(a)) keyA = this._toEntryFn!(a)[0];\n else if (this.isEntry(a)) keyA = a[0];\n else if (this.isRealNode(a)) keyA = a.key;\n else {\n keyA = a as K;\n }\n\n if (this.isRaw(b)) keyB = this._toEntryFn!(b)[0];\n else if (this.isEntry(b)) keyB = b[0];\n else if (this.isRealNode(b)) keyB = b.key;\n else {\n keyB = b as K;\n }\n\n if (keyA !== undefined && keyA !== null && keyB !== undefined && keyB !== null) {\n return this._compare(keyA, keyB);\n }\n return 0;\n });\n\n const _dfs = (\n arr: {\n key: R | K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined;\n value: V | undefined;\n orgIndex: number;\n }[]\n ) => {\n if (arr.length === 0) return;\n\n const mid = Math.floor((arr.length - 1) / 2);\n const { key, value } = arr[mid];\n const { orgIndex } = arr[mid];\n if (this.isRaw(key)) {\n const entry = this._toEntryFn!(key);\n inserted[orgIndex] = this.add(entry);\n } else {\n inserted[orgIndex] = this.add(key, value);\n }\n _dfs(arr.slice(0, mid));\n _dfs(arr.slice(mid + 1));\n };\n\n const _iterate = () => {\n const n = sorted.length;\n const stack: [[number, number]] = [[0, n - 1]];\n while (stack.length > 0) {\n const popped = stack.pop();\n if (popped) {\n const [l, r] = popped;\n if (l <= r) {\n const m = l + Math.floor((r - l) / 2);\n const { key, value } = sorted[m];\n const { orgIndex } = sorted[m];\n if (this.isRaw(key)) {\n const entry = this._toEntryFn!(key);\n inserted[orgIndex] = this.add(entry);\n } else {\n inserted[orgIndex] = this.add(key, value);\n }\n stack.push([m + 1, r]);\n stack.push([l, m - 1]);\n }\n }\n }\n };\n\n if (iterationType === 'RECURSIVE') {\n _dfs(sorted);\n } else {\n _iterate();\n }\n\n return inserted;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(k + log n)\n *\n * The function `search` in TypeScript overrides the search behavior in a binary tree structure based\n * on specified criteria.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BSTNode<K, V>>} keyNodeEntryOrPredicate - The\n * `keyNodeEntryOrPredicate` parameter in the `override search` method can accept one of the\n * following types:\n * @param [onlyOne=false] - The `onlyOne` parameter is a boolean flag that determines whether the\n * search should stop after finding the first matching node. If `onlyOne` is set to `true`, the\n * search will return as soon as a matching node is found. If `onlyOne` is set to `false`, the\n * @param {C} callback - The `callback` parameter in the `override search` function is a function\n * that will be called on each node that matches the search criteria. It is of type `C`, which\n * extends `NodeCallback<BSTNode<K, V> | null>`. The callback function should accept a node of type `BSTNode<K, V>` as its\n * argument and\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `override search`\n * method represents the node from which the search operation will begin. It is the starting point\n * for searching within the tree data structure. The method ensures that the `startNode` is a valid\n * node before proceeding with the search operation. If the `\n * @param {IterationType} iterationType - The `iterationType` parameter in the `override search`\n * function determines the type of iteration to be used during the search operation. It can have two\n * possible values:\n * @returns The `override search` method returns an array of values that match the search criteria\n * specified by the input parameters. The method performs a search operation on a binary tree\n * structure based on the provided key, predicate, and other options. The search results are\n * collected in an array and returned as the output of the method.\n */\n override search<C extends NodeCallback<BSTNode<K, V>>>(\n keyNodeEntryOrPredicate:\n | K\n | BSTNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BSTNode<K, V>>\n | Range<K>,\n onlyOne = false,\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C>[] {\n if (keyNodeEntryOrPredicate === undefined) return [];\n if (keyNodeEntryOrPredicate === null) return [];\n startNode = this.ensureNode(startNode);\n if (!startNode) return [];\n let predicate: NodePredicate<BSTNode<K, V>>;\n\n const isRange = this.isRange(keyNodeEntryOrPredicate);\n // Set predicate based on parameter type\n if (isRange) {\n predicate = node => {\n if (!node) return false;\n return keyNodeEntryOrPredicate.isInRange(node.key, this._comparator);\n };\n } else {\n predicate = this._ensurePredicate(keyNodeEntryOrPredicate);\n }\n const shouldVisitLeft = (cur: BSTNode<K, V> | null | undefined) => {\n if (!cur) return false;\n if (!this.isRealNode(cur.left)) return false;\n if (isRange) {\n const range = keyNodeEntryOrPredicate;\n const leftS = this.isReverse ? range.high : range.low;\n const leftI = this.isReverse ? range.includeHigh : range.includeLow;\n return (leftI && this._compare(cur.key, leftS) >= 0) || (!leftI && this._compare(cur.key, leftS) > 0);\n }\n if (!isRange && !this._isPredicate(keyNodeEntryOrPredicate)) {\n const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);\n return benchmarkKey !== null && benchmarkKey !== undefined && this._compare(cur.key, benchmarkKey) > 0;\n }\n return true;\n };\n\n const shouldVisitRight = (cur: BSTNode<K, V> | null | undefined) => {\n if (!cur) return false;\n if (!this.isRealNode(cur.right)) return false;\n if (isRange) {\n const range = keyNodeEntryOrPredicate;\n const rightS = this.isReverse ? range.low : range.high;\n const rightI = this.isReverse ? range.includeLow : range.includeLow;\n\n return (rightI && this._compare(cur.key, rightS) <= 0) || (!rightI && this._compare(cur.key, rightS) < 0);\n }\n if (!isRange && !this._isPredicate(keyNodeEntryOrPredicate)) {\n const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);\n return benchmarkKey !== null && benchmarkKey !== undefined && this._compare(cur.key, benchmarkKey) < 0;\n }\n return true;\n };\n return super._dfs(\n callback,\n 'IN',\n onlyOne,\n startNode,\n iterationType,\n false,\n shouldVisitLeft,\n shouldVisitRight,\n () => true,\n cur => {\n if (cur) return predicate(cur);\n return false;\n }\n );\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(k + log n)\n *\n * The `rangeSearch` function searches for nodes within a specified range in a binary search tree.\n * @param {Range<K> | [K, K]} range - The `range` parameter in the `rangeSearch` function can be\n * either a `Range` object or an array of two elements representing the range boundaries.\n * @param {C} callback - The `callback` parameter in the `rangeSearch` function is a callback\n * function that is used to process each node that is found within the specified range during the\n * search operation. It is of type `NodeCallback<BSTNode<K, V> | null>`, where `BSTNode<K, V>` is the type of nodes in the\n * data structure.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `rangeSearch`\n * function represents the node from which the search for nodes within the specified range will\n * begin. It is the starting point for the range search operation.\n * @param {IterationType} iterationType - The `iterationType` parameter in the `rangeSearch` function\n * is used to specify the type of iteration to be performed during the search operation. It has a\n * default value of `this.iterationType`, which suggests that it is likely a property of the class or\n * object that the `rangeSearch`\n * @returns The `rangeSearch` function is returning the result of calling the `search` method with\n * the specified parameters.\n */\n rangeSearch<C extends NodeCallback<BSTNode<K, V>>>(\n range: Range<K> | [K, K],\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ) {\n const searchRange: Range<K> = range instanceof Range ? range : new Range(range[0], range[1]);\n return this.search(searchRange, false, callback, startNode, iterationType);\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * This function retrieves a node based on a given keyNodeEntryOrPredicate within a binary search tree structure.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BSTNode<K, V>>} keyNodeEntryOrPredicate - The `keyNodeEntryOrPredicate`\n * parameter can be of type `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `, `R`, or `NodePredicate<BSTNode<K, V>>`.\n * @param {BSTNOptKeyOrNode<K, BSTNode<K, V>>} startNode - The `startNode` parameter in the `getNode` method\n * is used to specify the starting point for searching nodes in the binary search tree. If no\n * specific starting point is provided, the default value is set to `this._root`, which is the root\n * node of the binary search tree.\n * @param {IterationType} iterationType - The `iterationType` parameter in the `getNode` method is a\n * parameter that specifies the type of iteration to be used. It has a default value of\n * `this.iterationType`, which means it will use the iteration type defined in the class instance if\n * no value is provided when calling the method.\n * @returns The `getNode` method is returning an optional binary search tree node (`OptNode<BSTNode<K, V>>`).\n * It is using the `getNodes` method to find the node based on the provided keyNodeEntryOrPredicate, beginning at\n * the specified root node (`startNode`) and using the specified iteration type. The method then\n * returns the first node found or `undefined` if no node is found.\n */\n override getNode(\n keyNodeEntryOrPredicate:\n | K\n | BSTNode<K, V>\n | [K | null | undefined, V | undefined]\n | null\n | undefined\n | NodePredicate<BSTNode<K, V>>,\n startNode: BSTNOptKeyOrNode<K, BSTNode<K, V>> = this._root,\n iterationType: IterationType = this.iterationType\n ): OptNode<BSTNode<K, V>> {\n return this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0] ?? undefined;\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The function `dfs` in TypeScript overrides the base class method with default parameters and\n * returns the result of the super class `dfs` method.\n * @param {C} callback - The `callback` parameter is a function that will be called for each node\n * visited during the Depth-First Search traversal. It is a generic type `C` that extends the\n * `NodeCallback` interface for `BSTNode<K, V>`. The default value for `callback` is `this._\n * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `override dfs` method\n * specifies the order in which the Depth-First Search (DFS) traversal should be performed on the\n * Binary Search Tree (BST). The possible values for the `pattern` parameter are:\n * @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `override dfs` method is a\n * boolean flag that indicates whether you want to stop the depth-first search traversal after\n * finding the first matching node or continue searching for all matching nodes. If `onlyOne` is set\n * to `true`, the traversal will stop after finding\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} startNode -\n * The `startNode` parameter in the `override dfs` method can be one of the following types:\n * @param {IterationType} iterationType - The `iterationType` parameter in the `override dfs` method\n * specifies the type of iteration to be performed during the Depth-First Search (DFS) traversal of a\n * Binary Search Tree (BST). It is used to determine the order in which nodes are visited during the\n * traversal. The possible values for `\n * @returns The `override` function is returning the result of calling the `dfs` method from the\n * superclass, with the provided arguments `callback`, `pattern`, `onlyOne`, `startNode`, and\n * `iterationType`. The return type is an array of the return type of the callback function `C`.\n */\n override dfs<C extends NodeCallback<BSTNode<K, V>>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n pattern: DFSOrderPattern = 'IN',\n onlyOne: boolean = false,\n startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C>[] {\n return super.dfs(callback, pattern, onlyOne, startNode, iterationType);\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The function overrides the breadth-first search method and returns an array of the return types of\n * the callback function.\n * @param {C} callback - The `callback` parameter is a function that will be called for each node\n * visited during the breadth-first search. It should take a single argument, which is the current\n * node being visited, and it can return a value of any type.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting\n * point for the breadth-first search. It can be either a root node, a key-value pair, or an entry\n * object. If no value is provided, the default value is the root of the tree.\n * @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type\n * of iteration to be performed during the breadth-first search (BFS) traversal. It can have one of\n * the following values:\n * @returns an array of the return type of the callback function.\n */\n override bfs<C extends NodeCallback<BSTNode<K, V>>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C>[] {\n return super.bfs(callback, startNode, iterationType, false);\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The function overrides the listLevels method from the superclass and returns an array of arrays\n * containing the results of the callback function applied to each level of the tree.\n * @param {C} callback - The `callback` parameter is a generic type `C` that extends\n * `NodeCallback<BSTNode<K, V> | null>`. It represents a callback function that will be called for each node in the\n * tree during the iteration process.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting\n * point for listing the levels of the binary tree. It can be either a root node of the tree, a\n * key-value pair representing a node in the tree, or a key representing a node in the tree. If no\n * value is provided, the root of\n * @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type\n * of iteration to be performed on the tree. It can have one of the following values:\n * @returns The method is returning a two-dimensional array of the return type of the callback\n * function.\n */\n override listLevels<C extends NodeCallback<BSTNode<K, V>>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C>[][] {\n return super.listLevels(callback, startNode, iterationType, false);\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `lesserOrGreaterTraverse` function traverses a binary tree and applies a callback function to\n * each node that meets a certain condition based on a target node and a comparison value.\n * @param {C} callback - The `callback` parameter is a function that will be called for each node\n * that meets the condition specified by the `lesserOrGreater` parameter. It takes a single argument,\n * which is the current node being traversed, and returns a value of any type.\n * @param {CP} lesserOrGreater - The `lesserOrGreater` parameter is used to determine whether to\n * traverse nodes that are lesser, greater, or both than the `targetNode`. It accepts the values -1,\n * 0, or 1, where:\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } targetNode - The `targetNode` parameter is the node in\n * the binary tree that you want to start traversing from. It can be specified either by providing\n * the key of the node, the node itself, or an entry containing the key and value of the node. If no\n * `targetNode` is provided,\n * @param {IterationType} iterationType - The `iterationType` parameter determines the type of\n * traversal to be performed on the binary tree. It can have two possible values:\n * @returns The function `lesserOrGreaterTraverse` returns an array of values of type\n * `ReturnType<C>`, which is the return type of the callback function passed as an argument.\n */\n lesserOrGreaterTraverse<C extends NodeCallback<BSTNode<K, V>>>(\n callback: C = this._DEFAULT_NODE_CALLBACK as C,\n lesserOrGreater: CP = -1,\n targetNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,\n iterationType: IterationType = this.iterationType\n ): ReturnType<C>[] {\n const targetNodeEnsured = this.ensureNode(targetNode);\n const ans: ReturnType<NodeCallback<BSTNode<K, V>>>[] = [];\n if (!this._root) return ans;\n if (!targetNodeEnsured) return ans;\n\n const targetKey = targetNodeEnsured.key;\n\n if (iterationType === 'RECURSIVE') {\n const dfs = (cur: BSTNode<K, V>) => {\n const compared = this._compare(cur.key, targetKey);\n if (Math.sign(compared) === lesserOrGreater) ans.push(callback(cur));\n // TODO here can be optimized to O(log n)\n if (this.isRealNode(cur.left)) dfs(cur.left);\n if (this.isRealNode(cur.right)) dfs(cur.right);\n };\n\n dfs(this._root);\n return ans;\n } else {\n const queue = new Queue<BSTNode<K, V>>([this._root]);\n while (queue.length > 0) {\n const cur = queue.shift();\n if (this.isRealNode(cur)) {\n const compared = this._compare(cur.key, targetKey);\n if (Math.sign(compared) === lesserOrGreater) ans.push(callback(cur));\n\n if (this.isRealNode(cur.left)) queue.push(cur.left);\n if (this.isRealNode(cur.right)) queue.push(cur.right);\n }\n }\n return ans;\n }\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `perfectlyBalance` function takes an optional `iterationType` parameter and returns `true` if\n * the binary search tree is perfectly balanced, otherwise it returns `false`.\n * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that\n * specifies the type of iteration to use when building a balanced binary search tree. It has a\n * default value of `this.iterationType`, which means it will use the iteration type specified in the\n * current instance of the class.\n * @returns The function `perfectlyBalance` returns a boolean value.\n */\n perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {\n const sorted = this.dfs(node => node, 'IN'),\n n = sorted.length;\n this._clearNodes();\n\n if (sorted.length < 1) return false;\n if (iterationType === 'RECURSIVE') {\n const buildBalanceBST = (l: number, r: number) => {\n if (l > r) return;\n const m = l + Math.floor((r - l) / 2);\n const midNode = sorted[m];\n if (this._isMapMode && midNode !== null) this.add(midNode.key);\n else if (midNode !== null) this.add([midNode.key, midNode.value]);\n buildBalanceBST(l, m - 1);\n buildBalanceBST(m + 1, r);\n };\n\n buildBalanceBST(0, n - 1);\n return true;\n } else {\n const stack: [[number, number]] = [[0, n - 1]];\n while (stack.length > 0) {\n const popped = stack.pop();\n if (popped) {\n const [l, r] = popped;\n if (l <= r) {\n const m = l + Math.floor((r - l) / 2);\n const midNode = sorted[m];\n if (this._isMapMode && midNode !== null) this.add(midNode.key);\n else if (midNode !== null) this.add([midNode.key, midNode.value]);\n stack.push([m + 1, r]);\n stack.push([l, m - 1]);\n }\n }\n }\n return true;\n }\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(log n)\n *\n * The function `isAVLBalanced` checks if a binary tree is AVL balanced using either a recursive or\n * iterative approach.\n * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that\n * specifies the type of iteration to use when checking if the AVL tree is balanced. It has a default\n * value of `this.iterationType`, which means it will use the iteration type specified in the current\n * instance of the AVL tree.\n * @returns a boolean value.\n */\n isAVLBalanced(iterationType: IterationType = this.iterationType): boolean {\n if (!this._root) return true;\n\n let balanced = true;\n\n if (iterationType === 'RECURSIVE') {\n const _height = (cur: BSTNode<K, V> | null | undefined): number => {\n if (!cur) return 0;\n const leftHeight = _height(cur.left),\n rightHeight = _height(cur.right);\n if (Math.abs(leftHeight - rightHeight) > 1) balanced = false;\n return Math.max(leftHeight, rightHeight) + 1;\n };\n _height(this._root);\n } else {\n const stack: BSTNode<K, V>[] = [];\n let node: OptNode<BSTNode<K, V>> = this._root,\n last: OptNode<BSTNode<K, V>> = undefined;\n const depths: Map<BSTNode<K, V>, number> = new Map();\n\n while (stack.length > 0 || node) {\n if (node) {\n stack.push(node);\n if (node.left !== null) node = node.left;\n } else {\n node = stack[stack.length - 1];\n if (!node.right || last === node.right) {\n node = stack.pop();\n if (node) {\n const left = node.left ? depths.get(node.left)! : -1;\n const right = node.right ? depths.get(node.right)! : -1;\n if (Math.abs(left - right) > 1) return false;\n depths.set(node, 1 + Math.max(left, right));\n last = node;\n node = undefined;\n }\n } else node = node.right;\n }\n }\n }\n\n return balanced;\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The `map` function in TypeScript overrides the default map behavior for a binary search tree by\n * applying a callback function to each entry and creating a new tree with the results.\n * @param callback - A function that will be called for each entry in the BST. It takes four\n * arguments: the key, the value (which can be undefined), the index of the entry, and a reference to\n * the BST itself.\n * @param [options] - The `options` parameter in the `override map` method is of type `BSTOptions<MK,\n * MV, MR>`. It is an optional parameter that allows you to specify additional options for the Binary\n * Search Tree (BST) being created in the `map` method. These options could include configuration\n * @param {any} [thisArg] - The `thisArg` parameter in the `override map` method is used to specify\n * the value of `this` that should be used when executing the `callback` function. It allows you to\n * set the context or scope in which the callback function will be called. This can be useful when\n * you want\n * @returns The `map` method is returning a new Binary Search Tree (`BST`) instance with the entries\n * transformed by the provided callback function.\n */\n override map(\n callback: EntryCallback<K, V | undefined, [MK, MV]>,\n options?: BSTOptions<MK, MV, MR>,\n thisArg?: any\n ): BST<MK, MV, MR> {\n const newTree = new BST<MK, MV, MR>([], options);\n let index = 0;\n for (const [key, value] of this) {\n newTree.add(callback.call(thisArg, key, value, index++, this));\n }\n return newTree;\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The function `clone` overrides the default cloning behavior to create a deep copy of a tree\n * structure.\n * @returns The `cloned` object is being returned.\n */\n override clone() {\n const cloned = this.createTree();\n this._clone(cloned);\n return cloned;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function overrides a method and converts a key, value pair or entry or raw element to a node.\n * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - A variable that can be of\n * type R or K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined . It represents either a key, a node, an entry, or a raw\n * element.\n * @param {V} [value] - The `value` parameter is an optional value of type `V`. It represents the\n * value associated with a key in a key-value pair.\n * @returns either a BSTNode<K, V> object or undefined.\n */\n protected override _keyValueNodeOrEntryToNodeAndValue(\n keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V\n ): [OptNode<BSTNode<K, V>>, V | undefined] {\n const [node, entryValue] = super._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);\n if (node === null) return [undefined, undefined];\n return [node, value ?? entryValue];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function sets the root of a tree-like structure and updates the parent property of the new\n * root.\n * @param {OptNode<BSTNode<K, V>>} v - v is a parameter of type BSTNode<K, V> or undefined.\n */\n protected override _setRoot(v: OptNode<BSTNode<K, V>>) {\n if (v) {\n v.parent = undefined;\n }\n this._root = v;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The _compare function compares two values using a specified comparator function and optionally\n * reverses the result.\n * @param {K} a - The parameter `a` is of type `K`, which is used as an input for comparison in the\n * `_compare` method.\n * @param {K} b - The parameter `b` in the `_compare` function is of type `K`.\n * @returns The `_compare` method is returning the result of the ternary expression. If `_isReverse`\n * is true, it returns the negation of the result of calling the `_comparator` function with\n * arguments `a` and `b`. If `_isReverse` is false, it returns the result of calling the\n * `_comparator` function with arguments `a` and `b`.\n */\n protected _compare(a: K, b: K) {\n return this._isReverse ? -this._comparator(a, b) : this._comparator(a, b);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport { getMSB } from '../../utils';\n\n/**\n *\n */\nexport class BinaryIndexedTree {\n protected readonly _freq: number;\n protected readonly _max: number;\n\n /**\n * The constructor initializes the properties of an object, including default frequency, maximum\n * value, a freqMap data structure, the most significant bit, and the count of negative frequencies.\n * @param - - `frequency`: The default frequency value. It is optional and has a default\n * value of 0.\n */\n constructor({ frequency = 0, max }: { frequency?: number; max: number }) {\n this._freq = frequency;\n this._max = max;\n this._freqMap = { 0: 0 };\n this._msb = getMSB(max);\n this._negativeCount = frequency < 0 ? max : 0;\n }\n\n protected _freqMap: Record<number, number>;\n\n /**\n * The function returns the frequency map of numbers.\n * @returns The `_freqMap` property, which is a record with number keys and number values, is being\n * returned.\n */\n get freqMap(): Record<number, number> {\n return this._freqMap;\n }\n\n protected _msb: number;\n\n /**\n * The function returns the value of the _msb property.\n * @returns The `_msb` property of the object.\n */\n get msb(): number {\n return this._msb;\n }\n\n protected _negativeCount: number;\n\n /**\n * The function returns the value of the _negativeCount property.\n * @returns The method is returning the value of the variable `_negativeCount`, which is of type\n * `number`.\n */\n get negativeCount(): number {\n return this._negativeCount;\n }\n\n /**\n * The above function returns the value of the protected variable `_freq`.\n * @returns The frequency value stored in the protected variable `_freq`.\n */\n get freq(): number {\n return this._freq;\n }\n\n /**\n * The above function returns the maximum value.\n * @returns The maximum value stored in the variable `_max`.\n */\n get max(): number {\n return this._max;\n }\n\n /**\n * The function \"readSingle\" reads a single number from a specified index.\n * @param {number} index - The `index` parameter is a number that represents the index of an element in a\n * collection or array.\n * @returns a number.\n */\n readSingle(index: number): number {\n this._checkIndex(index);\n return this._readSingle(index);\n }\n\n /**\n * The \"update\" function updates the value at a given index by adding a delta and triggers a callback\n * to notify of the change.\n * @param {number} position - The `index` parameter represents the index of the element that needs to be\n * updated in the data structure.\n * @param {number} change - The \"delta\" parameter represents the change in value that needs to be\n * applied to the frequency at the specified index.\n */\n update(position: number, change: number): void {\n this._checkIndex(position);\n const freqCur = this._readSingle(position);\n\n this._update(position, change);\n this._updateNegativeCount(freqCur, freqCur + change);\n }\n\n /**\n * The function \"writeSingle\" checks the index and writes a single value with a given frequency.\n * @param {number} index - The `index` parameter is a number that represents the index of an element. It\n * is used to identify the specific element that needs to be written.\n * @param {number} freq - The `freq` parameter represents the frequency value that needs to be\n * written.\n */\n writeSingle(index: number, freq: number): void {\n this._checkIndex(index);\n this._writeSingle(index, freq);\n }\n\n /**\n * The read function takes a count parameter, checks if it is an integer, and returns the result of\n * calling the _read function with the count parameter clamped between 0 and the maximum value.\n * @param {number} count - The `count` parameter is a number that represents the number of items to\n * read.\n * @returns a number.\n */\n read(count: number): number {\n if (!Number.isInteger(count)) {\n throw new Error('Invalid count');\n }\n return this._read(Math.max(Math.min(count, this.max), 0));\n }\n\n /**\n * The function returns the lower bound of a non-descending sequence that sums up to a given number.\n * @param {number} sum - The `sum` parameter is a number that represents the target sum that we want\n * to find in the sequence.\n * @returns The lowerBound function is returning a number.\n */\n lowerBound(sum: number): number {\n if (this.negativeCount > 0) {\n throw new Error('Sequence is not non-descending');\n }\n return this._binarySearch(sum, (x, y) => x < y);\n }\n\n /**\n * The upperBound function returns the index of the first element in a sequence that is greater than\n * or equal to a given sum.\n * @param {number} sum - The \"sum\" parameter is a number that represents the target sum that we want\n * to find in the sequence.\n * @returns The upperBound function is returning a number.\n */\n upperBound(sum: number): number {\n if (this.negativeCount > 0) {\n throw new Error('Must not be descending');\n }\n return this._binarySearch(sum, (x, y) => x <= y);\n }\n\n /**\n * The function calculates the prefix sum of an array using a binary indexed tree.\n * @param {number} i - The parameter \"i\" in the function \"getPrefixSum\" represents the index of the element in the\n * array for which we want to calculate the prefix sum.\n * @returns The function `getPrefixSum` returns the prefix sum of the elements in the binary indexed tree up to index\n * `i`.\n */\n getPrefixSum(i: number): number {\n this._checkIndex(i);\n i++; // Convert to 1-based index\n\n let sum = 0;\n while (i > 0) {\n sum += this._getFrequency(i);\n i -= i & -i;\n }\n\n return sum;\n }\n\n /**\n * The function returns the value of a specific index in a freqMap data structure, or a default value if\n * the index is not found.\n * @param {number} index - The `index` parameter is a number that represents the index of a node in a\n * freqMap data structure.\n * @returns a number.\n */\n protected _getFrequency(index: number): number {\n if (index in this.freqMap) {\n return this.freqMap[index];\n }\n\n return this.freq * (index & -index);\n }\n\n /**\n * The function _updateFrequency adds a delta value to the element at the specified index in the freqMap array.\n * @param {number} index - The index parameter is a number that represents the index of the freqMap\n * element that needs to be updated.\n * @param {number} delta - The `delta` parameter represents the change in value that needs to be\n * added to the freqMap at the specified `index`.\n */\n protected _updateFrequency(index: number, delta: number): void {\n this.freqMap[index] = this._getFrequency(index) + delta;\n }\n\n /**\n * The function checks if the given index is valid and within the range.\n * @param {number} index - The parameter \"index\" is of type number and represents the index value\n * that needs to be checked.\n */\n protected _checkIndex(index: number): void {\n if (!Number.isInteger(index)) {\n throw new Error('Invalid index: Index must be an integer.');\n }\n if (index < 0 || index >= this.max) {\n throw new Error('Index out of range: Index must be within the range [0, this.max).');\n }\n }\n\n /**\n * The function calculates the sum of elements in an array up to a given index using a binary indexed\n * freqMap.\n * @param {number} index - The `index` parameter is a number that represents the index of an element in a\n * data structure.\n * @returns a number.\n */\n protected _readSingle(index: number): number {\n index = index + 1;\n let sum = this._getFrequency(index);\n const z = index - (index & -index);\n\n index--;\n\n while (index !== z) {\n sum -= this._getFrequency(index);\n index -= index & -index;\n }\n\n return sum;\n }\n\n /**\n * The function `_updateNegativeCount` updates a counter based on changes in frequency values.\n * @param {number} freqCur - The current frequency value.\n * @param {number} freqNew - The freqNew parameter represents the new frequency value.\n */\n protected _updateNegativeCount(freqCur: number, freqNew: number): void {\n if (freqCur < 0 && freqNew >= 0) {\n this._negativeCount--;\n } else if (freqCur >= 0 && freqNew < 0) {\n this._negativeCount++;\n }\n }\n\n /**\n * The `_update` function updates the values in a binary indexed freqMap starting from a given index and\n * propagating the changes to its parent nodes.\n * @param {number} index - The `index` parameter is a number that represents the index of the element in\n * the data structure that needs to be updated.\n * @param {number} delta - The `delta` parameter represents the change in value that needs to be\n * applied to the elements in the data structure.\n */\n protected _update(index: number, delta: number): void {\n index = index + 1;\n\n while (index <= this.max) {\n this._updateFrequency(index, delta);\n index += index & -index;\n }\n }\n\n /**\n * The `_writeSingle` function updates the frequency at a specific index and triggers a callback if\n * the frequency has changed.\n * @param {number} index - The `index` parameter is a number that represents the index of the element\n * being modified or accessed.\n * @param {number} freq - The `freq` parameter represents the new frequency value that needs to be\n * written to the specified index `index`.\n */\n protected _writeSingle(index: number, freq: number): void {\n const freqCur = this._readSingle(index);\n\n this._update(index, freq - freqCur);\n this._updateNegativeCount(freqCur, freq);\n }\n\n /**\n * The `_read` function calculates the sum of values in a binary freqMap up to a given count.\n * @param {number} count - The `count` parameter is a number that represents the number of elements\n * to read from the freqMap.\n * @returns the sum of the values obtained from calling the `_getFrequency` method for each index in the\n * range from `count` to 1.\n */\n protected _read(count: number): number {\n let index = count;\n let sum = 0;\n while (index) {\n sum += this._getFrequency(index);\n index -= index & -index;\n }\n\n return sum;\n }\n\n /**\n * The function `_binarySearch` performs a binary search to find the largest number that satisfies a given\n * condition.\n * @param {number} sum - The sum parameter is a number that represents the target sum value.\n * @param before - The `before` parameter is a function that takes two numbers `x` and `y` as\n * arguments and returns a boolean value. It is used to determine if `x` is less than or equal to\n * `y`. The purpose of this function is to compare two numbers and determine their order.\n * @returns the value of the variable \"left\".\n */\n protected _binarySearch(sum: number, before: (x: number, y: number) => boolean): number {\n let left = 0;\n let right = this.msb << 1;\n let sumT = sum;\n\n while (right > left + 1) {\n const middle = (left + right) >> 1;\n const sumM = this._getFrequency(middle);\n\n if (middle <= this.max && before(sumM, sumT)) {\n sumT -= sumM;\n left = middle;\n } else {\n right = middle;\n }\n }\n return left;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n\nimport type { SegmentTreeNodeVal } from '../../types';\n\nexport class SegmentTreeNode {\n /**\n * The constructor initializes the properties of a SegmentTreeNode object.\n * @param {number} start - The `start` parameter represents the starting index of the segment covered\n * by this node in a segment tree.\n * @param {number} end - The `end` parameter represents the end index of the segment covered by this\n * node in a segment tree.\n * @param {number} sum - The `sum` parameter represents the sum of the values in the range covered by\n * the segment tree node.\n * @param {SegmentTreeNodeVal | undefined} [value] - The `value` parameter is an optional parameter\n * of type `SegmentTreeNodeVal`. It represents the value associated with the segment tree node.\n */\n constructor(start: number, end: number, sum: number, value?: SegmentTreeNodeVal | undefined) {\n this._start = start;\n this._end = end;\n this._sum = sum;\n this._value = value || undefined;\n }\n\n protected _start = 0;\n\n /**\n * The function returns the value of the protected variable _start.\n * @returns The start value, which is of type number.\n */\n get start(): number {\n return this._start;\n }\n\n /**\n * The above function sets the value of the \"start\" property.\n * @param {number} value - The value parameter is of type number.\n */\n set start(value: number) {\n this._start = value;\n }\n\n protected _end = 0;\n\n /**\n * The function returns the value of the protected variable `_end`.\n * @returns The value of the protected property `_end`.\n */\n get end(): number {\n return this._end;\n }\n\n /**\n * The above function sets the value of the \"end\" property.\n * @param {number} value - The value parameter is a number that represents the new value for the end\n * property.\n */\n set end(value: number) {\n this._end = value;\n }\n\n protected _value: SegmentTreeNodeVal | undefined = undefined;\n\n /**\n * The function returns the value of a segment tree node.\n * @returns The value being returned is either a `SegmentTreeNodeVal` object or `undefined`.\n */\n get value(): SegmentTreeNodeVal | undefined {\n return this._value;\n }\n\n /**\n * The function sets the value of a segment tree node.\n * @param {SegmentTreeNodeVal | undefined} value - The `value` parameter is of type\n * `SegmentTreeNodeVal` or `undefined`.\n */\n set value(value: SegmentTreeNodeVal | undefined) {\n this._value = value;\n }\n\n protected _sum = 0;\n\n /**\n * The function returns the value of the sum property.\n * @returns The method is returning the value of the variable `_sum`.\n */\n get sum(): number {\n return this._sum;\n }\n\n /**\n * The above function sets the value of the sum property.\n * @param {number} value - The parameter \"value\" is of type \"number\".\n */\n set sum(value: number) {\n this._sum = value;\n }\n\n protected _left: SegmentTreeNode | undefined = undefined;\n\n /**\n * The function returns the left child of a segment tree node.\n * @returns The `left` property of the `SegmentTreeNode` object is being returned. It is of type\n * `SegmentTreeNode` or `undefined`.\n */\n get left(): SegmentTreeNode | undefined {\n return this._left;\n }\n\n /**\n * The function sets the value of the left property of a SegmentTreeNode object.\n * @param {SegmentTreeNode | undefined} value - The value parameter is of type SegmentTreeNode or\n * undefined.\n */\n set left(value: SegmentTreeNode | undefined) {\n this._left = value;\n }\n\n protected _right: SegmentTreeNode | undefined = undefined;\n\n /**\n * The function returns the right child of a segment tree node.\n * @returns The `getRight()` method is returning a value of type `SegmentTreeNode` or `undefined`.\n */\n get right(): SegmentTreeNode | undefined {\n return this._right;\n }\n\n /**\n * The function sets the right child of a segment tree node.\n * @param {SegmentTreeNode | undefined} value - The `value` parameter is of type `SegmentTreeNode |\n * undefined`. This means that it can accept either a `SegmentTreeNode` object or `undefined` as its\n * value.\n */\n set right(value: SegmentTreeNode | undefined) {\n this._right = value;\n }\n}\n\nexport class SegmentTree {\n /**\n * The constructor initializes the values, start, end, and root properties of an object.\n * @param {number[]} values - An array of numbers that will be used to build a binary search tree.\n * @param {number} [start] - The `start` parameter is the index of the first element in the `values` array that should\n * be included in the range. If no value is provided for `start`, it defaults to 0, which means the range starts from\n * the beginning of the array.\n * @param {number} [end] - The \"end\" parameter is the index of the last element in the \"values\" array that should be\n * included in the range. If not provided, it defaults to the index of the last element in the \"values\" array.\n */\n constructor(values: number[], start?: number, end?: number) {\n start = start || 0;\n end = end || values.length - 1;\n this._values = values;\n this._start = start;\n this._end = end;\n\n if (values.length > 0) {\n this._root = this.build(start, end);\n } else {\n this._root = undefined;\n this._values = [];\n }\n }\n\n protected _values: number[] = [];\n\n /**\n * The function returns an array of numbers.\n * @returns An array of numbers is being returned.\n */\n get values(): number[] {\n return this._values;\n }\n\n protected _start = 0;\n\n /**\n * The function returns the value of the protected variable _start.\n * @returns The start value, which is of type number.\n */\n get start(): number {\n return this._start;\n }\n\n protected _end: number;\n\n /**\n * The function returns the value of the protected variable `_end`.\n * @returns The value of the protected property `_end`.\n */\n get end(): number {\n return this._end;\n }\n\n protected _root: SegmentTreeNode | undefined;\n\n /**\n * The function returns the root node of a segment tree.\n * @returns The `root` property of the class `SegmentTreeNode` or `undefined` if it is not defined.\n */\n get root(): SegmentTreeNode | undefined {\n return this._root;\n }\n\n /**\n * The build function creates a segment tree by recursively dividing the given range into smaller segments and assigning\n * the sum of values to each segment.\n * @param {number} start - The `start` parameter represents the starting index of the segment or range for which we are\n * building the segment tree.\n * @param {number} end - The \"end\" parameter represents the ending index of the segment or range for which we want to\n * build a segment tree.\n * @returns a SegmentTreeNode object.\n */\n build(start: number, end: number): SegmentTreeNode {\n if (start > end) {\n return new SegmentTreeNode(start, end, 0);\n }\n if (start === end) return new SegmentTreeNode(start, end, this._values[start]);\n\n const mid = start + Math.floor((end - start) / 2);\n const left = this.build(start, mid);\n const right = this.build(mid + 1, end);\n const cur = new SegmentTreeNode(start, end, left.sum + right.sum);\n cur.left = left;\n cur.right = right;\n return cur;\n }\n\n /**\n * The function updates the value of a node in a segment tree and recalculates the sum of its children if they exist.\n * @param {number} index - The index parameter represents the index of the node in the segment tree that needs to be\n * updated.\n * @param {number} sum - The `sum` parameter represents the new value that should be assigned to the `sum` property of\n * the `SegmentTreeNode` at the specified `index`.\n * @param {SegmentTreeNodeVal} [value] - The `value` parameter is an optional value that can be assigned to the `value`\n * property of the `SegmentTreeNode` object. It is not currently used in the code, but you can uncomment the line `//\n * cur.value = value;` and pass a value for `value` in the\n * @returns The function does not return anything.\n */\n updateNode(index: number, sum: number, value?: SegmentTreeNodeVal) {\n const root = this.root || undefined;\n if (!root) {\n return;\n }\n const dfs = (cur: SegmentTreeNode, index: number, sum: number, value?: SegmentTreeNodeVal) => {\n if (cur.start === cur.end && cur.start === index) {\n cur.sum = sum;\n if (value !== undefined) cur.value = value;\n return;\n }\n const mid = cur.start + Math.floor((cur.end - cur.start) / 2);\n if (index <= mid) {\n if (cur.left) {\n dfs(cur.left, index, sum, value);\n }\n } else {\n if (cur.right) {\n dfs(cur.right, index, sum, value);\n }\n }\n if (cur.left && cur.right) {\n cur.sum = cur.left.sum + cur.right.sum;\n }\n };\n\n dfs(root, index, sum, value);\n }\n\n /**\n * The function `querySumByRange` calculates the sum of values within a given range in a segment tree.\n * @param {number} indexA - The starting index of the range for which you want to calculate the sum.\n * @param {number} indexB - The parameter `indexB` represents the ending index of the range for which you want to\n * calculate the sum.\n * @returns The function `querySumByRange` returns a number.\n */\n querySumByRange(indexA: number, indexB: number): number {\n const root = this.root || undefined;\n if (!root) {\n return 0;\n }\n\n if (indexA < 0 || indexB >= this.values.length || indexA > indexB) {\n return NaN;\n }\n\n const dfs = (cur: SegmentTreeNode, i: number, j: number): number => {\n if (i <= cur.start && j >= cur.end) {\n // The range [i, j] completely covers the current node's range [cur.start, cur.end]\n return cur.sum;\n }\n const mid = cur.start + Math.floor((cur.end - cur.start) / 2);\n if (j <= mid) {\n if (cur.left) {\n return dfs(cur.left, i, j);\n } else {\n return NaN;\n }\n } else if (i > mid) {\n if (cur.right) {\n return dfs(cur.right, i, j);\n } else {\n return NaN;\n }\n } else {\n // Query both left and right subtrees\n let leftSum = 0;\n let rightSum = 0;\n if (cur.left) {\n leftSum = dfs(cur.left, i, mid);\n }\n if (cur.right) {\n rightSum = dfs(cur.right, mid + 1, j);\n }\n return leftSum + rightSum;\n }\n };\n return dfs(root, indexA, indexB);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport { BST, BSTNode } from './bst';\nimport type { AVLTreeOptions, BinaryTreeDeleteResult, BSTNOptKeyOrNode, EntryCallback } from '../../types';\nimport { IBinaryTree } from '../../interfaces';\n\nexport class AVLTreeNode<K = any, V = any> extends BSTNode<K, V> {\n override parent?: AVLTreeNode<K, V> = undefined;\n\n /**\n * This TypeScript constructor function initializes an instance with a key and an optional value.\n * @param {K} key - The `key` parameter is typically used to uniquely identify an object or element\n * within a data structure. It serves as a reference or identifier for accessing or manipulating the\n * associated value or data.\n * @param {V} [value] - The `value` parameter in the constructor is optional, meaning it does not\n * have to be provided when creating an instance of the class. If a value is not provided, it will\n * default to `undefined`.\n */\n constructor(key: K, value?: V) {\n super(key, value);\n }\n\n override _left?: AVLTreeNode<K, V> | null | undefined = undefined;\n\n override get left(): AVLTreeNode<K, V> | null | undefined {\n return this._left;\n }\n\n override set left(v: AVLTreeNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._left = v;\n }\n\n override _right?: AVLTreeNode<K, V> | null | undefined = undefined;\n\n override get right(): AVLTreeNode<K, V> | null | undefined {\n return this._right;\n }\n\n override set right(v: AVLTreeNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n}\n\n/**\n * 1. Height-Balanced: Each node's left and right subtrees differ in height by no more than one.\n * 2. Automatic Rebalancing: AVL trees rebalance themselves automatically during insertions and deletions.\n * 3. Rotations for Balancing: Utilizes rotations (single or double) to maintain balance after updates.\n * 4. Order Preservation: Maintains the binary search tree property where left child values are less than the parent, and right child values are greater.\n * 5. Efficient Lookups: Offers O(log n) search time, where 'n' is the number of nodes, due to its balanced nature.\n * 6. Complex Insertions and Deletions: Due to rebalancing, these operations are more complex than in a regular BST.\n * 7. Path Length: The path length from the root to any leaf is longer compared to an unbalanced BST, but shorter than a linear chain of nodes.\n * @example\n * // Find elements in a range\n * // In interval queries, AVL trees, with their strictly balanced structure and lower height, offer better query efficiency, making them ideal for frequent and high-performance interval queries. In contrast, Red-Black trees, with lower update costs, are more suitable for scenarios involving frequent insertions and deletions where the requirements for interval queries are less demanding.\n * type Datum = { timestamp: Date; temperature: number };\n * // Fixed dataset of CPU temperature readings\n * const cpuData: Datum[] = [\n * { timestamp: new Date('2024-12-02T00:00:00'), temperature: 55.1 },\n * { timestamp: new Date('2024-12-02T00:01:00'), temperature: 56.3 },\n * { timestamp: new Date('2024-12-02T00:02:00'), temperature: 54.8 },\n * { timestamp: new Date('2024-12-02T00:03:00'), temperature: 57.2 },\n * { timestamp: new Date('2024-12-02T00:04:00'), temperature: 58.0 },\n * { timestamp: new Date('2024-12-02T00:05:00'), temperature: 59.4 },\n * { timestamp: new Date('2024-12-02T00:06:00'), temperature: 60.1 },\n * { timestamp: new Date('2024-12-02T00:07:00'), temperature: 61.3 },\n * { timestamp: new Date('2024-12-02T00:08:00'), temperature: 62.0 },\n * { timestamp: new Date('2024-12-02T00:09:00'), temperature: 63.5 },\n * { timestamp: new Date('2024-12-02T00:10:00'), temperature: 64.0 },\n * { timestamp: new Date('2024-12-02T00:11:00'), temperature: 62.8 },\n * { timestamp: new Date('2024-12-02T00:12:00'), temperature: 61.5 },\n * { timestamp: new Date('2024-12-02T00:13:00'), temperature: 60.2 },\n * { timestamp: new Date('2024-12-02T00:14:00'), temperature: 59.8 },\n * { timestamp: new Date('2024-12-02T00:15:00'), temperature: 58.6 },\n * { timestamp: new Date('2024-12-02T00:16:00'), temperature: 57.4 },\n * { timestamp: new Date('2024-12-02T00:17:00'), temperature: 56.2 },\n * { timestamp: new Date('2024-12-02T00:18:00'), temperature: 55.7 },\n * { timestamp: new Date('2024-12-02T00:19:00'), temperature: 54.5 },\n * { timestamp: new Date('2024-12-02T00:20:00'), temperature: 53.2 },\n * { timestamp: new Date('2024-12-02T00:21:00'), temperature: 52.8 },\n * { timestamp: new Date('2024-12-02T00:22:00'), temperature: 51.9 },\n * { timestamp: new Date('2024-12-02T00:23:00'), temperature: 50.5 },\n * { timestamp: new Date('2024-12-02T00:24:00'), temperature: 49.8 },\n * { timestamp: new Date('2024-12-02T00:25:00'), temperature: 48.7 },\n * { timestamp: new Date('2024-12-02T00:26:00'), temperature: 47.5 },\n * { timestamp: new Date('2024-12-02T00:27:00'), temperature: 46.3 },\n * { timestamp: new Date('2024-12-02T00:28:00'), temperature: 45.9 },\n * { timestamp: new Date('2024-12-02T00:29:00'), temperature: 45.0 }\n * ];\n *\n * // Create an AVL tree to store CPU temperature data\n * const cpuTemperatureTree = new AVLTree<Date, number, Datum>(cpuData, {\n * toEntryFn: ({ timestamp, temperature }) => [timestamp, temperature]\n * });\n *\n * // Query a specific time range (e.g., from 00:05 to 00:15)\n * const rangeStart = new Date('2024-12-02T00:05:00');\n * const rangeEnd = new Date('2024-12-02T00:15:00');\n * const rangeResults = cpuTemperatureTree.rangeSearch([rangeStart, rangeEnd], node => ({\n * minute: node ? node.key.getMinutes() : 0,\n * temperature: cpuTemperatureTree.get(node ? node.key : undefined)\n * }));\n *\n * console.log(rangeResults); // [\n * // { minute: 5, temperature: 59.4 },\n * // { minute: 6, temperature: 60.1 },\n * // { minute: 7, temperature: 61.3 },\n * // { minute: 8, temperature: 62 },\n * // { minute: 9, temperature: 63.5 },\n * // { minute: 10, temperature: 64 },\n * // { minute: 11, temperature: 62.8 },\n * // { minute: 12, temperature: 61.5 },\n * // { minute: 13, temperature: 60.2 },\n * // { minute: 14, temperature: 59.8 },\n * // { minute: 15, temperature: 58.6 }\n * // ]\n */\nexport class AVLTree<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends BST<K, V, R, MK, MV, MR>\n implements IBinaryTree<K, V, R, MK, MV, MR>\n{\n /**\n * This TypeScript constructor initializes an AVLTree with keys, nodes, entries, or raw data provided\n * in an iterable format.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an\n * iterable that can contain either `\n K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` objects or `R` objects. It is\n * used to initialize the AVLTree with key-value pairs or raw data entries. If provided\n * @param [options] - The `options` parameter in the constructor is of type `AVLTreeOptions<K, V,\n * R>`. It is an optional parameter that allows you to specify additional options for configuring the\n * AVL tree. These options could include things like custom comparators, initial capacity, or any\n * other configuration settings specific\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n > = [],\n options?: AVLTreeOptions<K, V, R>\n ) {\n super([], options);\n if (keysNodesEntriesOrRaws) super.addMany(keysNodesEntriesOrRaws);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a new AVL tree node with the given key and value.\n * @param {K} key - The key parameter is of type K, which represents the key of the node being\n * created.\n * @param {V} [value] - The \"value\" parameter is an optional parameter of type V. It represents the\n * value associated with the key in the node being created.\n * @returns The method is returning a new instance of the AVLTreeNode class, casted as the generic\n * type AVLTreeNode<K, V>.\n */\n override createNode(key: K, value?: V): AVLTreeNode<K, V> {\n return new AVLTreeNode<K, V>(key, this._isMapMode ? undefined : value) as AVLTreeNode<K, V>;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a new AVL tree with the specified options and returns it.\n * @param {AVLTreeOptions} [options] - The `options` parameter is an optional object that can be\n * passed to the `createTree` function. It is used to customize the behavior of the AVL tree that is\n * being created.\n * @returns a new AVLTree object.\n */\n override createTree(options?: AVLTreeOptions<K, V, R>) {\n return new AVLTree<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n isMapMode: this._isMapMode,\n specifyComparable: this._specifyComparable,\n toEntryFn: this._toEntryFn,\n isReverse: this._isReverse,\n ...options\n });\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if the input is an instance of AVLTreeNode.\n * @param {K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be of type `R` or `\n K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.\n * @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is\n * an instance of the `AVLTreeNode` class.\n */\n override isNode(\n keyNodeOrEntry: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is AVLTreeNode<K, V> {\n return keyNodeOrEntry instanceof AVLTreeNode;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function overrides the add method of a class and inserts a key-value pair into a data\n * structure, then balances the path.\n * @param { K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can accept values of type `R`, `\n K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `\n * @param {V} [value] - The `value` parameter is an optional value that you want to associate with\n * the key or node being added to the data structure.\n * @returns The method is returning a boolean value.\n */\n override add(\n keyNodeOrEntry: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V\n ): boolean {\n if (keyNodeOrEntry === null) return false;\n const inserted = super.add(keyNodeOrEntry, value);\n if (inserted) this._balancePath(keyNodeOrEntry);\n return inserted;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function overrides the delete method in a TypeScript class, performs deletion, and then\n * balances the tree if necessary.\n * @param { K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`\n * parameter in the `override delete` method can be one of the following types:\n * @returns The `delete` method is being overridden in this code snippet. It first calls the `delete`\n * method from the superclass (presumably a parent class) with the provided `predicate`, which could\n * be a key, node, entry, or a custom predicate. The result of this deletion operation is stored in\n * `deletedResults`, which is an array of `BinaryTreeDeleteResult` objects.\n */\n override delete(\n keyNodeOrEntry: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): BinaryTreeDeleteResult<AVLTreeNode<K, V>>[] {\n const deletedResults = super.delete(keyNodeOrEntry);\n for (const { needBalanced } of deletedResults) {\n if (needBalanced) {\n this._balancePath(needBalanced);\n }\n }\n return deletedResults;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function in TypeScript overrides the default map behavior of an AVLTree data structure\n * by applying a callback function to each entry and creating a new AVLTree with the results.\n * @param callback - A function that will be called for each entry in the AVLTree. It takes four\n * arguments: the key, the value (which can be undefined), the index of the entry, and a reference to\n * the AVLTree itself.\n * @param [options] - The `options` parameter in the `override map` function is of type\n * `AVLTreeOptions<MK, MV, MR>`. It is an optional parameter that allows you to specify additional\n * options for the AVL tree being created during the mapping process. These options could include\n * custom comparators, initial\n * @param {any} [thisArg] - The `thisArg` parameter in the `override map` function is used to specify\n * the value of `this` when executing the `callback` function. It allows you to set the context\n * (value of `this`) within the callback function. This can be useful when you want to access\n * properties or\n * @returns The `map` method is returning a new AVLTree instance (`newTree`) with the entries\n * modified by the provided callback function.\n */\n override map(\n callback: EntryCallback<K, V | undefined, [MK, MV]>,\n options?: AVLTreeOptions<MK, MV, MR>,\n thisArg?: any\n ): AVLTree<MK, MV, MR> {\n const newTree = new AVLTree<MK, MV, MR>([], options);\n let index = 0;\n for (const [key, value] of this) {\n newTree.add(callback.call(thisArg, key, value, index++, this));\n }\n return newTree;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `clone` overrides the default cloning behavior to create a deep copy of a tree\n * structure.\n * @returns A cloned tree object is being returned.\n */\n override clone() {\n const cloned = this.createTree();\n this._clone(cloned);\n return cloned;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_swapProperties` function swaps the key, value, and height properties between two nodes in a\n * binary search tree.\n * @param {BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>} srcNode - The `srcNode` parameter represents either a node\n * object (`AVLTreeNode<K, V>`) or a key-value pair (`R`) that is being swapped with another node.\n * @param {BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>} destNode - The `destNode` parameter is either an instance of\n * `R` or an instance of `BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>`.\n * @returns The method is returning the `destNodeEnsured` object if both `srcNodeEnsured` and\n * `destNodeEnsured` are truthy. Otherwise, it returns `undefined`.\n */\n protected override _swapProperties(\n srcNode: BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>,\n destNode: BSTNOptKeyOrNode<K, AVLTreeNode<K, V>>\n ): AVLTreeNode<K, V> | undefined {\n const srcNodeEnsured = this.ensureNode(srcNode);\n const destNodeEnsured = this.ensureNode(destNode);\n\n if (srcNodeEnsured && destNodeEnsured) {\n const { key, value, height } = destNodeEnsured;\n const tempNode = this.createNode(key, value);\n\n if (tempNode) {\n tempNode.height = height;\n\n destNodeEnsured.key = srcNodeEnsured.key;\n if (!this._isMapMode) destNodeEnsured.value = srcNodeEnsured.value;\n destNodeEnsured.height = srcNodeEnsured.height;\n\n srcNodeEnsured.key = tempNode.key;\n if (!this._isMapMode) srcNodeEnsured.value = tempNode.value;\n srcNodeEnsured.height = tempNode.height;\n }\n\n return destNodeEnsured;\n }\n return undefined;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function calculates the balance factor of a node in a binary tree.\n * @param {AVLTreeNode<K, V>} node - The parameter \"node\" is of type \"AVLTreeNode<K, V>\", which likely represents a node in a\n * binary tree data structure.\n * @returns the balance factor of a given node. The balance factor is calculated by subtracting the\n * height of the left subtree from the height of the right subtree.\n */\n protected _balanceFactor(node: AVLTreeNode<K, V>): number {\n if (!node.right)\n // node has no right subtree\n return -node.height;\n else if (!node.left)\n // node has no left subtree\n return +node.height;\n else return node.right.height - node.left.height;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function updates the height of a node in a binary tree based on the heights of its left and\n * right children.\n * @param {AVLTreeNode<K, V>} node - The parameter \"node\" represents a node in a binary tree data structure.\n */\n protected _updateHeight(node: AVLTreeNode<K, V>): void {\n if (!node.left && !node.right) node.height = 0;\n else if (!node.left) {\n const rightHeight = node.right ? node.right.height : 0;\n node.height = 1 + rightHeight;\n } else if (!node.right) node.height = 1 + node.left.height;\n else node.height = 1 + Math.max(node.right.height, node.left.height);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_balanceLL` function performs a left-left rotation to balance a binary search tree.\n * @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.\n */\n protected _balanceLL(A: AVLTreeNode<K, V>): void {\n const parentOfA = A.parent;\n const B = A.left;\n if (B !== null) A.parent = B;\n if (B && B.right) {\n B.right.parent = A;\n }\n if (B) B.parent = parentOfA;\n if (A === this.root) {\n if (B) this._setRoot(B);\n } else {\n if (parentOfA?.left === A) {\n parentOfA.left = B;\n } else {\n if (parentOfA) parentOfA.right = B;\n }\n }\n\n if (B) {\n A.left = B.right;\n B.right = A;\n }\n this._updateHeight(A);\n if (B) this._updateHeight(B);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_balanceLR` function performs a left-right rotation to balance a binary tree.\n * @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.\n */\n protected _balanceLR(A: AVLTreeNode<K, V>): void {\n const parentOfA = A.parent;\n const B = A.left;\n let C = undefined;\n if (B) {\n C = B.right;\n }\n if (A && C !== null) A.parent = C;\n if (B && C !== null) B.parent = C;\n\n if (C) {\n if (C.left) {\n if (B !== null) C.left.parent = B;\n }\n if (C.right) {\n C.right.parent = A;\n }\n C.parent = parentOfA;\n }\n\n if (A === this.root) {\n if (C) this._setRoot(C);\n } else {\n if (parentOfA) {\n if (parentOfA.left === A) {\n parentOfA.left = C;\n } else {\n parentOfA.right = C;\n }\n }\n }\n\n if (C) {\n A.left = C.right;\n if (B) B.right = C.left;\n C.left = B;\n C.right = A;\n }\n\n this._updateHeight(A);\n if (B) this._updateHeight(B);\n if (C) this._updateHeight(C);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_balanceRR` performs a right-right rotation to balance a binary tree.\n * @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.\n */\n protected _balanceRR(A: AVLTreeNode<K, V>): void {\n const parentOfA = A.parent;\n const B = A.right;\n if (B !== null) A.parent = B;\n if (B) {\n if (B.left) {\n B.left.parent = A;\n }\n B.parent = parentOfA;\n }\n\n if (A === this.root) {\n if (B) this._setRoot(B);\n } else {\n if (parentOfA) {\n if (parentOfA.left === A) {\n parentOfA.left = B;\n } else {\n parentOfA.right = B;\n }\n }\n }\n\n if (B) {\n A.right = B.left;\n B.left = A;\n }\n this._updateHeight(A);\n if (B) this._updateHeight(B);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_balanceRL` performs a right-left rotation to balance a binary tree.\n * @param {AVLTreeNode<K, V>} A - A is a node in a binary tree.\n */\n protected _balanceRL(A: AVLTreeNode<K, V>): void {\n const parentOfA = A.parent;\n const B = A.right;\n let C = undefined;\n if (B) {\n C = B.left;\n }\n\n if (C !== null) A.parent = C;\n if (B && C !== null) B.parent = C;\n\n if (C) {\n if (C.left) {\n C.left.parent = A;\n }\n if (C.right) {\n if (B !== null) C.right.parent = B;\n }\n C.parent = parentOfA;\n }\n\n if (A === this.root) {\n if (C) this._setRoot(C);\n } else {\n if (parentOfA) {\n if (parentOfA.left === A) {\n parentOfA.left = C;\n } else {\n parentOfA.right = C;\n }\n }\n }\n\n if (C) A.right = C.left;\n if (B && C) B.left = C.right;\n if (C) C.left = A;\n if (C) C.right = B;\n\n this._updateHeight(A);\n if (B) this._updateHeight(B);\n if (C) this._updateHeight(C);\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The `_balancePath` function is used to update the heights of nodes and perform rotation operations\n * to restore balance in an AVL tree after inserting a node.\n * @param { K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } node - The `node` parameter can be of type `R` or\n * `\n K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.\n */\n protected _balancePath(node: K | AVLTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined): void {\n node = this.ensureNode(node);\n const path = this.getPathToRoot(node, node => node, false); // first O(log n) + O(log n)\n for (let i = 0; i < path.length; i++) {\n // second O(log n)\n const A = path[i];\n if (A) {\n // Update Heights: After inserting a node, backtrack from the insertion point to the root node, updating the height of each node along the way.\n this._updateHeight(A); // first O(1)\n // Check Balance: Simultaneously with height updates, check if each node violates the balance property of an AVL tree.\n // Balance Restoration: If a balance issue is discovered after inserting a node, it requires balance restoration operations. Balance restoration includes four basic cases where rotation operations need to be performed to fix the balance:\n switch (\n this._balanceFactor(A) // second O(1)\n ) {\n case -2:\n if (A && A.left) {\n if (this._balanceFactor(A.left) <= 0) {\n // second O(1)\n // Left Rotation (LL Rotation): When the inserted node is in the left subtree of the left subtree, causing an imbalance.\n this._balanceLL(A);\n } else {\n // Left-Right Rotation (LR Rotation): When the inserted node is in the right subtree of the left subtree, causing an imbalance.\n this._balanceLR(A);\n }\n }\n break;\n case +2:\n if (A && A.right) {\n if (this._balanceFactor(A.right) >= 0) {\n // Right Rotation (RR Rotation): When the inserted node is in the right subtree of the right subtree, causing an imbalance.\n this._balanceRR(A);\n } else {\n // Right-Left Rotation (RL Rotation): When the inserted node is in the left subtree of the right subtree, causing an imbalance.\n this._balanceRL(A);\n }\n }\n }\n // TODO So far, no sure if this is necessary that Recursive Repair: Once rotation operations are executed, it may cause imbalance issues at higher levels of the tree. Therefore, you need to recursively check and repair imbalance problems upwards until you reach the root node.\n }\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function replaces an old node with a new node and sets the height of the new node to be the\n * same as the old node.\n * @param {AVLTreeNode<K, V>} oldNode - The `oldNode` parameter represents the node that needs to be replaced in\n * the data structure.\n * @param {AVLTreeNode<K, V>} newNode - The `newNode` parameter is the new node that will replace the `oldNode` in\n * the data structure.\n * @returns The method is returning the result of calling the `_replaceNode` method from the\n * superclass, with the `oldNode` and `newNode` as arguments.\n */\n protected override _replaceNode(oldNode: AVLTreeNode<K, V>, newNode: AVLTreeNode<K, V>): AVLTreeNode<K, V> {\n newNode.height = oldNode.height;\n\n return super._replaceNode(oldNode, newNode);\n }\n}\n","import type { BinaryTreeDeleteResult, CRUD, EntryCallback, OptNode, RBTNColor, RedBlackTreeOptions } from '../../types';\nimport { BST, BSTNode } from './bst';\nimport { IBinaryTree } from '../../interfaces';\n\nexport class RedBlackTreeNode<K = any, V = any> extends BSTNode<K, V> {\n override parent?: RedBlackTreeNode<K, V> = undefined;\n\n /**\n * The constructor initializes a node with a key, value, and color for a Red-Black Tree.\n * @param {K} key - The `key` parameter is a key of type `K` that is used to identify the node in a\n * Red-Black Tree data structure.\n * @param {V} [value] - The `value` parameter in the constructor is an optional parameter of type\n * `V`. It represents the value associated with the key in the data structure being constructed.\n * @param {RBTNColor} [color=BLACK] - The `color` parameter in the constructor is used to specify the\n * color of the node in a Red-Black Tree. It has a default value of 'BLACK' if not provided\n * explicitly.\n */\n constructor(key: K, value?: V, color: RBTNColor = 'BLACK') {\n super(key, value);\n this._color = color;\n }\n\n override _left?: RedBlackTreeNode<K, V> | null | undefined = undefined;\n\n override get left(): RedBlackTreeNode<K, V> | null | undefined {\n return this._left;\n }\n\n override set left(v: RedBlackTreeNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._left = v;\n }\n\n override _right?: RedBlackTreeNode<K, V> | null | undefined = undefined;\n\n override get right(): RedBlackTreeNode<K, V> | null | undefined {\n return this._right;\n }\n\n override set right(v: RedBlackTreeNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n}\n\n/**\n * 1. Efficient self-balancing, but not completely balanced. Compared with AVLTree, the addition and deletion efficiency is high but the query efficiency is slightly lower.\n * 2. It is BST itself. Compared with Heap which is not completely ordered, RedBlackTree is completely ordered.\n * @example\n * // using Red-Black Tree as a price-based index for stock data\n * // Define the structure of individual stock records\n * interface StockRecord {\n * price: number; // Stock price (key for indexing)\n * symbol: string; // Stock ticker symbol\n * volume: number; // Trade volume\n * }\n *\n * // Simulate stock market data as it might come from an external feed\n * const marketStockData: StockRecord[] = [\n * { price: 142.5, symbol: 'AAPL', volume: 1000000 },\n * { price: 335.2, symbol: 'MSFT', volume: 800000 },\n * { price: 3285.04, symbol: 'AMZN', volume: 500000 },\n * { price: 267.98, symbol: 'META', volume: 750000 },\n * { price: 234.57, symbol: 'GOOGL', volume: 900000 }\n * ];\n *\n * // Extend the stock record type to include metadata for database usage\n * type StockTableRecord = StockRecord & { lastUpdated: Date };\n *\n * // Create a Red-Black Tree to index stock records by price\n * // Simulates a database index with stock price as the key for quick lookups\n * const priceIndex = new RedBlackTree<number, StockTableRecord, StockRecord>(marketStockData, {\n * toEntryFn: stockRecord => [\n * stockRecord.price, // Use stock price as the key\n * {\n * ...stockRecord,\n * lastUpdated: new Date() // Add a timestamp for when the record was indexed\n * }\n * ]\n * });\n *\n * // Query the stock with the highest price\n * const highestPricedStock = priceIndex.getRightMost();\n * console.log(priceIndex.get(highestPricedStock)?.symbol); // 'AMZN' // Amazon has the highest price\n *\n * // Query stocks within a specific price range (200 to 400)\n * const stocksInRange = priceIndex.rangeSearch(\n * [200, 400], // Price range\n * node => priceIndex.get(node)?.symbol // Extract stock symbols for the result\n * );\n * console.log(stocksInRange); // ['GOOGL', 'META', 'MSFT']\n */\nexport class RedBlackTree<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends BST<K, V, R, MK, MV, MR>\n implements IBinaryTree<K, V, R, MK, MV, MR>\n{\n /**\n * This TypeScript constructor initializes a Red-Black Tree with optional keys, nodes, entries, or\n * raw data.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an\n * iterable that can contain either `K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined` objects or `R` objects. It\n * is used to initialize the Red-Black Tree with keys, nodes, entries, or\n * @param [options] - The `options` parameter in the constructor is of type `RedBlackTreeOptions<K,\n * V, R>`. It is an optional parameter that allows you to specify additional options for the\n * RedBlackTree class. These options could include configuration settings, behavior customization, or\n * any other parameters that are specific to\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n > = [],\n options?: RedBlackTreeOptions<K, V, R>\n ) {\n super([], options);\n\n this._root = this.NIL;\n\n if (keysNodesEntriesOrRaws) {\n this.addMany(keysNodesEntriesOrRaws);\n }\n }\n\n protected override _root: RedBlackTreeNode<K, V> | undefined;\n\n override get root(): RedBlackTreeNode<K, V> | undefined {\n return this._root;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a new Red-Black Tree node with the specified key, value, and color.\n * @param {K} key - The key parameter represents the key value of the node being created. It is of\n * type K, which is a generic type that can be replaced with any specific type when using the\n * function.\n * @param {V} [value] - The `value` parameter is an optional parameter that represents the value\n * associated with the key in the node. It is not required and can be omitted if you only need to\n * create a node with a key.\n * @param {RBTNColor} [color=BLACK] - The \"color\" parameter is used to specify the color of the node\n * in a Red-Black Tree. It can have two possible values: \"RED\" or \"BLACK\". By default, the color is\n * set to \"BLACK\" if not specified.\n * @returns A new instance of a RedBlackTreeNode with the specified key, value, and color is being\n * returned.\n */\n override createNode(key: K, value?: V, color: RBTNColor = 'BLACK'): RedBlackTreeNode<K, V> {\n return new RedBlackTreeNode<K, V>(key, this._isMapMode ? undefined : value, color);\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function creates a new Red-Black Tree with the specified options.\n * @param [options] - The `options` parameter is an optional object that contains additional\n * configuration options for creating the Red-Black Tree. It has the following properties:\n * @returns a new instance of a RedBlackTree object.\n */\n override createTree(options?: RedBlackTreeOptions<K, V, R>) {\n return new RedBlackTree<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n isMapMode: this._isMapMode,\n specifyComparable: this._specifyComparable,\n toEntryFn: this._toEntryFn,\n ...options\n });\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function checks if the input is an instance of the RedBlackTreeNode class.\n * @param {K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be of type `R` or `K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`.\n * @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is\n * an instance of the `RedBlackTreeNode` class.\n */\n override isNode(\n keyNodeOrEntry: K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is RedBlackTreeNode<K, V> {\n return keyNodeOrEntry instanceof RedBlackTreeNode;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The \"clear\" function sets the root node of a data structure to a sentinel value and resets the\n * size counter to zero.\n */\n override clear() {\n super.clear();\n this._root = this.NIL;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function adds a new node to a binary search tree and returns true if the node was successfully\n * added.\n * @param {K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can accept a value of type `R` or `K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`.\n * @param {V} [value] - The `value` parameter is an optional value that you want to associate with\n * the key in the data structure. It represents the value that you want to add or update in the data\n * structure.\n * @returns The method is returning a boolean value. If a new node is successfully added to the tree,\n * the method returns true. If the node already exists and its value is updated, the method also\n * returns true. If the node cannot be added or updated, the method returns false.\n */\n override add(\n keyNodeOrEntry: K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V\n ): boolean {\n const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);\n if (!this.isRealNode(newNode)) return false;\n\n const insertStatus = this._insert(newNode);\n\n if (insertStatus === 'CREATED') {\n // Ensure the root is black\n if (this.isRealNode(this._root)) {\n this._root.color = 'BLACK';\n } else {\n return false;\n }\n if (this._isMapMode) this._setValue(newNode.key, newValue);\n this._size++;\n return true;\n }\n if (insertStatus === 'UPDATED') {\n if (this._isMapMode) this._setValue(newNode.key, newValue);\n return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function overrides the delete method in a binary tree data structure to remove a node based on\n * a given predicate and maintain the binary search tree properties.\n * @param {K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The `keyNodeOrEntry`\n * parameter in the `override delete` method is used to specify the condition or key based on which a\n * node should be deleted from the binary tree. It can be a key, a node, an entry, or a predicate\n * function that determines which node(s) should be deleted.\n * @returns The `override delete` method is returning an array of `BinaryTreeDeleteResult<RedBlackTreeNode<K, V>>`\n * objects. Each object in the array contains information about the deleted node and whether\n * balancing is needed.\n */\n override delete(\n keyNodeOrEntry: K | RedBlackTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): BinaryTreeDeleteResult<RedBlackTreeNode<K, V>>[] {\n if (keyNodeOrEntry === null) return [];\n\n const results: BinaryTreeDeleteResult<RedBlackTreeNode<K, V>>[] = [];\n let nodeToDelete: OptNode<RedBlackTreeNode<K, V>>;\n if (this._isPredicate(keyNodeOrEntry)) nodeToDelete = this.getNode(keyNodeOrEntry);\n else nodeToDelete = this.isRealNode(keyNodeOrEntry) ? keyNodeOrEntry : this.getNode(keyNodeOrEntry);\n\n if (!nodeToDelete) {\n return results;\n }\n\n let originalColor = nodeToDelete.color;\n let replacementNode: RedBlackTreeNode<K, V> | undefined;\n\n if (!this.isRealNode(nodeToDelete.left)) {\n if (nodeToDelete.right !== null) {\n replacementNode = nodeToDelete.right;\n this._transplant(nodeToDelete, nodeToDelete.right);\n }\n } else if (!this.isRealNode(nodeToDelete.right)) {\n replacementNode = nodeToDelete.left;\n this._transplant(nodeToDelete, nodeToDelete.left);\n } else {\n const successor = this.getLeftMost(node => node, nodeToDelete.right);\n if (successor) {\n originalColor = successor.color;\n if (successor.right !== null) replacementNode = successor.right;\n\n if (successor.parent === nodeToDelete) {\n if (this.isRealNode(replacementNode)) {\n replacementNode.parent = successor;\n }\n } else {\n if (successor.right !== null) {\n this._transplant(successor, successor.right);\n successor.right = nodeToDelete.right;\n }\n if (this.isRealNode(successor.right)) {\n successor.right.parent = successor;\n }\n }\n\n this._transplant(nodeToDelete, successor);\n successor.left = nodeToDelete.left;\n if (this.isRealNode(successor.left)) {\n successor.left.parent = successor;\n }\n successor.color = nodeToDelete.color;\n }\n }\n if (this._isMapMode) this._store.delete(nodeToDelete.key);\n this._size--;\n\n // If the original color was black, fix the tree\n if (originalColor === 'BLACK') {\n this._deleteFixup(replacementNode);\n }\n\n results.push({ deleted: nodeToDelete, needBalanced: undefined });\n\n return results;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function in TypeScript overrides the default behavior to create a new Red-Black Tree by\n * applying a callback to each entry in the original tree.\n * @param callback - A function that will be called for each entry in the tree, with parameters\n * representing the key, value, index, and the tree itself. It should return an entry for the new\n * tree.\n * @param [options] - The `options` parameter in the `map` method is of type `RedBlackTreeOptions<MK, MV,\n * MR>`. This parameter allows you to specify additional options or configurations for the Red-Black\n * Tree that will be created during the mapping process. These options could include things like\n * custom comparators\n * @param {any} [thisArg] - The `thisArg` parameter in the `override map` function is used to specify\n * the value of `this` when executing the `callback` function. It allows you to set the context\n * (value of `this`) for the callback function. This can be useful when you want to access properties\n * or\n * @returns A new Red-Black Tree is being returned, where each entry has been transformed using the\n * provided callback function.\n */\n override map(\n callback: EntryCallback<K, V | undefined, [MK, MV]>,\n options?: RedBlackTreeOptions<MK, MV, MR>,\n thisArg?: any\n ): RedBlackTree<MK, MV, MR> {\n const newTree = new RedBlackTree<MK, MV, MR>([], options);\n let index = 0;\n for (const [key, value] of this) {\n newTree.add(callback.call(thisArg, key, value, index++, this));\n }\n return newTree;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `clone` overrides the default cloning behavior to create a deep copy of a tree\n * structure.\n * @returns The `cloned` object is being returned.\n */\n override clone() {\n const cloned = this.createTree();\n this._clone(cloned);\n return cloned;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function sets the root of a tree-like structure and updates the parent property of the new\n * root.\n * @param {RedBlackTreeNode<K, V> | undefined} v - v is a parameter of type RedBlackTreeNode<K, V> or undefined.\n */\n protected override _setRoot(v: RedBlackTreeNode<K, V> | undefined) {\n if (v) {\n v.parent = undefined;\n }\n this._root = v;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function replaces an old node with a new node while preserving the color of the old node.\n * @param {RedBlackTreeNode<K, V>} oldNode - The `oldNode` parameter represents the node that needs to be replaced in\n * the data structure.\n * @param {RedBlackTreeNode<K, V>} newNode - The `newNode` parameter is of type `RedBlackTreeNode<K, V>`, which represents a node in a\n * data structure.\n * @returns The method is returning the result of calling the `_replaceNode` method from the\n * superclass, with the `oldNode` and `newNode` parameters.\n */\n protected override _replaceNode(\n oldNode: RedBlackTreeNode<K, V>,\n newNode: RedBlackTreeNode<K, V>\n ): RedBlackTreeNode<K, V> {\n newNode.color = oldNode.color;\n\n return super._replaceNode(oldNode, newNode);\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The `_insert` function inserts a node into a binary search tree and performs necessary fix-ups to\n * maintain the red-black tree properties.\n * @param {RedBlackTreeNode<K, V>} node - The `node` parameter represents the node that needs to be inserted into the\n * binary search tree.\n * @returns a string value indicating the result of the insertion operation. It can return either\n * 'UPDATED' if the node with the same key already exists and was updated, or 'CREATED' if a new node\n * was created and inserted into the tree.\n */\n protected _insert(node: RedBlackTreeNode<K, V>): CRUD {\n let current = this.root;\n let parent: RedBlackTreeNode<K, V> | undefined = undefined;\n\n while (this.isRealNode(current)) {\n parent = current;\n const compared = this._compare(node.key, current.key);\n if (compared < 0) {\n current = current.left ?? this.NIL;\n } else if (compared > 0) {\n current = current.right ?? this.NIL;\n } else {\n this._replaceNode(current, node);\n return 'UPDATED';\n }\n }\n\n node.parent = parent;\n\n if (!parent) {\n this._setRoot(node);\n } else if (this._compare(node.key, parent.key) < 0) {\n parent.left = node;\n } else {\n parent.right = node;\n }\n\n node.left = this.NIL;\n node.right = this.NIL;\n node.color = 'RED';\n\n this._insertFixup(node);\n return 'CREATED';\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `_transplant` is used to replace a node `u` with another node `v` in a binary tree.\n * @param {RedBlackTreeNode<K, V>} u - The parameter \"u\" represents a node in a binary tree.\n * @param {RedBlackTreeNode<K, V> | undefined} v - The parameter `v` is of type `RedBlackTreeNode<K, V> | undefined`, which means it can\n * either be a `RedBlackTreeNode<K, V>` object or `undefined`.\n */\n protected _transplant(u: RedBlackTreeNode<K, V>, v: RedBlackTreeNode<K, V> | undefined): void {\n if (!u.parent) {\n this._setRoot(v);\n } else if (u === u.parent.left) {\n u.parent.left = v;\n } else {\n u.parent.right = v;\n }\n\n if (v) {\n v.parent = u.parent;\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The `_insertFixup` function is used to fix the Red-Black Tree after inserting a new node.\n * @param {RedBlackTreeNode<K, V> | undefined} z - The parameter `z` represents a node in the Red-Black Tree data\n * structure. It can either be a valid node or `undefined`.\n */\n protected _insertFixup(z: RedBlackTreeNode<K, V> | undefined): void {\n // Continue fixing the tree as long as the parent of z is red\n while (z?.parent?.color === 'RED') {\n // Check if the parent of z is the left child of its parent\n if (z.parent === z.parent.parent?.left) {\n // Case 1: The uncle (y) of z is red\n const y = z.parent.parent.right;\n if (y?.color === 'RED') {\n // Set colors to restore properties of Red-Black Tree\n z.parent.color = 'BLACK';\n y.color = 'BLACK';\n z.parent.parent.color = 'RED';\n // Move up the tree to continue fixing\n z = z.parent.parent;\n } else {\n // Case 2: The uncle (y) of z is black, and z is a right child\n if (z === z.parent.right) {\n // Perform a left rotation to transform the case into Case 3\n z = z.parent;\n this._leftRotate(z);\n }\n\n // Case 3: The uncle (y) of z is black, and z is a left child\n // Adjust colors and perform a right rotation\n if (z && this.isRealNode(z.parent) && this.isRealNode(z.parent.parent)) {\n z.parent.color = 'BLACK';\n z.parent.parent.color = 'RED';\n this._rightRotate(z.parent.parent);\n }\n }\n } else {\n // Symmetric case for the right child (left and right exchanged)\n // Follow the same logic as above with left and right exchanged\n const y: RedBlackTreeNode<K, V> | undefined = z?.parent?.parent?.left ?? undefined;\n if (y?.color === 'RED') {\n z.parent.color = 'BLACK';\n y.color = 'BLACK';\n z.parent.parent!.color = 'RED';\n z = z.parent.parent;\n } else {\n if (z === z.parent.left) {\n z = z.parent;\n this._rightRotate(z);\n }\n\n if (z && this.isRealNode(z.parent) && this.isRealNode(z.parent.parent)) {\n z.parent.color = 'BLACK';\n z.parent.parent.color = 'RED';\n this._leftRotate(z.parent.parent);\n }\n }\n }\n }\n\n // Ensure that the root is black after fixing\n if (this.isRealNode(this._root)) this._root.color = 'BLACK';\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The `_deleteFixup` function is used to fix the red-black tree after a node deletion by adjusting\n * the colors and performing rotations.\n * @param {RedBlackTreeNode<K, V> | undefined} node - The `node` parameter represents a node in a binary tree. It can\n * be either a valid node object or `undefined`.\n * @returns The function does not return any value. It has a return type of `void`, which means it\n * does not return anything.\n */\n protected _deleteFixup(node: RedBlackTreeNode<K, V> | undefined): void {\n // Early exit condition\n if (!node || node === this.root || node.color === 'BLACK') {\n if (node) {\n node.color = 'BLACK'; // Ensure the final node is black\n }\n return;\n }\n\n while (node && node !== this.root && node.color === 'BLACK') {\n const parent: RedBlackTreeNode<K, V> | undefined = node.parent;\n\n if (!parent) {\n break; // Ensure the loop terminates if there's an issue with the tree structure\n }\n\n if (node === parent.left) {\n let sibling = parent.right;\n\n // Cases 1 and 2: Sibling is red or both children of sibling are black\n if (sibling?.color === 'RED') {\n sibling.color = 'BLACK';\n parent.color = 'RED';\n this._leftRotate(parent);\n sibling = parent.right;\n }\n\n // Case 3: Sibling's left child is black\n if ((sibling?.left?.color ?? 'BLACK') === 'BLACK') {\n if (sibling) sibling.color = 'RED';\n node = parent;\n } else {\n // Case 4: Adjust colors and perform a right rotation\n if (sibling?.left) sibling.left.color = 'BLACK';\n if (sibling) sibling.color = parent.color;\n parent.color = 'BLACK';\n this._rightRotate(parent);\n node = this.root;\n }\n } else {\n // Symmetric case for the right child (left and right exchanged)\n let sibling = parent.left;\n\n // Cases 1 and 2: Sibling is red or both children of sibling are black\n if (sibling?.color === 'RED') {\n sibling.color = 'BLACK';\n if (parent) parent.color = 'RED';\n this._rightRotate(parent);\n if (parent) sibling = parent.left;\n }\n\n // Case 3: Sibling's left child is black\n if ((sibling?.right?.color ?? 'BLACK') === 'BLACK') {\n if (sibling) sibling.color = 'RED';\n node = parent;\n } else {\n // Case 4: Adjust colors and perform a left rotation\n if (sibling?.right) sibling.right.color = 'BLACK';\n if (sibling) sibling.color = parent.color;\n if (parent) parent.color = 'BLACK';\n this._leftRotate(parent);\n node = this.root;\n }\n }\n }\n\n // Ensure that the final node (possibly the root) is black\n if (node) {\n node.color = 'BLACK';\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_leftRotate` function performs a left rotation on a given node in a binary tree.\n * @param {RedBlackTreeNode<K, V> | undefined} x - The parameter `x` is of type `RedBlackTreeNode<K, V> | undefined`. It represents a\n * node in a binary tree or `undefined` if there is no node.\n * @returns void, which means it does not return any value.\n */\n protected _leftRotate(x: RedBlackTreeNode<K, V> | undefined): void {\n if (!x || !x.right) {\n return;\n }\n\n const y = x.right;\n x.right = y.left;\n\n if (this.isRealNode(y.left)) {\n y.left.parent = x;\n }\n\n y.parent = x.parent;\n\n if (!x.parent) {\n this._setRoot(y);\n } else if (x === x.parent.left) {\n x.parent.left = y;\n } else {\n x.parent.right = y;\n }\n\n y.left = x;\n x.parent = y;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_rightRotate` function performs a right rotation on a given node in a binary tree.\n * @param {RedBlackTreeNode<K, V> | undefined} y - The parameter `y` is of type `RedBlackTreeNode<K, V> | undefined`. It represents a\n * node in a binary tree or `undefined` if there is no node.\n * @returns void, which means it does not return any value.\n */\n protected _rightRotate(y: RedBlackTreeNode<K, V> | undefined): void {\n if (!y || !y.left) {\n return;\n }\n\n const x = y.left;\n y.left = x.right;\n\n if (this.isRealNode(x.right)) {\n x.right.parent = y;\n }\n\n x.parent = y.parent;\n\n if (!y.parent) {\n this._setRoot(x);\n } else if (y === y.parent.left) {\n y.parent.left = x;\n } else {\n y.parent.right = x;\n }\n\n x.right = y;\n y.parent = x;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport { AVLTreeMultiMapOptions, BTNOptKeyOrNull } from '../../types';\nimport { AVLTree, AVLTreeNode } from './avl-tree';\nimport { IBinaryTree } from '../../interfaces';\n\nexport class AVLTreeMultiMapNode<K = any, V = any> extends AVLTreeNode<K, V[]> {\n override parent?: AVLTreeMultiMapNode<K, V> = undefined;\n\n /**\n * This TypeScript constructor initializes an object with a key of type K and an array of values of\n * type V.\n * @param {K} key - The `key` parameter is typically used to store a unique identifier or key for the\n * data being stored in the data structure. It helps in quickly accessing or retrieving the\n * associated value in the data structure.\n * @param {V[]} value - The `value` parameter in the constructor represents an array of values of\n * type `V`.\n */\n constructor(key: K, value: V[]) {\n super(key, value);\n }\n\n override _left?: AVLTreeMultiMapNode<K, V> | null | undefined = undefined;\n\n override get left(): AVLTreeMultiMapNode<K, V> | null | undefined {\n return this._left;\n }\n\n override set left(v: AVLTreeMultiMapNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._left = v;\n }\n\n override _right?: AVLTreeMultiMapNode<K, V> | null | undefined = undefined;\n\n override get right(): AVLTreeMultiMapNode<K, V> | null | undefined {\n return this._right;\n }\n\n override set right(v: AVLTreeMultiMapNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n}\n\n/**\n *\n */\nexport class AVLTreeMultiMap<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends AVLTree<K, V[], R, MK, MV[], MR>\n implements IBinaryTree<K, V[], R, MK, MV, MR>\n{\n /**\n * The constructor initializes an AVLTreeMultiMap with the provided keys, nodes, entries, or raw data\n * and options.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an\n * iterable that can contain either key-value pairs represented as `BTNRep<K, V[],\n * AVLTreeMultiMapNode<K, V>>` or raw data represented as `R`. This parameter is used to initialize\n * the AVLTreeMulti\n * @param [options] - The `options` parameter in the constructor is of type\n * `AVLTreeMultiMapOptions<K, V[], R>`. It is an optional parameter that allows you to specify\n * additional options for configuring the AVLTreeMultiMap instance.\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | R\n > = [],\n options?: AVLTreeMultiMapOptions<K, V[], R>\n ) {\n super([], { ...options, isMapMode: true });\n if (keysNodesEntriesOrRaws) {\n this.addMany(keysNodesEntriesOrRaws);\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `createTree` in TypeScript overrides the creation of an AVLTreeMultiMap with\n * specified options.\n * @param [options] - The `options` parameter in the `createTree` function is of type\n * `AVLTreeMultiMapOptions<K, V[], R>`. This means it is an object that can have properties of type\n * `K`, `V[]`, and `R`. The function creates a new `AVL\n * @returns The `createTree` method is returning a new instance of `AVLTreeMultiMap` with the\n * provided options.\n */\n override createTree(options?: AVLTreeMultiMapOptions<K, V[], R>) {\n return new AVLTreeMultiMap<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n specifyComparable: this._specifyComparable,\n toEntryFn: this._toEntryFn,\n isReverse: this._isReverse,\n isMapMode: this._isMapMode,\n ...options\n });\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `createNode` function in TypeScript overrides the default implementation to create a new\n * AVLTreeMultiMapNode with a specified key and value array.\n * @param {K} key - The `key` parameter represents the key of the node being created in the\n * AVLTreeMultiMap.\n * @param {V[]} value - The `value` parameter in the `createNode` method represents an array of\n * values associated with a specific key in the AVLTreeMultiMapNode. If no value is provided when\n * calling the method, an empty array `[]` is used as the default value.\n * @returns An AVLTreeMultiMapNode object is being returned, with the specified key and value. If the\n * AVLTreeMultiMap is in map mode, an empty array is used as the value, otherwise the provided value\n * array is used.\n */\n override createNode(key: K, value: V[] = []): AVLTreeMultiMapNode<K, V> {\n return new AVLTreeMultiMapNode<K, V>(key, this._isMapMode ? [] : value);\n }\n\n override add(\n keyNodeOrEntry: K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined\n ): boolean;\n\n override add(key: K, value: V): boolean;\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `add` in this TypeScript code overrides the superclass method to add key-value pairs\n * to an AVLTreeMultiMap, handling different input types and scenarios.\n * @param [key] - The `key` parameter in the `override add` method represents the key of the entry to\n * be added to the AVLTreeMultiMap. It can be of type `K`, which is the key type of the map. The key\n * can be a single key value, a node of the AVLTree\n * @param {V[]} [values] - The `values` parameter in the `add` method represents an array of values\n * that you want to add to the AVLTreeMultiMap. It can contain one or more values associated with a\n * specific key.\n * @returns The `add` method is returning a boolean value, which indicates whether the operation was\n * successful or not.\n */\n override add(\n keyNodeOrEntry: K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | K,\n value?: V\n ): boolean {\n if (this.isRealNode(keyNodeOrEntry)) return super.add(keyNodeOrEntry);\n\n const _commonAdd = (key?: BTNOptKeyOrNull<K>, values?: V[]) => {\n if (key === undefined || key === null) return false;\n\n const _addToValues = () => {\n const existingValues = this.get(key);\n if (existingValues !== undefined && values !== undefined) {\n for (const value of values) existingValues.push(value);\n return true;\n }\n return false;\n };\n\n const _addByNode = () => {\n const existingNode = this.getNode(key);\n if (this.isRealNode(existingNode)) {\n const existingValues = this.get(existingNode);\n if (existingValues === undefined) {\n super.add(key, values);\n return true;\n }\n if (values !== undefined) {\n for (const value of values) existingValues.push(value);\n return true;\n } else {\n return false;\n }\n } else {\n return super.add(key, values);\n }\n };\n\n if (this._isMapMode) {\n return _addByNode() || _addToValues();\n }\n return _addToValues() || _addByNode();\n };\n\n if (this.isEntry(keyNodeOrEntry)) {\n const [key, values] = keyNodeOrEntry;\n return _commonAdd(key, value !== undefined ? [value] : values);\n }\n\n return _commonAdd(keyNodeOrEntry, value !== undefined ? [value] : undefined);\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `deleteValue` removes a specific value from a key in an AVLTreeMultiMap data\n * structure and deletes the entire node if no values are left for that key.\n * @param {K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | K} keyNodeOrEntry - The `keyNodeOrEntry`\n * parameter in the `deleteValue` function can be either a `BTNRep` object representing a key-value\n * pair in the AVLTreeMultiMapNode, or just the key itself.\n * @param {V} value - The `value` parameter in the `deleteValue` function represents the specific\n * value that you want to delete from the multi-map data structure associated with a particular key.\n * The function checks if the value exists in the array of values associated with the key, and if\n * found, removes it from the array.\n * @returns The `deleteValue` function returns a boolean value. It returns `true` if the specified\n * `value` was successfully deleted from the array of values associated with the `keyNodeOrEntry`. If\n * the value was not found in the array, it returns `false`.\n */\n deleteValue(\n keyNodeOrEntry: K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | K,\n value: V\n ): boolean {\n const values = this.get(keyNodeOrEntry);\n if (Array.isArray(values)) {\n const index = values.indexOf(value);\n if (index === -1) return false;\n values.splice(index, 1);\n\n // If no values left, remove the entire node\n if (values.length === 0) this.delete(keyNodeOrEntry);\n\n return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `clone` overrides the default cloning behavior to create a deep copy of a tree\n * structure.\n * @returns A cloned tree object is being returned.\n */\n override clone() {\n const cloned = this.createTree();\n this._clone(cloned);\n return cloned;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { BTNOptKeyOrNull, TreeMultiMapOptions } from '../../types';\nimport { RedBlackTree, RedBlackTreeNode } from './red-black-tree';\nimport { IBinaryTree } from '../../interfaces';\n\nexport class TreeMultiMapNode<K = any, V = any> extends RedBlackTreeNode<K, V[]> {\n override parent?: TreeMultiMapNode<K, V> = undefined;\n\n /**\n * This TypeScript constructor initializes an object with a key of type K and an array of values of\n * type V.\n * @param {K} key - The `key` parameter is typically used to store a unique identifier or key for the\n * data being stored in the data structure. It helps in quickly accessing or retrieving the\n * associated value in the data structure.\n * @param {V[]} value - The `value` parameter in the constructor represents an array of values of\n * type `V`.\n */\n constructor(key: K, value?: V[]) {\n super(key, value);\n }\n\n override _left?: TreeMultiMapNode<K, V> | null | undefined = undefined;\n\n override get left(): TreeMultiMapNode<K, V> | null | undefined {\n return this._left;\n }\n\n override set left(v: TreeMultiMapNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._left = v;\n }\n\n override _right?: TreeMultiMapNode<K, V> | null | undefined = undefined;\n\n override get right(): TreeMultiMapNode<K, V> | null | undefined {\n return this._right;\n }\n\n override set right(v: TreeMultiMapNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n}\n\n/**\n *\n * @example\n * // players ranked by score with their equipment\n * type Equipment = {\n * name: string; // Equipment name\n * quality: 'legendary' | 'epic' | 'rare' | 'common';\n * level: number;\n * };\n *\n * type Player = {\n * name: string;\n * score: number;\n * equipments: Equipment[];\n * };\n *\n * // Mock player data with their scores and equipment\n * const players: Player[] = [\n * {\n * name: 'DragonSlayer',\n * score: 8750,\n * equipments: [\n * { name: 'AWM', quality: 'legendary', level: 85 },\n * { name: 'Level 3 Helmet', quality: 'epic', level: 80 },\n * { name: 'Extended Quickdraw Mag', quality: 'rare', level: 75 },\n * { name: 'Compensator', quality: 'epic', level: 78 },\n * { name: 'Vertical Grip', quality: 'rare', level: 72 }\n * ]\n * },\n * {\n * name: 'ShadowNinja',\n * score: 7200,\n * equipments: [\n * { name: 'M416', quality: 'epic', level: 75 },\n * { name: 'Ghillie Suit', quality: 'rare', level: 70 },\n * { name: 'Red Dot Sight', quality: 'common', level: 65 },\n * { name: 'Extended QuickDraw Mag', quality: 'rare', level: 68 }\n * ]\n * },\n * {\n * name: 'RuneMaster',\n * score: 9100,\n * equipments: [\n * { name: 'KAR98K', quality: 'legendary', level: 90 },\n * { name: 'Level 3 Vest', quality: 'legendary', level: 85 },\n * { name: 'Holographic Sight', quality: 'epic', level: 82 },\n * { name: 'Suppressor', quality: 'legendary', level: 88 },\n * { name: 'Level 3 Backpack', quality: 'epic', level: 80 }\n * ]\n * },\n * {\n * name: 'BattleKing',\n * score: 8500,\n * equipments: [\n * { name: 'AUG', quality: 'epic', level: 82 },\n * { name: 'Red Dot Sight', quality: 'rare', level: 75 },\n * { name: 'Extended Mag', quality: 'common', level: 70 },\n * { name: 'Tactical Stock', quality: 'rare', level: 76 }\n * ]\n * },\n * {\n * name: 'SniperElite',\n * score: 7800,\n * equipments: [\n * { name: 'M24', quality: 'legendary', level: 88 },\n * { name: 'Compensator', quality: 'epic', level: 80 },\n * { name: 'Scope 8x', quality: 'legendary', level: 85 },\n * { name: 'Level 2 Helmet', quality: 'rare', level: 75 }\n * ]\n * },\n * {\n * name: 'RushMaster',\n * score: 7500,\n * equipments: [\n * { name: 'Vector', quality: 'rare', level: 72 },\n * { name: 'Level 2 Helmet', quality: 'common', level: 65 },\n * { name: 'Quickdraw Mag', quality: 'common', level: 60 },\n * { name: 'Laser Sight', quality: 'rare', level: 68 }\n * ]\n * },\n * {\n * name: 'GhostWarrior',\n * score: 8200,\n * equipments: [\n * { name: 'SCAR-L', quality: 'epic', level: 78 },\n * { name: 'Extended Quickdraw Mag', quality: 'rare', level: 70 },\n * { name: 'Holographic Sight', quality: 'epic', level: 75 },\n * { name: 'Suppressor', quality: 'rare', level: 72 },\n * { name: 'Vertical Grip', quality: 'common', level: 65 }\n * ]\n * },\n * {\n * name: 'DeathDealer',\n * score: 7300,\n * equipments: [\n * { name: 'SKS', quality: 'epic', level: 76 },\n * { name: 'Holographic Sight', quality: 'rare', level: 68 },\n * { name: 'Extended Mag', quality: 'common', level: 65 }\n * ]\n * },\n * {\n * name: 'StormRider',\n * score: 8900,\n * equipments: [\n * { name: 'MK14', quality: 'legendary', level: 92 },\n * { name: 'Level 3 Backpack', quality: 'legendary', level: 85 },\n * { name: 'Scope 8x', quality: 'epic', level: 80 },\n * { name: 'Suppressor', quality: 'legendary', level: 88 },\n * { name: 'Tactical Stock', quality: 'rare', level: 75 }\n * ]\n * },\n * {\n * name: 'CombatLegend',\n * score: 7600,\n * equipments: [\n * { name: 'UMP45', quality: 'rare', level: 74 },\n * { name: 'Level 2 Vest', quality: 'common', level: 67 },\n * { name: 'Red Dot Sight', quality: 'common', level: 62 },\n * { name: 'Extended Mag', quality: 'rare', level: 70 }\n * ]\n * }\n * ];\n *\n * // Create a TreeMultiMap for player rankings\n * const playerRankings = new TreeMultiMap<number, Equipment, Player>(players, {\n * toEntryFn: ({ score, equipments }) => [score, equipments],\n * isMapMode: false\n * });\n *\n * const topPlayersEquipments = playerRankings.rangeSearch([8900, 10000], node => playerRankings.get(node));\n * console.log(topPlayersEquipments); // [\n * // [\n * // {\n * // name: 'MK14',\n * // quality: 'legendary',\n * // level: 92\n * // },\n * // { name: 'Level 3 Backpack', quality: 'legendary', level: 85 },\n * // {\n * // name: 'Scope 8x',\n * // quality: 'epic',\n * // level: 80\n * // },\n * // { name: 'Suppressor', quality: 'legendary', level: 88 },\n * // {\n * // name: 'Tactical Stock',\n * // quality: 'rare',\n * // level: 75\n * // }\n * // ],\n * // [\n * // { name: 'KAR98K', quality: 'legendary', level: 90 },\n * // {\n * // name: 'Level 3 Vest',\n * // quality: 'legendary',\n * // level: 85\n * // },\n * // { name: 'Holographic Sight', quality: 'epic', level: 82 },\n * // {\n * // name: 'Suppressor',\n * // quality: 'legendary',\n * // level: 88\n * // },\n * // { name: 'Level 3 Backpack', quality: 'epic', level: 80 }\n * // ]\n * // ]\n */\nexport class TreeMultiMap<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends RedBlackTree<K, V[], R, MK, MV[], MR>\n implements IBinaryTree<K, V[], R, MK, MV, MR>\n{\n /**\n * The constructor initializes an TreeMultiMap with the provided keys, nodes, entries, or raw data\n * and options.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an\n * iterable that can contain either key-value pairs represented as `BTNRep<K, V[],\n * TreeMultiMapNode<K, V>>` or raw data represented as `R`. This parameter is used to initialize\n * the RedBlackTreeMulti\n * @param [options] - The `options` parameter in the constructor is of type\n * `TreeMultiMapOptions<K, V[], R>`. It is an optional parameter that allows you to specify\n * additional options for configuring the TreeMultiMap instance.\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | TreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | R\n > = [],\n options?: TreeMultiMapOptions<K, V[], R>\n ) {\n super([], { ...options });\n if (keysNodesEntriesOrRaws) {\n this.addMany(keysNodesEntriesOrRaws);\n }\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `createTree` function in TypeScript overrides the default implementation to create a new\n * TreeMultiMap with specified options.\n * @param [options] - The `options` parameter in the `createTree` method is of type\n * `TreeMultiMapOptions<K, V[], R>`. This parameter allows you to pass additional configuration\n * options when creating a new `TreeMultiMap` instance. It includes properties such as\n * `iterationType`, `specifyComparable\n * @returns A new instance of `TreeMultiMap` is being returned, with an empty array as the initial\n * data and the provided options merged with the existing properties of the current object.\n */\n override createTree(options?: TreeMultiMapOptions<K, V[], R>) {\n return new TreeMultiMap<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n specifyComparable: this._specifyComparable,\n toEntryFn: this._toEntryFn,\n isReverse: this._isReverse,\n isMapMode: this._isMapMode,\n ...options\n });\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function `createNode` overrides the creation of a new TreeMultiMapNode with a specified key\n * and value array.\n * @param {K} key - The `key` parameter represents the key of the node being created in the\n * `TreeMultiMap`.\n * @param {V[]} value - The `value` parameter in the `createNode` method represents an array of\n * values associated with a specific key in the TreeMultiMap data structure.\n * @returns A new instance of `TreeMultiMapNode<K, V>` is being returned with the specified key and\n * value. If `_isMapMode` is true, an empty array is passed as the value, otherwise the provided\n * value is used.\n */\n override createNode(key: K, value: V[] = []): TreeMultiMapNode<K, V> {\n return new TreeMultiMapNode<K, V>(key, this._isMapMode ? [] : value);\n }\n\n override add(\n keyNodeOrEntry: K | TreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined\n ): boolean;\n\n override add(key: K, value: V): boolean;\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function overrides the add method to handle different types of input for a TreeMultiMap data\n * structure.\n * @param [key] - The `key` parameter in the `override add` method represents the key of the entry to\n * be added to the TreeMultiMap. It can be of type `K`, which is the key type of the TreeMultiMap, or\n * it can be a TreeMultiMapNode containing the key and its\n * @param {V[]} [values] - The `values` parameter in the `add` method represents an array of values\n * that you want to add to the TreeMultiMap. It can contain one or more values of type `V`.\n * @returns The `add` method is returning a boolean value, which indicates whether the operation was\n * successful or not.\n */\n override add(\n keyNodeOrEntry: K | TreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined,\n value?: V\n ): boolean {\n if (this.isRealNode(keyNodeOrEntry)) return super.add(keyNodeOrEntry);\n\n const _commonAdd = (key?: BTNOptKeyOrNull<K>, values?: V[]) => {\n if (key === undefined || key === null) return false;\n\n const _addToValues = () => {\n const existingValues = this.get(key);\n if (existingValues !== undefined && values !== undefined) {\n for (const value of values) existingValues.push(value);\n return true;\n }\n return false;\n };\n\n const _addByNode = () => {\n const existingNode = this.getNode(key);\n if (this.isRealNode(existingNode)) {\n const existingValues = this.get(existingNode);\n if (existingValues === undefined) {\n super.add(key, values);\n return true;\n }\n if (values !== undefined) {\n for (const value of values) existingValues.push(value);\n return true;\n } else {\n return false;\n }\n } else {\n return super.add(key, values);\n }\n };\n\n if (this._isMapMode) {\n return _addByNode() || _addToValues();\n }\n return _addToValues() || _addByNode();\n };\n\n if (this.isEntry(keyNodeOrEntry)) {\n const [key, values] = keyNodeOrEntry;\n return _commonAdd(key, value !== undefined ? [value] : values);\n }\n\n return _commonAdd(keyNodeOrEntry, value !== undefined ? [value] : undefined);\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(log n)\n *\n * The function `deleteValue` removes a specific value from a key in a TreeMultiMap data structure\n * and deletes the entire node if no values are left for that key.\n * @param {K | TreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined} keyNodeOrEntry - The `keyNodeOrEntry`\n * parameter in the `deleteValue` function can be either a `BTNRep` object containing a key and an\n * array of values, or just a key itself.\n * @param {V} value - The `value` parameter in the `deleteValue` function represents the specific\n * value that you want to remove from the multi-map data structure associated with a particular key.\n * The function checks if the value exists in the array of values associated with the key, and if\n * found, removes it from the array.\n * @returns The `deleteValue` function returns a boolean value - `true` if the specified `value` was\n * successfully deleted from the values associated with the `keyNodeOrEntry`, and `false` otherwise.\n */\n deleteValue(\n keyNodeOrEntry: K | TreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined,\n value: V\n ): boolean {\n const values = this.get(keyNodeOrEntry);\n if (Array.isArray(values)) {\n const index = values.indexOf(value);\n if (index === -1) return false;\n values.splice(index, 1);\n\n // If no values left, remove the entire node\n if (values.length === 0) this.delete(keyNodeOrEntry);\n\n return true;\n }\n return false;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `clone` overrides the default cloning behavior to create a deep copy of a tree\n * structure.\n * @returns The `cloned` object is being returned.\n */\n override clone() {\n const cloned = this.createTree();\n this._clone(cloned);\n return cloned;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type {\n BinaryTreeDeleteResult,\n BSTNOptKeyOrNode,\n EntryCallback,\n IterationType,\n OptNode,\n RBTNColor,\n TreeCounterOptions\n} from '../../types';\nimport { IBinaryTree } from '../../interfaces';\nimport { RedBlackTree, RedBlackTreeNode } from './red-black-tree';\n\nexport class TreeCounterNode<K = any, V = any> extends RedBlackTreeNode<K, V> {\n override parent?: TreeCounterNode<K, V> = undefined;\n\n /**\n * The constructor function initializes a Red-Black Tree node with a key, value, count, and color.\n * @param {K} key - The key parameter represents the key of the node in the Red-Black Tree. It is\n * used to identify and locate the node within the tree.\n * @param {V} [value] - The `value` parameter is an optional parameter that represents the value\n * associated with the key in the Red-Black Tree node. It is not required and can be omitted when\n * creating a new node.\n * @param [count=1] - The `count` parameter represents the number of occurrences of a particular key\n * in the Red-Black Tree. It is an optional parameter with a default value of 1.\n * @param {RBTNColor} [color=BLACK] - The `color` parameter is used to specify the color of the node\n * in a Red-Black Tree. It is optional and has a default value of `'BLACK'`.\n */\n constructor(key: K, value?: V, count = 1, color: RBTNColor = 'BLACK') {\n super(key, value, color);\n this.count = count;\n }\n\n override _left?: TreeCounterNode<K, V> | null | undefined = undefined;\n\n override get left(): TreeCounterNode<K, V> | null | undefined {\n return this._left;\n }\n\n override set left(v: TreeCounterNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._left = v;\n }\n\n override _right?: TreeCounterNode<K, V> | null | undefined = undefined;\n\n override get right(): TreeCounterNode<K, V> | null | undefined {\n return this._right;\n }\n\n override set right(v: TreeCounterNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n}\n\n/**\n *\n */\nexport class TreeCounter<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends RedBlackTree<K, V, R, MK, MV, MR>\n implements IBinaryTree<K, V, R, MK, MV, MR>\n{\n /**\n * The constructor function initializes a TreeCounter object with optional initial data.\n * @param keysNodesEntriesOrRaws - The parameter `keysNodesEntriesOrRaws` is an\n * iterable that can contain keys, nodes, entries, or raw elements. It is used to initialize the\n * TreeCounter with initial data.\n * @param [options] - The `options` parameter is an optional object that can be used to customize the\n * behavior of the `TreeCounter` constructor. It can include properties such as `compareKeys` and\n * `compareValues`, which are functions used to compare keys and values respectively.\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n > = [],\n options?: TreeCounterOptions<K, V, R>\n ) {\n super([], options);\n if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);\n }\n\n protected _count = 0;\n\n // TODO the _count is not accurate after nodes count modified\n /**\n * The function calculates the sum of the count property of all nodes in a tree structure.\n * @returns the sum of the count property of all nodes in the tree.\n */\n get count(): number {\n return this._count;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function calculates the sum of the count property of all nodes in a tree using depth-first\n * search.\n * @returns the sum of the count property of all nodes in the tree.\n */\n getComputedCount(): number {\n let sum = 0;\n this.dfs(node => (sum += node ? node.count : 0));\n return sum;\n }\n\n /**\n * The function creates a new TreeCounterNode with the specified key, value, color, and count.\n * @param {K} key - The key parameter represents the key of the node being created. It is of type K,\n * which is a generic type representing the type of keys in the tree.\n * @param {V} [value] - The `value` parameter is an optional parameter that represents the value\n * associated with the key in the node. It is of type `V`, which can be any data type.\n * @param {RBTNColor} [color=BLACK] - The color parameter is used to specify the color of the node in\n * a Red-Black Tree. It can have two possible values: 'RED' or 'BLACK'. The default value is 'BLACK'.\n * @param {number} [count] - The `count` parameter represents the number of occurrences of a key in\n * the tree. It is an optional parameter and is used to keep track of the number of values associated\n * with a key in the tree.\n * @returns A new instance of the TreeCounterNode class, casted as TreeCounterNode<K, V>.\n */\n override createNode(key: K, value?: V, color: RBTNColor = 'BLACK', count?: number): TreeCounterNode<K, V> {\n return new TreeCounterNode(key, this._isMapMode ? undefined : value, count, color) as TreeCounterNode<K, V>;\n }\n\n /**\n * The function creates a new instance of a TreeCounter with the specified options and returns it.\n * @param [options] - The `options` parameter is an optional object that contains additional\n * configuration options for creating the `TreeCounter`. It is of type `TreeCounterOptions<K, V,\n * R>`.\n * @returns a new instance of the `TreeCounter` class, with the provided options merged with the\n * existing `iterationType` property. The returned value is casted as `TREE`.\n */\n override createTree(options?: TreeCounterOptions<K, V, R>) {\n return new TreeCounter<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n specifyComparable: this._specifyComparable,\n isMapMode: this._isMapMode,\n toEntryFn: this._toEntryFn,\n ...options\n });\n }\n\n /**\n * The function checks if the input is an instance of the TreeCounterNode class.\n * @param {K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be of type `R` or `K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`.\n * @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is\n * an instance of the `TreeCounterNode` class.\n */\n override isNode(\n keyNodeOrEntry: K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is TreeCounterNode<K, V> {\n return keyNodeOrEntry instanceof TreeCounterNode;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The function overrides the add method of a class and adds a new node to a data structure, updating\n * the count and returning a boolean indicating success.\n * @param {K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The\n * `keyNodeOrEntry` parameter can accept one of the following types:\n * @param {V} [value] - The `value` parameter represents the value associated with the key in the\n * data structure. It is an optional parameter, so it can be omitted if not needed.\n * @param [count=1] - The `count` parameter represents the number of times the key-value pair should\n * be added to the data structure. By default, it is set to 1, meaning that if no value is provided\n * for `count`, the key-value pair will be added once.\n * @returns The method is returning a boolean value. It returns true if the addition of the new node\n * was successful, and false otherwise.\n */\n override add(\n keyNodeOrEntry: K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V,\n count = 1\n ): boolean {\n const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value, count);\n const orgCount = newNode?.count || 0;\n const isSuccessAdded = super.add(newNode, newValue);\n\n if (isSuccessAdded) {\n this._count += orgCount;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The function `delete` in TypeScript overrides the deletion operation in a binary tree data\n * structure, handling cases where nodes have children and maintaining balance in the tree.\n * @param {K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The `predicate`\n * parameter in the `delete` method is used to specify the condition or key based on which a node\n * should be deleted from the binary tree. It can be a key, a node, or an entry.\n * @param [ignoreCount=false] - The `ignoreCount` parameter in the `override delete` method is a\n * boolean flag that determines whether to ignore the count of nodes when performing deletion. If\n * `ignoreCount` is set to `true`, the method will delete the node regardless of its count. If\n * `ignoreCount` is `false\n * @returns The `override delete` method returns an array of `BinaryTreeDeleteResult<TreeCounterNode<K, V>>` objects.\n */\n override delete(\n keyNodeOrEntry: K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n ignoreCount = false\n ): BinaryTreeDeleteResult<TreeCounterNode<K, V>>[] {\n if (keyNodeOrEntry === null) return [];\n\n const results: BinaryTreeDeleteResult<TreeCounterNode<K, V>>[] = [];\n\n let nodeToDelete: OptNode<TreeCounterNode<K, V>>;\n if (this._isPredicate(keyNodeOrEntry)) nodeToDelete = this.getNode(keyNodeOrEntry);\n else nodeToDelete = this.isRealNode(keyNodeOrEntry) ? keyNodeOrEntry : this.getNode(keyNodeOrEntry);\n\n if (!nodeToDelete) {\n return results;\n }\n\n let originalColor = nodeToDelete.color;\n let replacementNode: TreeCounterNode<K, V> | undefined;\n\n if (!this.isRealNode(nodeToDelete.left)) {\n if (nodeToDelete.right !== null) replacementNode = nodeToDelete.right;\n if (ignoreCount || nodeToDelete.count <= 1) {\n if (nodeToDelete.right !== null) {\n this._transplant(nodeToDelete, nodeToDelete.right);\n this._count -= nodeToDelete.count;\n }\n } else {\n nodeToDelete.count--;\n this._count--;\n results.push({ deleted: nodeToDelete, needBalanced: undefined });\n return results;\n }\n } else if (!this.isRealNode(nodeToDelete.right)) {\n replacementNode = nodeToDelete.left;\n if (ignoreCount || nodeToDelete.count <= 1) {\n this._transplant(nodeToDelete, nodeToDelete.left);\n this._count -= nodeToDelete.count;\n } else {\n nodeToDelete.count--;\n this._count--;\n results.push({ deleted: nodeToDelete, needBalanced: undefined });\n return results;\n }\n } else {\n const successor = this.getLeftMost(node => node, nodeToDelete.right);\n if (successor) {\n originalColor = successor.color;\n if (successor.right !== null) replacementNode = successor.right;\n\n if (successor.parent === nodeToDelete) {\n if (this.isRealNode(replacementNode)) {\n replacementNode.parent = successor;\n }\n } else {\n if (ignoreCount || nodeToDelete.count <= 1) {\n if (successor.right !== null) {\n this._transplant(successor, successor.right);\n this._count -= nodeToDelete.count;\n }\n } else {\n nodeToDelete.count--;\n this._count--;\n results.push({ deleted: nodeToDelete, needBalanced: undefined });\n return results;\n }\n successor.right = nodeToDelete.right;\n if (this.isRealNode(successor.right)) {\n successor.right.parent = successor;\n }\n }\n if (ignoreCount || nodeToDelete.count <= 1) {\n this._transplant(nodeToDelete, successor);\n this._count -= nodeToDelete.count;\n } else {\n nodeToDelete.count--;\n this._count--;\n results.push({ deleted: nodeToDelete, needBalanced: undefined });\n return results;\n }\n successor.left = nodeToDelete.left;\n if (this.isRealNode(successor.left)) {\n successor.left.parent = successor;\n }\n successor.color = nodeToDelete.color;\n }\n }\n this._size--;\n\n // If the original color was black, fix the tree\n if (originalColor === 'BLACK') {\n this._deleteFixup(replacementNode);\n }\n\n results.push({ deleted: nodeToDelete, needBalanced: undefined });\n\n return results;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The \"clear\" function overrides the parent class's \"clear\" function and also resets the count to\n * zero.\n */\n override clear() {\n super.clear();\n this._count = 0;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(log n)\n *\n * The `perfectlyBalance` function takes a sorted array of nodes and builds a balanced binary search\n * tree using either a recursive or iterative approach.\n * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that\n * specifies the type of iteration to use when building the balanced binary search tree. It has a\n * default value of `this.iterationType`, which means it will use the iteration type specified by the\n * `iterationType` property of the current object.\n * @returns The function `perfectlyBalance` returns a boolean value. It returns `true` if the\n * balancing operation is successful, and `false` if there are no nodes to balance.\n */\n override perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {\n const sorted = this.dfs(node => node, 'IN'),\n n = sorted.length;\n if (sorted.length < 1) return false;\n\n this.clear();\n\n if (iterationType === 'RECURSIVE') {\n const buildBalanceBST = (l: number, r: number) => {\n if (l > r) return;\n const m = l + Math.floor((r - l) / 2);\n const midNode = sorted[m];\n if (this._isMapMode && midNode !== null) this.add(midNode.key, undefined, midNode.count);\n else if (midNode !== null) this.add(midNode.key, midNode.value, midNode.count);\n buildBalanceBST(l, m - 1);\n buildBalanceBST(m + 1, r);\n };\n\n buildBalanceBST(0, n - 1);\n return true;\n } else {\n const stack: [[number, number]] = [[0, n - 1]];\n while (stack.length > 0) {\n const popped = stack.pop();\n if (popped) {\n const [l, r] = popped;\n if (l <= r) {\n const m = l + Math.floor((r - l) / 2);\n const midNode = sorted[m];\n if (this._isMapMode && midNode !== null) this.add(midNode.key, undefined, midNode.count);\n else if (midNode !== null) this.add(midNode.key, midNode.value, midNode.count);\n stack.push([m + 1, r]);\n stack.push([l, m - 1]);\n }\n }\n }\n return true;\n }\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The function overrides the clone method to create a deep copy of a tree object.\n * @returns The `clone()` method is returning a cloned instance of the `TREE` object.\n */\n override clone() {\n const cloned = this.createTree();\n this.bfs(node => cloned.add(node === null ? null : node.key, undefined, node === null ? 0 : node.count));\n if (this._isMapMode) cloned._store = this._store;\n return cloned;\n }\n\n /**\n * The `map` function in TypeScript overrides the default behavior to create a new TreeCounter with\n * modified entries based on a provided callback.\n * @param callback - The `callback` parameter is a function that will be called for each entry in the\n * map. It takes four arguments:\n * @param [options] - The `options` parameter in the `override map` function is of type\n * `TreeCounterOptions<MK, MV, MR>`. This parameter allows you to provide additional configuration\n * options when creating a new `TreeCounter` instance within the `map` function. These options could\n * include things like\n * @param {any} [thisArg] - The `thisArg` parameter in the `override map` function is used to specify\n * the value of `this` when executing the `callback` function. It allows you to set the context\n * (value of `this`) for the callback function when it is called within the `map` function. This\n * @returns A new TreeCounter instance is being returned, which is populated with entries generated\n * by the provided callback function.\n */\n override map(\n callback: EntryCallback<K, V | undefined, [MK, MV]>,\n options?: TreeCounterOptions<MK, MV, MR>,\n thisArg?: any\n ): TreeCounter<MK, MV, MR> {\n const newTree = new TreeCounter<MK, MV, MR>([], options);\n let index = 0;\n for (const [key, value] of this) {\n newTree.add(callback.call(thisArg, key, value, index++, this));\n }\n return newTree;\n }\n\n /**\n * The function `keyValueNodeEntryRawToNodeAndValue` takes in a key, value, and count and returns a\n * node based on the input.\n * @param {K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be of type `R` or `K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`.\n * @param {V} [value] - The `value` parameter is an optional value that represents the value\n * associated with the key in the node. It is used when creating a new node or updating the value of\n * an existing node.\n * @param [count=1] - The `count` parameter is an optional parameter that specifies the number of\n * times the key-value pair should be added to the data structure. If not provided, it defaults to 1.\n * @returns either a TreeCounterNode<K, V> object or undefined.\n */\n protected override _keyValueNodeOrEntryToNodeAndValue(\n keyNodeOrEntry: K | TreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V,\n count = 1\n ): [TreeCounterNode<K, V> | undefined, V | undefined] {\n if (keyNodeOrEntry === undefined || keyNodeOrEntry === null) return [undefined, undefined];\n\n if (this.isNode(keyNodeOrEntry)) return [keyNodeOrEntry, value];\n\n if (this.isEntry(keyNodeOrEntry)) {\n const [key, entryValue] = keyNodeOrEntry;\n if (key === undefined || key === null) return [undefined, undefined];\n const finalValue = value ?? entryValue;\n return [this.createNode(key, finalValue, 'BLACK', count), finalValue];\n }\n\n return [this.createNode(keyNodeOrEntry, value, 'BLACK', count), value];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_swapProperties` function swaps the properties (key, value, count, color) between two nodes\n * in a binary search tree.\n * @param {R | BSTNOptKeyOrNode<K, TreeCounterNode<K, V>>} srcNode - The `srcNode` parameter represents the source node\n * that will be swapped with the `destNode`. It can be either an instance of the `R` class or an\n * instance of the `BSTNOptKeyOrNode<K, TreeCounterNode<K, V>>` class.\n * @param {R | BSTNOptKeyOrNode<K, TreeCounterNode<K, V>>} destNode - The `destNode` parameter represents the destination\n * node where the properties will be swapped with the source node.\n * @returns The method is returning the `destNode` after swapping its properties with the `srcNode`.\n * If either `srcNode` or `destNode` is undefined, it returns undefined.\n */\n protected override _swapProperties(\n srcNode: BSTNOptKeyOrNode<K, TreeCounterNode<K, V>>,\n destNode: BSTNOptKeyOrNode<K, TreeCounterNode<K, V>>\n ): TreeCounterNode<K, V> | undefined {\n srcNode = this.ensureNode(srcNode);\n destNode = this.ensureNode(destNode);\n if (srcNode && destNode) {\n const { key, value, count, color } = destNode;\n const tempNode = this.createNode(key, value, color, count);\n if (tempNode) {\n tempNode.color = color;\n\n destNode.key = srcNode.key;\n if (!this._isMapMode) destNode.value = srcNode.value;\n destNode.count = srcNode.count;\n destNode.color = srcNode.color;\n\n srcNode.key = tempNode.key;\n if (!this._isMapMode) srcNode.value = tempNode.value;\n srcNode.count = tempNode.count;\n srcNode.color = tempNode.color;\n }\n\n return destNode;\n }\n return undefined;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function replaces an old node with a new node and updates the count property of the new node.\n * @param {TreeCounterNode<K, V>} oldNode - The `oldNode` parameter is the node that you want to replace in the data\n * structure.\n * @param {TreeCounterNode<K, V>} newNode - The `newNode` parameter is an instance of the `TreeCounterNode<K, V>` class.\n * @returns The method is returning the result of calling the `_replaceNode` method from the\n * superclass, which is of type `TreeCounterNode<K, V>`.\n */\n protected override _replaceNode(\n oldNode: TreeCounterNode<K, V>,\n newNode: TreeCounterNode<K, V>\n ): TreeCounterNode<K, V> {\n newNode.count = oldNode.count + newNode.count;\n return super._replaceNode(oldNode, newNode);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type {\n AVLTreeCounterOptions,\n BinaryTreeDeleteResult,\n BSTNOptKeyOrNode,\n EntryCallback,\n IterationType\n} from '../../types';\nimport { IBinaryTree } from '../../interfaces';\nimport { AVLTree, AVLTreeNode } from './avl-tree';\n\nexport class AVLTreeCounterNode<K = any, V = any> extends AVLTreeNode<K, V> {\n override parent?: AVLTreeCounterNode<K, V> = undefined;\n\n /**\n * The constructor function initializes a BinaryTreeNode object with a key, value, and count.\n * @param {K} key - The `key` parameter is of type `K` and represents the unique identifier\n * of the binary tree node.\n * @param {V} [value] - The `value` parameter is an optional parameter of type `V`. It represents the value of the binary\n * tree node. If no value is provided, it will be `undefined`.\n * @param {number} [count=1] - The `count` parameter is a number that represents the number of times a particular value\n * occurs in a binary tree node. It has a default value of 1, which means that if no value is provided for the `count`\n * parameter when creating a new instance of the `BinaryTreeNode` class.\n */\n constructor(key: K, value?: V, count = 1) {\n super(key, value);\n this.count = count;\n }\n\n override _left?: AVLTreeCounterNode<K, V> | null | undefined = undefined;\n\n override get left(): AVLTreeCounterNode<K, V> | null | undefined {\n return this._left;\n }\n\n override set left(v: AVLTreeCounterNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._left = v;\n }\n\n override _right?: AVLTreeCounterNode<K, V> | null | undefined = undefined;\n\n override get right(): AVLTreeCounterNode<K, V> | null | undefined {\n return this._right;\n }\n\n override set right(v: AVLTreeCounterNode<K, V> | null | undefined) {\n if (v) {\n v.parent = this;\n }\n this._right = v;\n }\n}\n\n/**\n * The only distinction between a AVLTreeCounter and a AVLTree lies in the ability of the former to store duplicate nodes through the utilization of counters.\n */\nexport class AVLTreeCounter<K = any, V = any, R = object, MK = any, MV = any, MR = object>\n extends AVLTree<K, V, R, MK, MV, MR>\n implements IBinaryTree<K, V, R, MK, MV, MR>\n{\n /**\n * The constructor initializes a new AVLTreeCounter object with optional initial elements.\n * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter is an\n * iterable object that can contain either keys, nodes, entries, or raw elements.\n * @param [options] - The `options` parameter is an optional object that can be used to customize the\n * behavior of the AVLTreeCounter. It can include properties such as `compareKeys` and\n * `compareValues` functions to define custom comparison logic for keys and values, respectively.\n */\n constructor(\n keysNodesEntriesOrRaws: Iterable<\n K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R\n > = [],\n options?: AVLTreeCounterOptions<K, V, R>\n ) {\n super([], options);\n if (keysNodesEntriesOrRaws) this.addMany(keysNodesEntriesOrRaws);\n }\n\n protected _count = 0;\n\n /**\n * The function calculates the sum of the count property of all nodes in a tree using depth-first\n * search.\n * @returns the sum of the count property of all nodes in the tree.\n */\n get count(): number {\n return this._count;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function calculates the sum of the count property of all nodes in a tree using depth-first\n * search.\n * @returns the sum of the count property of all nodes in the tree.\n */\n getComputedCount(): number {\n let sum = 0;\n this.dfs(node => (sum += node.count));\n return sum;\n }\n\n /**\n * The function creates a new AVLTreeCounterNode with the specified key, value, and count.\n * @param {K} key - The key parameter represents the key of the node being created. It is of type K,\n * which is a generic type that can be replaced with any specific type when using the function.\n * @param {V} [value] - The `value` parameter is an optional parameter that represents the value\n * associated with the key in the node. It is of type `V`, which can be any data type.\n * @param {number} [count] - The `count` parameter represents the number of occurrences of a\n * key-value pair in the AVLTreeCounterNode. It is an optional parameter, so it can be omitted when\n * calling the `createNode` method. If provided, it specifies the initial count for the node.\n * @returns a new instance of the AVLTreeCounterNode class, casted as AVLTreeCounterNode<K, V>.\n */\n override createNode(key: K, value?: V, count?: number): AVLTreeCounterNode<K, V> {\n return new AVLTreeCounterNode(key, this._isMapMode ? undefined : value, count) as AVLTreeCounterNode<K, V>;\n }\n\n /**\n * The function creates a new AVLTreeCounter object with the specified options and returns it.\n * @param [options] - The `options` parameter is an optional object that contains additional\n * configuration options for creating the AVLTreeCounter. It can have the following properties:\n * @returns a new instance of the AVLTreeCounter class, with the specified options, as a TREE\n * object.\n */\n override createTree(options?: AVLTreeCounterOptions<K, V, R>) {\n return new AVLTreeCounter<K, V, R, MK, MV, MR>([], {\n iterationType: this.iterationType,\n isMapMode: this._isMapMode,\n specifyComparable: this._specifyComparable,\n toEntryFn: this._toEntryFn,\n isReverse: this._isReverse,\n ...options\n });\n }\n\n /**\n * The function checks if the input is an instance of AVLTreeCounterNode.\n * @param {K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The parameter\n * `keyNodeOrEntry` can be of type `R` or `K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`.\n * @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is\n * an instance of the `AVLTreeCounterNode` class.\n */\n override isNode(\n keyNodeOrEntry: K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined\n ): keyNodeOrEntry is AVLTreeCounterNode<K, V> {\n return keyNodeOrEntry instanceof AVLTreeCounterNode;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The function overrides the add method of a TypeScript class to add a new node to a data structure\n * and update the count.\n * @param {K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The\n * `keyNodeOrEntry` parameter can accept a value of type `R`, which can be any type. It\n * can also accept a value of type `K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`, which represents a key, node,\n * entry, or raw element\n * @param {V} [value] - The `value` parameter represents the value associated with the key in the\n * data structure. It is an optional parameter, so it can be omitted if not needed.\n * @param [count=1] - The `count` parameter represents the number of times the key-value pair should\n * be added to the data structure. By default, it is set to 1, meaning that the key-value pair will\n * be added once. However, you can specify a different value for `count` if you want to add\n * @returns a boolean value.\n */\n override add(\n keyNodeOrEntry: K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V,\n count = 1\n ): boolean {\n const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value, count);\n if (newNode === undefined) return false;\n\n const orgNodeCount = newNode?.count || 0;\n const inserted = super.add(newNode, newValue);\n if (inserted) {\n this._count += orgNodeCount;\n }\n return true;\n }\n\n /**\n * Time Complexity: O(log n)\n * Space Complexity: O(1)\n *\n * The function overrides the delete method in a binary tree data structure, handling deletion of\n * nodes and maintaining balance in the tree.\n * @param {K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The `predicate`\n * parameter in the `delete` method is used to specify the condition for deleting a node from the\n * binary tree. It can be a key, node, or entry that determines which\n * node(s) should be deleted.\n * @param [ignoreCount=false] - The `ignoreCount` parameter in the `override delete` method is a\n * boolean flag that determines whether to ignore the count of the node being deleted. If\n * `ignoreCount` is set to `true`, the method will delete the node regardless of its count. If\n * `ignoreCount` is set to\n * @returns The `delete` method overrides the default delete behavior in a binary tree data\n * structure. It takes a predicate or node to be deleted and an optional flag to ignore count. The\n * method returns an array of `BinaryTreeDeleteResult` objects, each containing information about the\n * deleted node and whether balancing is needed in the tree.\n */\n override delete(\n keyNodeOrEntry: K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n ignoreCount = false\n ): BinaryTreeDeleteResult<AVLTreeCounterNode<K, V>>[] {\n const deletedResult: BinaryTreeDeleteResult<AVLTreeCounterNode<K, V>>[] = [];\n if (!this.root) return deletedResult;\n\n const curr: AVLTreeCounterNode<K, V> | undefined = this.getNode(keyNodeOrEntry) ?? undefined;\n if (!curr) return deletedResult;\n\n const parent: AVLTreeCounterNode<K, V> | undefined = curr?.parent ? curr.parent : undefined;\n let needBalanced: AVLTreeCounterNode<K, V> | undefined = undefined,\n orgCurrent: AVLTreeCounterNode<K, V> | undefined = curr;\n\n if (curr.count > 1 && !ignoreCount) {\n curr.count--;\n this._count--;\n } else {\n if (!curr.left) {\n if (!parent) {\n if (curr.right !== undefined && curr.right !== null) this._setRoot(curr.right);\n } else {\n const { familyPosition: fp } = curr;\n if (fp === 'LEFT' || fp === 'ROOT_LEFT') {\n parent.left = curr.right;\n } else if (fp === 'RIGHT' || fp === 'ROOT_RIGHT') {\n parent.right = curr.right;\n }\n needBalanced = parent;\n }\n } else {\n const leftSubTreeRightMost = curr.left ? this.getRightMost(node => node, curr.left) : undefined;\n if (leftSubTreeRightMost) {\n const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;\n orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);\n if (parentOfLeftSubTreeMax) {\n if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost) {\n parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;\n } else {\n parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;\n }\n needBalanced = parentOfLeftSubTreeMax;\n }\n }\n }\n this._size = this._size - 1;\n // TODO How to handle when the count of target node is lesser than current node's count\n if (orgCurrent) this._count -= orgCurrent.count;\n }\n\n deletedResult.push({ deleted: orgCurrent, needBalanced });\n\n if (needBalanced) {\n this._balancePath(needBalanced);\n }\n\n return deletedResult;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The \"clear\" function overrides the parent class's \"clear\" function and also resets the count to\n * zero.\n */\n override clear() {\n super.clear();\n this._count = 0;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(log n)\n *\n * The `perfectlyBalance` function takes a sorted array of nodes and builds a balanced binary search\n * tree using either a recursive or iterative approach.\n * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that\n * specifies the type of iteration to use when building the balanced binary search tree. It has a\n * default value of `this.iterationType`, which means it will use the iteration type currently set in\n * the object.\n * @returns The function `perfectlyBalance` returns a boolean value. It returns `true` if the\n * balancing operation is successful, and `false` if there are no nodes to balance.\n */\n override perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {\n const sorted = this.dfs(node => node, 'IN'),\n n = sorted.length;\n if (sorted.length < 1) return false;\n\n this.clear();\n\n if (iterationType === 'RECURSIVE') {\n const buildBalanceBST = (l: number, r: number) => {\n if (l > r) return;\n const m = l + Math.floor((r - l) / 2);\n const midNode = sorted[m];\n if (this._isMapMode) this.add(midNode.key, undefined, midNode.count);\n else this.add(midNode.key, midNode.value, midNode.count);\n buildBalanceBST(l, m - 1);\n buildBalanceBST(m + 1, r);\n };\n\n buildBalanceBST(0, n - 1);\n return true;\n } else {\n const stack: [[number, number]] = [[0, n - 1]];\n while (stack.length > 0) {\n const popped = stack.pop();\n if (popped) {\n const [l, r] = popped;\n if (l <= r) {\n const m = l + Math.floor((r - l) / 2);\n const midNode = sorted[m];\n if (this._isMapMode) this.add(midNode.key, undefined, midNode.count);\n else this.add(midNode.key, midNode.value, midNode.count);\n stack.push([m + 1, r]);\n stack.push([l, m - 1]);\n }\n }\n }\n return true;\n }\n }\n\n /**\n * Time complexity: O(n)\n * Space complexity: O(n)\n *\n * The function overrides the clone method to create a deep copy of a tree object.\n * @returns The `clone()` method is returning a cloned instance of the `TREE` object.\n */\n override clone() {\n const cloned = this.createTree();\n if (this._isMapMode) this.bfs(node => cloned.add(node.key, undefined, node.count));\n else this.bfs(node => cloned.add(node.key, node.value, node.count));\n if (this._isMapMode) cloned._store = this._store;\n return cloned;\n }\n\n /**\n * The `map` function in TypeScript overrides the default behavior to create a new AVLTreeCounter\n * with modified entries based on a provided callback.\n * @param callback - The `callback` parameter is a function that will be called for each entry in the\n * AVLTreeCounter. It takes four arguments:\n * @param [options] - The `options` parameter in the `override map` function is of type\n * `AVLTreeCounterOptions<MK, MV, MR>`. This parameter allows you to provide additional\n * configuration options when creating a new `AVLTreeCounter` instance within the `map` function.\n * These options\n * @param {any} [thisArg] - The `thisArg` parameter in the `override map` function is used to specify\n * the value of `this` when executing the `callback` function. It allows you to set the context\n * (value of `this`) for the callback function. This can be useful when you want to access properties\n * or\n * @returns The `map` method is returning a new `AVLTreeCounter` instance with the entries\n * transformed by the provided `callback` function. Each entry in the original tree is passed to the\n * `callback` function along with the index and the original tree itself. The transformed entries are\n * then added to the new `AVLTreeCounter` instance, which is returned at the end.\n */\n override map<MK, MV, MR>(\n callback: EntryCallback<K, V | undefined, [MK, MV]>,\n options?: AVLTreeCounterOptions<MK, MV, MR>,\n thisArg?: any\n ): AVLTreeCounter<MK, MV, MR> {\n const newTree = new AVLTreeCounter<MK, MV, MR>([], options);\n let index = 0;\n for (const [key, value] of this) {\n newTree.add(callback.call(thisArg, key, value, index++, this));\n }\n return newTree;\n }\n\n /**\n * The function `keyValueNodeEntryRawToNodeAndValue` converts a key, value, entry, or raw element into\n * a node object.\n * @param {K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The\n * `keyNodeOrEntry` parameter can be of type `R` or `K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`.\n * @param {V} [value] - The `value` parameter is an optional value that can be passed to the\n * `override` function. It represents the value associated with the key in the data structure. If no\n * value is provided, it will default to `undefined`.\n * @param [count=1] - The `count` parameter is an optional parameter that specifies the number of\n * times the key-value pair should be added to the data structure. If not provided, it defaults to 1.\n * @returns either a AVLTreeCounterNode<K, V> object or undefined.\n */\n protected override _keyValueNodeOrEntryToNodeAndValue(\n keyNodeOrEntry: K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,\n value?: V,\n count = 1\n ): [AVLTreeCounterNode<K, V> | undefined, V | undefined] {\n if (keyNodeOrEntry === undefined || keyNodeOrEntry === null) return [undefined, undefined];\n if (this.isNode(keyNodeOrEntry)) return [keyNodeOrEntry, value];\n\n if (this.isEntry(keyNodeOrEntry)) {\n const [key, entryValue] = keyNodeOrEntry;\n if (key === undefined || key === null) return [undefined, undefined];\n const finalValue = value ?? entryValue;\n return [this.createNode(key, finalValue, count), finalValue];\n }\n\n return [this.createNode(keyNodeOrEntry, value, count), value];\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The `_swapProperties` function swaps the properties (key, value, count, height) between two nodes\n * in a binary search tree.\n * @param {BSTNOptKeyOrNode<K, AVLTreeCounterNode<K, V>>} srcNode - The `srcNode` parameter represents the source node\n * that will be swapped with the `destNode`.\n * @param {BSTNOptKeyOrNode<K, AVLTreeCounterNode<K, V>>} destNode - The `destNode` parameter represents the destination\n * node where the properties will be swapped with the source node.\n * @returns The method is returning the `destNode` after swapping its properties with the `srcNode`.\n * If either `srcNode` or `destNode` is undefined, it returns `undefined`.\n */\n protected override _swapProperties(\n srcNode: BSTNOptKeyOrNode<K, AVLTreeCounterNode<K, V>>,\n destNode: BSTNOptKeyOrNode<K, AVLTreeCounterNode<K, V>>\n ): AVLTreeCounterNode<K, V> | undefined {\n srcNode = this.ensureNode(srcNode);\n destNode = this.ensureNode(destNode);\n if (srcNode && destNode) {\n const { key, value, count, height } = destNode;\n const tempNode = this.createNode(key, value, count);\n if (tempNode) {\n tempNode.height = height;\n\n destNode.key = srcNode.key;\n if (!this._isMapMode) destNode.value = srcNode.value;\n destNode.count = srcNode.count;\n destNode.height = srcNode.height;\n\n srcNode.key = tempNode.key;\n if (!this._isMapMode) srcNode.value = tempNode.value;\n srcNode.count = tempNode.count;\n srcNode.height = tempNode.height;\n }\n\n return destNode;\n }\n return undefined;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The function replaces an old node with a new node and updates the count property of the new node.\n * @param {AVLTreeCounterNode<K, V>} oldNode - The oldNode parameter represents the node that needs to be replaced in the\n * data structure. It is of type AVLTreeCounterNode<K, V>.\n * @param {AVLTreeCounterNode<K, V>} newNode - The `newNode` parameter is an instance of the `AVLTreeCounterNode<K, V>` class.\n * @returns The method is returning the result of calling the `_replaceNode` method from the\n * superclass, which is of type `AVLTreeCounterNode<K, V>`.\n */\n protected override _replaceNode(\n oldNode: AVLTreeCounterNode<K, V>,\n newNode: AVLTreeCounterNode<K, V>\n ): AVLTreeCounterNode<K, V> {\n newNode.count = oldNode.count + newNode.count;\n return super._replaceNode(oldNode, newNode);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Kirk Qi\n * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>\n * @license MIT License\n */\nimport type { Comparator, ElementCallback, PriorityQueueOptions } from '../../types';\nimport { Heap } from '../heap';\n\n/**\n * 1. Element Priority: In a PriorityQueue, elements are sorted according to their priority. Each dequeue (element removal) operation removes the element with the highest priority. The priority can be determined based on the natural ordering of the elements or through a provided comparator (Comparator).\n * 2. Heap-Based Implementation: PriorityQueue is typically implemented using a binary heap, allowing both insertion and removal operations to be completed in O(log n) time, where n is the number of elements in the queue.\n * 3. Task Scheduling: In systems where tasks need to be processed based on the urgency of tasks rather than the order of arrival.\n * 4. Dijkstra's Algorithm: In shortest path algorithms for graphs, used to select the next shortest edge to visit.\n * 5. Huffman Coding: Used to select the smallest node combination when constructing a Huffman tree.\n * 6. Kth Largest Element in a Data Stream: Used to maintain a min-heap of size K for quickly finding the Kth largest element in stream data\n */\nexport class PriorityQueue<E = any, R = any> extends Heap<E, R> {\n /**\n * The constructor initializes a priority queue with optional elements and options.\n * @param elements - The `elements` parameter is an iterable object that contains the initial\n * elements to be added to the priority queue. It is an optional parameter, and if not provided, the\n * priority queue will be initialized as empty.\n * @param [options] - The `options` parameter is an optional object that can be used to customize the\n * behavior of the priority queue. It can contain the following properties:\n */\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: PriorityQueueOptions<E, R>) {\n super(elements, options);\n }\n\n /**\n * The `clone` function returns a new instance of the `PriorityQueue` class with the same comparator\n * and toElementFn as the original instance.\n * @returns The method is returning a new instance of the `PriorityQueue` class with the same\n * elements and properties as the current instance.\n */\n override clone(): PriorityQueue<E, R> {\n return new PriorityQueue<E, R>(this, { comparator: this.comparator, toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new PriorityQueue object containing elements that pass a given callback\n * function.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: the current element, the index of the current element, and the\n * heap itself. The callback function should return a boolean value indicating whether the current\n * element should be included in the filtered list\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `PriorityQueue` object that contains the elements that pass\n * the filter condition specified by the `callback` function.\n */\n override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): PriorityQueue<E, R> {\n const filteredPriorityQueue = new PriorityQueue<E, R>([], {\n toElementFn: this.toElementFn,\n comparator: this.comparator\n });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredPriorityQueue.add(current);\n }\n index++;\n }\n return filteredPriorityQueue;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * The `map` function creates a new heap by applying a callback function to each element of the\n * original heap.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: `el` (the current element), `index` (the index of the current\n * element), and `this` (the heap itself). The callback function should return a value of\n * @param comparator - The `comparator` parameter is a function that defines the order of the\n * elements in the heap. It takes two elements `a` and `b` as arguments and returns a negative number\n * if `a` should be placed before `b`, a positive number if `a` should be placed after\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that converts the raw\n * element `RR` to the desired type `T`. It takes a single argument `rawElement` of type `RR` and\n * returns a value of type `T`. This function is used to transform the elements of the original\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `PriorityQueue` class with the mapped elements.\n */\n override map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n comparator: Comparator<EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): PriorityQueue<EM, RM> {\n const mappedPriorityQueue: PriorityQueue<EM, RM> = new PriorityQueue<EM, RM>([], { comparator, toElementFn });\n let index = 0;\n for (const el of this) {\n mappedPriorityQueue.add(callback.call(thisArg, el, index, this));\n index++;\n }\n return mappedPriorityQueue;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Kirk Qi\n * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>\n * @license MIT License\n */\nimport type { Comparator, ElementCallback, PriorityQueueOptions } from '../../types';\nimport { PriorityQueue } from './priority-queue';\n\n/**\n *\n */\nexport class MinPriorityQueue<E = any, R = any> extends PriorityQueue<E, R> {\n /**\n * The constructor initializes a PriorityQueue with optional elements and options, including a\n * comparator function.\n * @param elements - The `elements` parameter is an iterable object that contains the initial\n * elements to be added to the priority queue. It is optional and defaults to an empty array if not\n * provided.\n * @param options - The `options` parameter is an object that contains additional configuration\n * options for the priority queue. In this case, it has a property called `comparator,` which is a\n * function used to compare elements in the priority queue. The `comparator` function takes two\n * parameters `a` and `b`\n */\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: PriorityQueueOptions<E, R>) {\n super(elements, options);\n }\n\n /**\n * The `clone` function returns a new instance of the `MinPriorityQueue` class with the same\n * comparator and toElementFn as the original instance.\n * @returns The method is returning a new instance of the `MinPriorityQueue` class with the same\n * properties as the current instance.\n */\n override clone(): MinPriorityQueue<E, R> {\n return new MinPriorityQueue<E, R>(this, { comparator: this.comparator, toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new MinPriorityQueue object containing elements that pass a given callback\n * function.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: the current element, the index of the current element, and the\n * heap itself. The callback function should return a boolean value indicating whether the current\n * element should be included in the filtered list\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `MinPriorityQueue` object that contains the elements that pass\n * the filter condition specified by the `callback` function.\n */\n override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): MinPriorityQueue<E, R> {\n const filteredPriorityQueue = new MinPriorityQueue<E, R>([], {\n toElementFn: this.toElementFn,\n comparator: this.comparator\n });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredPriorityQueue.add(current);\n }\n index++;\n }\n return filteredPriorityQueue;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * The `map` function creates a new heap by applying a callback function to each element of the\n * original heap.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: `el` (the current element), `index` (the index of the current\n * element), and `this` (the heap itself). The callback function should return a value of\n * @param comparator - The `comparator` parameter is a function that defines the order of the\n * elements in the heap. It takes two elements `a` and `b` as arguments and returns a negative number\n * if `a` should be placed before `b`, a positive number if `a` should be placed after\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that converts the raw\n * element `RR` to the desired type `T`. It takes a single argument `rawElement` of type `RR` and\n * returns a value of type `T`. This function is used to transform the elements of the original\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `MinPriorityQueue` class with the mapped elements.\n */\n override map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n comparator: Comparator<EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): MinPriorityQueue<EM, RM> {\n const mappedPriorityQueue: MinPriorityQueue<EM, RM> = new MinPriorityQueue<EM, RM>([], { comparator, toElementFn });\n let index = 0;\n for (const el of this) {\n mappedPriorityQueue.add(callback.call(thisArg, el, index, this));\n index++;\n }\n return mappedPriorityQueue;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Kirk Qi\n * @copyright Copyright (c) 2022 Kirk Qi <qilinaus@gmail.com>\n * @license MIT License\n */\nimport type { Comparator, ElementCallback, PriorityQueueOptions } from '../../types';\nimport { PriorityQueue } from './priority-queue';\n\n/**\n *\n */\nexport class MaxPriorityQueue<E = any, R = any> extends PriorityQueue<E, R> {\n /**\n * The constructor initializes a PriorityQueue with optional elements and options, including a\n * comparator function.\n * @param elements - The `elements` parameter is an iterable object that contains the initial\n * elements to be added to the priority queue. It is optional and defaults to an empty array if not\n * provided.\n * @param options - The `options` parameter is an object that contains additional configuration\n * options for the priority queue. In this case, it has a property called `comparator,` which is a\n * function used to compare elements in the priority queue.\n */\n constructor(elements: Iterable<E> | Iterable<R> = [], options?: PriorityQueueOptions<E, R>) {\n super(elements, {\n comparator: (a: E, b: E): number => {\n if (typeof a === 'object' || typeof b === 'object') {\n throw TypeError(\n `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`\n );\n }\n if (a < b) return 1;\n if (a > b) return -1;\n return 0;\n },\n ...options\n });\n }\n\n /**\n * The `clone` function returns a new instance of the `MaxPriorityQueue` class with the same\n * comparator and toElementFn as the current instance.\n * @returns The method is returning a new instance of the MaxPriorityQueue class with the same\n * comparator and toElementFn as the current instance.\n */\n override clone(): MaxPriorityQueue<E, R> {\n return new MaxPriorityQueue<E, R>(this, { comparator: this.comparator, toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function creates a new MaxPriorityQueue object containing elements that pass a given callback\n * function.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: the current element, the index of the current element, and the\n * heap itself. The callback function should return a boolean value indicating whether the current\n * element should be included in the filtered list\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value\n * to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be\n * passed as the `this` value to the `callback` function. If `thisArg` is\n * @returns The `filter` method is returning a new `MaxPriorityQueue` object that contains the elements that pass\n * the filter condition specified by the `callback` function.\n */\n override filter(callback: ElementCallback<E, R, boolean>, thisArg?: any): MaxPriorityQueue<E, R> {\n const filteredPriorityQueue = new MaxPriorityQueue<E, R>([], {\n toElementFn: this.toElementFn,\n comparator: this.comparator\n });\n let index = 0;\n for (const current of this) {\n if (callback.call(thisArg, current, index, this)) {\n filteredPriorityQueue.add(current);\n }\n index++;\n }\n return filteredPriorityQueue;\n }\n\n /**\n * Time Complexity: O(n log n)\n * Space Complexity: O(n)\n *\n * The `map` function creates a new heap by applying a callback function to each element of the\n * original heap.\n * @param callback - The `callback` parameter is a function that will be called for each element in\n * the heap. It takes three arguments: `el` (the current element), `index` (the index of the current\n * element), and `this` (the heap itself). The callback function should return a value of\n * @param comparator - The `comparator` parameter is a function that defines the order of the\n * elements in the heap. It takes two elements `a` and `b` as arguments and returns a negative number\n * if `a` should be placed before `b`, a positive number if `a` should be placed after\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that converts the raw\n * element `RR` to the desired type `T`. It takes a single argument `rawElement` of type `RR` and\n * returns a value of type `T`. This function is used to transform the elements of the original\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new instance of the `MaxPriorityQueue` class with the mapped elements.\n */\n override map<EM, RM>(\n callback: ElementCallback<E, R, EM>,\n comparator: Comparator<EM>,\n toElementFn?: (rawElement: RM) => EM,\n thisArg?: any\n ): MaxPriorityQueue<EM, RM> {\n const mappedPriorityQueue = new MaxPriorityQueue<EM, RM>([], { comparator, toElementFn });\n let index = 0;\n for (const el of this) {\n mappedPriorityQueue.add(callback.call(thisArg, el, index, this));\n index++;\n }\n return mappedPriorityQueue;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { MatrixOptions } from '../../types';\n\n/**\n *\n */\nexport class Matrix {\n /**\n * The constructor function initializes a matrix object with the provided data and options, or with\n * default values if no options are provided.\n * @param {number[][]} data - A 2D array of numbers representing the data for the matrix.\n * @param [options] - The `options` parameter is an optional object that can contain the following\n * properties:\n */\n constructor(data: number[][], options?: MatrixOptions) {\n if (options) {\n const { rows, cols, addFn, subtractFn, multiplyFn } = options;\n if (typeof rows === 'number' && rows > 0) this._rows = rows;\n else this._rows = data.length;\n if (typeof cols === 'number' && cols > 0) this._cols = cols;\n else this._cols = data[0]?.length || 0;\n if (addFn) this._addFn = addFn;\n if (subtractFn) this._subtractFn = subtractFn;\n if (multiplyFn) this._multiplyFn = multiplyFn;\n } else {\n this._rows = data.length;\n this._cols = data[0]?.length ?? 0;\n }\n\n if (data.length > 0) {\n this._data = data;\n } else {\n this._data = [];\n for (let i = 0; i < this.rows; i++) {\n this._data[i] = new Array(this.cols).fill(0);\n }\n }\n }\n\n protected _rows: number = 0;\n\n /**\n * The function returns the number of rows.\n * @returns The number of rows.\n */\n get rows(): number {\n return this._rows;\n }\n\n protected _cols: number = 0;\n\n /**\n * The function returns the value of the protected variable _cols.\n * @returns The number of columns.\n */\n get cols(): number {\n return this._cols;\n }\n\n protected _data: number[][];\n\n /**\n * The function returns a two-dimensional array of numbers.\n * @returns The data property, which is a two-dimensional array of numbers.\n */\n get data(): number[][] {\n return this._data;\n }\n\n /**\n * The above function returns the value of the _addFn property.\n * @returns The value of the property `_addFn` is being returned.\n */\n get addFn() {\n return this._addFn;\n }\n\n /**\n * The function returns the value of the _subtractFn property.\n * @returns The `_subtractFn` property is being returned.\n */\n get subtractFn() {\n return this._subtractFn;\n }\n\n /**\n * The function returns the value of the _multiplyFn property.\n * @returns The `_multiplyFn` property is being returned.\n */\n get multiplyFn() {\n return this._multiplyFn;\n }\n\n /**\n * The `get` function returns the value at the specified row and column index if it is a valid index.\n * @param {number} row - The `row` parameter represents the row index of the element you want to\n * retrieve from the data array.\n * @param {number} col - The parameter \"col\" represents the column number of the element you want to\n * retrieve from the data array.\n * @returns The `get` function returns a number if the provided row and column indices are valid.\n * Otherwise, it returns `undefined`.\n */\n get(row: number, col: number): number | undefined {\n if (this.isValidIndex(row, col)) {\n return this.data[row][col];\n }\n }\n\n /**\n * The set function updates the value at a specified row and column in a two-dimensional array.\n * @param {number} row - The \"row\" parameter represents the row index of the element in a\n * two-dimensional array or matrix. It specifies the row where the value will be set.\n * @param {number} col - The \"col\" parameter represents the column index of the element in a\n * two-dimensional array.\n * @param {number} value - The value parameter represents the number that you want to set at the\n * specified row and column in the data array.\n * @returns a boolean value. It returns true if the index (row, col) is valid and the value is\n * successfully set in the data array. It returns false if the index is invalid and the value is not\n * set.\n */\n set(row: number, col: number, value: number): boolean {\n if (this.isValidIndex(row, col)) {\n this.data[row][col] = value;\n return true;\n }\n return false;\n }\n\n /**\n * The function checks if the dimensions of the given matrix match the dimensions of the current\n * matrix.\n * @param {Matrix} matrix - The parameter `matrix` is of type `Matrix`.\n * @returns a boolean value.\n */\n isMatchForCalculate(matrix: Matrix): boolean {\n return this.rows === matrix.rows && this.cols === matrix.cols;\n }\n\n /**\n * The `add` function adds two matrices together, returning a new matrix with the result.\n * @param {Matrix} matrix - The `matrix` parameter is an instance of the `Matrix` class.\n * @returns The `add` method returns a new `Matrix` object that represents the result of adding the\n * current matrix with the provided `matrix` parameter.\n */\n add(matrix: Matrix): Matrix | undefined {\n if (!this.isMatchForCalculate(matrix)) {\n throw new Error('Matrix dimensions must match for addition.');\n }\n\n const resultData: number[][] = [];\n for (let i = 0; i < this.rows; i++) {\n resultData[i] = [];\n for (let j = 0; j < this.cols; j++) {\n const a = this.get(i, j),\n b = matrix.get(i, j);\n if (a !== undefined && b !== undefined) {\n const added = this._addFn(a, b);\n if (added) {\n resultData[i][j] = added;\n }\n }\n }\n }\n\n return new Matrix(resultData, {\n rows: this.rows,\n cols: this.cols,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n }\n\n /**\n * The `subtract` function performs element-wise subtraction between two matrices and returns a new\n * matrix with the result.\n * @param {Matrix} matrix - The `matrix` parameter is an instance of the `Matrix` class. It\n * represents the matrix that you want to subtract from the current matrix.\n * @returns a new Matrix object with the result of the subtraction operation.\n */\n subtract(matrix: Matrix): Matrix | undefined {\n if (!this.isMatchForCalculate(matrix)) {\n throw new Error('Matrix dimensions must match for subtraction.');\n }\n\n const resultData: number[][] = [];\n for (let i = 0; i < this.rows; i++) {\n resultData[i] = [];\n for (let j = 0; j < this.cols; j++) {\n const a = this.get(i, j),\n b = matrix.get(i, j);\n if (a !== undefined && b !== undefined) {\n const subtracted = this._subtractFn(a, b);\n if (subtracted) {\n resultData[i][j] = subtracted;\n }\n }\n }\n }\n\n return new Matrix(resultData, {\n rows: this.rows,\n cols: this.cols,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n }\n\n /**\n * The `multiply` function performs matrix multiplication between two matrices and returns the result\n * as a new matrix.\n * @param {Matrix} matrix - The `matrix` parameter is an instance of the `Matrix` class.\n * @returns a new Matrix object.\n */\n multiply(matrix: Matrix): Matrix | undefined {\n if (this.cols !== matrix.rows) {\n throw new Error('Matrix dimensions must be compatible for multiplication (A.cols = B.rows).');\n }\n\n const resultData: number[][] = [];\n for (let i = 0; i < this.rows; i++) {\n resultData[i] = [];\n for (let j = 0; j < matrix.cols; j++) {\n let sum: number | undefined;\n for (let k = 0; k < this.cols; k++) {\n const a = this.get(i, k),\n b = matrix.get(k, j);\n if (a !== undefined && b !== undefined) {\n const multiplied = this.multiplyFn(a, b);\n if (multiplied !== undefined) {\n sum = this.addFn(sum, multiplied);\n }\n }\n }\n if (sum !== undefined) resultData[i][j] = sum;\n }\n }\n\n return new Matrix(resultData, {\n rows: this.rows,\n cols: matrix.cols,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n }\n\n /**\n * The transpose function takes a matrix and returns a new matrix that is the transpose of the\n * original matrix.\n * @returns The transpose() function returns a new Matrix object with the transposed data.\n */\n transpose(): Matrix {\n if (this.data.some(row => row.length !== this.rows)) {\n throw new Error('Matrix must be rectangular for transposition.');\n }\n\n const resultData: number[][] = [];\n\n for (let j = 0; j < this.cols; j++) {\n resultData[j] = [];\n for (let i = 0; i < this.rows; i++) {\n const trans = this.get(i, j);\n if (trans !== undefined) resultData[j][i] = trans;\n }\n }\n\n return new Matrix(resultData, {\n rows: this.cols,\n cols: this.rows,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n }\n\n /**\n * The `inverse` function calculates the inverse of a square matrix using Gaussian elimination.\n * @returns a Matrix object, which represents the inverse of the original matrix.\n */\n inverse(): Matrix | undefined {\n // Check if the matrix is square\n if (this.rows !== this.cols) {\n throw new Error('Matrix must be square for inversion.');\n }\n\n // Create an augmented matrix [this | I]\n const augmentedMatrixData: number[][] = [];\n for (let i = 0; i < this.rows; i++) {\n augmentedMatrixData[i] = this.data[i].slice(); // Copy the original matrix\n for (let j = 0; j < this.cols; j++) {\n augmentedMatrixData[i][this.cols + j] = i === j ? 1 : 0; // Append the identity matrix\n }\n }\n\n const augmentedMatrix = new Matrix(augmentedMatrixData, {\n rows: this.rows,\n cols: this.cols * 2,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n\n // Apply Gaussian elimination to transform the left half into the identity matrix\n for (let i = 0; i < this.rows; i++) {\n // Find pivot\n let pivotRow = i;\n while (pivotRow < this.rows && augmentedMatrix.get(pivotRow, i) === 0) {\n pivotRow++;\n }\n\n if (pivotRow === this.rows) {\n // Matrix is singular, and its inverse does not exist\n throw new Error('Matrix is singular, and its inverse does not exist.');\n }\n\n // Swap rows to make the pivot the current row\n augmentedMatrix._swapRows(i, pivotRow);\n\n // Scale the pivot row to make the pivot element 1\n const pivotElement = augmentedMatrix.get(i, i) ?? 1;\n\n if (pivotElement === 0) {\n // Handle division by zero\n throw new Error('Matrix is singular, and its inverse does not exist (division by zero).');\n }\n\n augmentedMatrix._scaleRow(i, 1 / pivotElement);\n\n // Eliminate other rows to make elements in the current column zero\n for (let j = 0; j < this.rows; j++) {\n if (j !== i) {\n let factor = augmentedMatrix.get(j, i);\n if (factor === undefined) factor = 0;\n\n augmentedMatrix._addScaledRow(j, i, -factor);\n }\n }\n }\n\n // Extract the right half of the augmented matrix as the inverse\n const inverseData: number[][] = [];\n for (let i = 0; i < this.rows; i++) {\n inverseData[i] = augmentedMatrix.data[i].slice(this.cols);\n }\n\n return new Matrix(inverseData, {\n rows: this.rows,\n cols: this.cols,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n }\n\n /**\n * The dot function calculates the dot product of two matrices and returns a new matrix.\n * @param {Matrix} matrix - The `matrix` parameter is an instance of the `Matrix` class.\n * @returns a new Matrix object.\n */\n dot(matrix: Matrix): Matrix | undefined {\n if (this.cols !== matrix.rows) {\n throw new Error(\n 'Number of columns in the first matrix must be equal to the number of rows in the second matrix for dot product.'\n );\n }\n\n const resultData: number[][] = [];\n for (let i = 0; i < this.rows; i++) {\n resultData[i] = [];\n for (let j = 0; j < matrix.cols; j++) {\n let sum: number | undefined;\n for (let k = 0; k < this.cols; k++) {\n const a = this.get(i, k),\n b = matrix.get(k, j);\n if (a !== undefined && b !== undefined) {\n const multiplied = this.multiplyFn(a, b);\n if (multiplied !== undefined) {\n sum = this.addFn(sum, multiplied);\n }\n }\n }\n if (sum !== undefined) resultData[i][j] = sum;\n }\n }\n\n return new Matrix(resultData, {\n rows: this.rows,\n cols: matrix.cols,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n }\n\n /**\n * The function checks if a given row and column index is valid within a specified range.\n * @param {number} row - The `row` parameter represents the row index of a two-dimensional array or\n * matrix. It is a number that indicates the specific row in the matrix.\n * @param {number} col - The \"col\" parameter represents the column index in a two-dimensional array\n * or grid. It is used to check if the given column index is valid within the bounds of the grid.\n * @returns A boolean value is being returned.\n */\n isValidIndex(row: number, col: number): boolean {\n return row >= 0 && row < this.rows && col >= 0 && col < this.cols;\n }\n\n /**\n * The `clone` function returns a new instance of the Matrix class with the same data and properties\n * as the original instance.\n * @returns The `clone()` method is returning a new instance of the `Matrix` class with the same data\n * and properties as the current instance.\n */\n clone(): Matrix {\n return new Matrix(this.data, {\n rows: this.rows,\n cols: this.cols,\n addFn: this.addFn,\n subtractFn: this.subtractFn,\n multiplyFn: this.multiplyFn\n });\n }\n\n protected _addFn(a: number | undefined, b: number): number | undefined {\n if (a === undefined) return b;\n return a + b;\n }\n\n protected _subtractFn(a: number, b: number) {\n return a - b;\n }\n\n protected _multiplyFn(a: number, b: number) {\n return a * b;\n }\n\n /**\n * The function `_swapRows` swaps the positions of two rows in an array.\n * @param {number} row1 - The `row1` parameter is the index of the first row that you want to swap.\n * @param {number} row2 - The `row2` parameter is the index of the second row that you want to swap\n * with the first row.\n */\n protected _swapRows(row1: number, row2: number): void {\n const temp = this.data[row1];\n this.data[row1] = this.data[row2];\n this.data[row2] = temp;\n }\n\n /**\n * The function scales a specific row in a matrix by a given scalar value.\n * @param {number} row - The `row` parameter represents the index of the row in the matrix that you\n * want to scale. It is a number that indicates the position of the row within the matrix.\n * @param {number} scalar - The scalar parameter is a number that is used to multiply each element in\n * a specific row of a matrix.\n */\n protected _scaleRow(row: number, scalar: number): void {\n for (let j = 0; j < this.cols; j++) {\n let multiplied = this.multiplyFn(this.data[row][j], scalar);\n if (multiplied === undefined) multiplied = 0;\n this.data[row][j] = multiplied;\n }\n }\n\n /**\n * The function `_addScaledRow` multiplies a row in a matrix by a scalar value and adds it to another\n * row.\n * @param {number} targetRow - The targetRow parameter represents the index of the row in which the\n * scaled values will be added.\n * @param {number} sourceRow - The sourceRow parameter represents the index of the row from which the\n * values will be scaled and added to the targetRow.\n * @param {number} scalar - The scalar parameter is a number that is used to scale the values in the\n * source row before adding them to the target row.\n */\n protected _addScaledRow(targetRow: number, sourceRow: number, scalar: number): void {\n for (let j = 0; j < this.cols; j++) {\n let multiplied = this.multiplyFn(this.data[sourceRow][j], scalar);\n if (multiplied === undefined) multiplied = 0;\n const scaledValue = multiplied;\n let added = this.addFn(this.data[targetRow][j], scaledValue);\n if (added === undefined) added = 0;\n this.data[targetRow][j] = added;\n }\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { Direction, NavigatorParams, Turning } from '../../types';\n\nexport class Character {\n direction: Direction;\n turn: () => Character;\n\n /**\n * The constructor function takes in a direction and turning object and sets the direction and turn properties of the\n * Character class.\n * @param {Direction} direction - The direction parameter is used to specify the current direction of the character. It\n * can be any value that represents a direction, such as \"north\", \"south\", \"east\", or \"west\".\n * @param {Turning} turning - The `turning` parameter is an object that maps each direction to the corresponding\n * turning direction. It is used to determine the new direction when the character turns.\n */\n constructor(direction: Direction, turning: Turning) {\n this.direction = direction;\n this.turn = () => new Character(turning[direction], turning);\n }\n}\n\n/**\n *\n */\nexport class Navigator<T = number> {\n onMove: (cur: [number, number]) => void;\n protected readonly _matrix: T[][];\n protected readonly _cur: [number, number];\n protected _character: Character;\n protected readonly _VISITED: T;\n\n /**\n * The constructor initializes the Navigator object with the given parameters and sets the current position as visited\n * in the matrix.\n * @param - - `matrix`: a 2D array representing the grid or map\n */\n constructor({ matrix, turning, onMove, init: { cur, charDir, VISITED } }: NavigatorParams<T>) {\n this._matrix = matrix;\n this._cur = cur;\n this._character = new Character(charDir, turning);\n this.onMove = onMove;\n if (this.onMove) this.onMove(this._cur);\n this._VISITED = VISITED;\n this._matrix[this._cur[0]][this._cur[1]] = this._VISITED;\n }\n\n /**\n * The \"start\" function moves the character in its current direction until it encounters an obstacle, then it turns the\n * character and repeats the process.\n */\n start() {\n while (this.check(this._character.direction) || this.check(this._character.turn().direction)) {\n const { direction } = this._character;\n if (this.check(direction)) {\n this.move(direction);\n } else if (this.check(this._character.turn().direction)) {\n this._character = this._character.turn();\n }\n }\n }\n\n /**\n * The function checks if there is a valid move in the specified direction in a matrix.\n * @param {Direction} direction - The direction parameter is a string that represents the direction in which to check.\n * It can be one of the following values: 'up', 'right', 'down', or 'left'.\n * @returns a boolean value.\n */\n check(direction: Direction) {\n let forward: T | undefined, row: T[] | undefined;\n const matrix = this._matrix;\n const [i, j] = this._cur;\n switch (direction) {\n case 'up':\n row = matrix[i - 1];\n if (!row) return false;\n forward = row[j];\n break;\n case 'right':\n forward = matrix[i][j + 1];\n break;\n case 'down':\n row = matrix[i + 1];\n if (!row) return false;\n forward = row[j];\n break;\n case 'left':\n forward = matrix[i][j - 1];\n break;\n }\n return forward !== undefined && forward !== this._VISITED;\n }\n\n /**\n * The `move` function updates the current position based on the given direction and updates the matrix accordingly.\n * @param {Direction} direction - The `direction` parameter is a string that represents the direction in which to move.\n * It can have one of the following values: 'up', 'right', 'down', or 'left'.\n */\n move(direction: Direction) {\n switch (direction) {\n case 'up':\n this._cur[0]--;\n break;\n case 'right':\n this._cur[1]++;\n break;\n case 'down':\n this._cur[0]++;\n break;\n case 'left':\n this._cur[1]--;\n break;\n }\n\n const [i, j] = this._cur;\n this._matrix[i][j] = this._VISITED;\n if (this.onMove) this.onMove(this._cur);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Pablo Zeng\n * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type { ElementCallback, TrieOptions } from '../../types';\nimport { IterableElementBase } from '../base';\n\nexport class TrieNode {\n constructor(key: string) {\n this._key = key;\n this._isEnd = false;\n this._children = new Map<string, TrieNode>();\n }\n\n protected _key: string;\n\n /**\n * The function returns the value of the protected variable _key.\n * @returns The value of the `_key` property, which is a string.\n */\n get key(): string {\n return this._key;\n }\n\n /**\n * The above function sets the value of a protected variable called \"key\".\n * @param {string} value - The value parameter is a string that represents the value to be assigned\n * to the key.\n */\n set key(value: string) {\n this._key = value;\n }\n\n protected _children: Map<string, TrieNode>;\n\n /**\n * The function returns the children of a TrieNode as a Map.\n * @returns The `children` property of the TrieNode object, which is a Map containing string keys and\n * TrieNode values.\n */\n get children(): Map<string, TrieNode> {\n return this._children;\n }\n\n /**\n * The function sets the value of the `_children` property of a TrieNode object.\n * @param value - The value parameter is a Map object that represents the children of a TrieNode. The\n * keys of the map are strings, which represent the characters that are associated with each child\n * TrieNode. The values of the map are TrieNode objects, which represent the child nodes of the\n * current TrieNode.\n */\n set children(value: Map<string, TrieNode>) {\n this._children = value;\n }\n\n protected _isEnd: boolean;\n\n /**\n * The function returns a boolean value indicating whether a certain condition is met.\n * @returns The method is returning a boolean value, specifically the value of the variable `_isEnd`.\n */\n get isEnd(): boolean {\n return this._isEnd;\n }\n\n /**\n * The function sets the value of the \"_isEnd\" property.\n * @param {boolean} value - The value parameter is a boolean value that indicates whether the current\n * state is the end state or not.\n */\n set isEnd(value: boolean) {\n this._isEnd = value;\n }\n}\n\n/**\n * 1. Node Structure: Each node in a Trie represents a string (or a part of a string). The root node typically represents an empty string.\n * 2. Child Node Relationship: Each node's children represent the strings that can be formed by adding one character to the string at the current node. For example, if a node represents the string 'ca', one of its children might represent 'cat'.\n * 3. Fast Retrieval: Trie allows retrieval in O(m) time complexity, where m is the length of the string to be searched.\n * 4. Space Efficiency: Trie can store a large number of strings very space-efficiently, especially when these strings share common prefixes.\n * 5. Autocomplete and Prediction: Trie can be used for implementing autocomplete and word prediction features, as it can quickly find all strings with a common prefix.\n * 6. Sorting: Trie can be used to sort a set of strings in alphabetical order.\n * 7. String Retrieval: For example, searching for a specific string in a large set of strings.\n * 8. Autocomplete: Providing recommended words or phrases as a user types.\n * 9. Spell Check: Checking the spelling of words.\n * 10. IP Routing: Used in certain types of IP routing algorithms.\n * 11. Text Word Frequency Count: Counting and storing the frequency of words in a large amount of text data.\n * @example\n * // Autocomplete: Prefix validation and checking\n * const autocomplete = new Trie<string>(['gmail.com', 'gmail.co.nz', 'gmail.co.jp', 'yahoo.com', 'outlook.com']);\n *\n * // Get all completions for a prefix\n * const gmailCompletions = autocomplete.getWords('gmail');\n * console.log(gmailCompletions); // ['gmail.com', 'gmail.co.nz', 'gmail.co.jp']\n * @example\n * // File System Path Operations\n * const fileSystem = new Trie<string>([\n * '/home/user/documents/file1.txt',\n * '/home/user/documents/file2.txt',\n * '/home/user/pictures/photo.jpg',\n * '/home/user/pictures/vacation/',\n * '/home/user/downloads'\n * ]);\n *\n * // Find common directory prefix\n * console.log(fileSystem.getLongestCommonPrefix()); // '/home/user/'\n *\n * // List all files in a directory\n * const documentsFiles = fileSystem.getWords('/home/user/documents/');\n * console.log(documentsFiles); // ['/home/user/documents/file1.txt', '/home/user/documents/file2.txt']\n * @example\n * // Autocomplete: Basic word suggestions\n * // Create a trie for autocomplete\n * const autocomplete = new Trie<string>([\n * 'function',\n * 'functional',\n * 'functions',\n * 'class',\n * 'classes',\n * 'classical',\n * 'closure',\n * 'const',\n * 'constructor'\n * ]);\n *\n * // Test autocomplete with different prefixes\n * console.log(autocomplete.getWords('fun')); // ['functional', 'functions', 'function']\n * console.log(autocomplete.getWords('cla')); // ['classes', 'classical', 'class']\n * console.log(autocomplete.getWords('con')); // ['constructor', 'const']\n *\n * // Test with non-matching prefix\n * console.log(autocomplete.getWords('xyz')); // []\n * @example\n * // Dictionary: Case-insensitive word lookup\n * // Create a case-insensitive dictionary\n * const dictionary = new Trie<string>([], { caseSensitive: false });\n *\n * // Add words with mixed casing\n * dictionary.add('Hello');\n * dictionary.add('WORLD');\n * dictionary.add('JavaScript');\n *\n * // Test lookups with different casings\n * console.log(dictionary.has('hello')); // true\n * console.log(dictionary.has('HELLO')); // true\n * console.log(dictionary.has('Hello')); // true\n * console.log(dictionary.has('javascript')); // true\n * console.log(dictionary.has('JAVASCRIPT')); // true\n * @example\n * // IP Address Routing Table\n * // Add IP address prefixes and their corresponding routes\n * const routes = {\n * '192.168.1': 'LAN_SUBNET_1',\n * '192.168.2': 'LAN_SUBNET_2',\n * '10.0.0': 'PRIVATE_NETWORK_1',\n * '10.0.1': 'PRIVATE_NETWORK_2'\n * };\n *\n * const ipRoutingTable = new Trie<string>(Object.keys(routes));\n *\n * // Check IP address prefix matching\n * console.log(ipRoutingTable.hasPrefix('192.168.1')); // true\n * console.log(ipRoutingTable.hasPrefix('192.168.2')); // true\n *\n * // Validate IP address belongs to subnet\n * const ip = '192.168.1.100';\n * const subnet = ip.split('.').slice(0, 3).join('.');\n * console.log(ipRoutingTable.hasPrefix(subnet)); // true\n */\nexport class Trie<R = any> extends IterableElementBase<string, R> {\n /**\n * The constructor initializes a Trie data structure with optional options and words provided as\n * input.\n * @param {Iterable<string> | Iterable<R>} words - The `words` parameter in the constructor is an\n * iterable containing either strings or elements of type `R`. It is used to initialize the Trie with\n * a list of words or elements. If no `words` are provided, an empty iterable is used as the default\n * value.\n * @param [options] - The `options` parameter in the constructor is an optional object that can\n * contain configuration options for the Trie data structure. One of the options it can have is\n * `caseSensitive`, which is a boolean value indicating whether the Trie should be case-sensitive or\n * not. If `caseSensitive` is set to `\n */\n constructor(words: Iterable<string> | Iterable<R> = [], options?: TrieOptions<R>) {\n super(options);\n if (options) {\n const { caseSensitive } = options;\n if (caseSensitive !== undefined) this._caseSensitive = caseSensitive;\n }\n if (words) {\n this.addMany(words);\n }\n }\n\n protected _size: number = 0;\n\n /**\n * The size function returns the size of the stack.\n * @return The number of elements in the list\n */\n get size(): number {\n return this._size;\n }\n\n protected _caseSensitive: boolean = true;\n\n /**\n * The caseSensitive function is a getter that returns the value of the protected _caseSensitive property.\n * @return The value of the _caseSensitive protected variable\n */\n get caseSensitive(): boolean {\n return this._caseSensitive;\n }\n\n protected _root: TrieNode = new TrieNode('');\n\n /**\n * The root function returns the root node of the tree.\n * @return The root node\n */\n get root() {\n return this._root;\n }\n\n /**\n * Time Complexity: O(l), where l is the length of the word being added.\n * Space Complexity: O(l) - Each character in the word adds a TrieNode.\n *\n * Add a word to the Trie structure.\n * @param {string} word - The word to add.\n * @returns {boolean} True if the word was successfully added.\n */\n add(word: string): boolean {\n word = this._caseProcess(word);\n let cur = this.root;\n let isNewWord = false;\n for (const c of word) {\n let nodeC = cur.children.get(c);\n if (!nodeC) {\n nodeC = new TrieNode(c);\n cur.children.set(c, nodeC);\n }\n cur = nodeC;\n }\n if (!cur.isEnd) {\n isNewWord = true;\n cur.isEnd = true;\n this._size++;\n }\n return isNewWord;\n }\n\n /**\n * Time Complexity: O(n * l)\n * Space Complexity: O(1)\n *\n * The `addMany` function in TypeScript takes an iterable of strings or elements of type R, converts\n * them using a provided function if available, and adds them to a data structure while returning an\n * array of boolean values indicating success.\n * @param {Iterable<string> | Iterable<R>} words - The `words` parameter in the `addMany` function is\n * an iterable that contains either strings or elements of type `R`.\n * @returns The `addMany` method returns an array of boolean values indicating whether each word in\n * the input iterable was successfully added to the data structure.\n */\n addMany(words: Iterable<string> | Iterable<R>): boolean[] {\n const ans: boolean[] = [];\n for (const word of words) {\n if (this.toElementFn) {\n ans.push(this.add(this.toElementFn(word as R)));\n } else {\n ans.push(this.add(word as string));\n }\n }\n return ans;\n }\n\n /**\n * Time Complexity: O(l), where l is the length of the input word.\n * Space Complexity: O(1) - Constant space.\n *\n * Check if the Trie contains a given word.\n * @param {string} word - The word to check for.\n * @returns {boolean} True if the word is present in the Trie.\n */\n override has(word: string): boolean {\n word = this._caseProcess(word);\n let cur = this.root;\n for (const c of word) {\n const nodeC = cur.children.get(c);\n if (!nodeC) return false;\n cur = nodeC;\n }\n return cur.isEnd;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The isEmpty function checks if the size of the queue is 0.\n * @return True if the size of the queue is 0\n */\n isEmpty(): boolean {\n return this._size === 0;\n }\n\n /**\n * Time Complexity: O(1)\n * Space Complexity: O(1)\n *\n * The clear function resets the size of the Trie to 0 and creates a new root TrieNode.\n */\n clear(): void {\n this._size = 0;\n this._root = new TrieNode('');\n }\n\n /**\n * Time Complexity: O(l), where l is the length of the word being deleted.\n * Space Complexity: O(n) - Due to the recursive DFS approach.\n *\n * Remove a word from the Trie structure.\n * @param{string} word - The word to delete.\n * @returns {boolean} True if the word was successfully removed.\n */\n delete(word: string): boolean {\n word = this._caseProcess(word);\n let isDeleted = false;\n const dfs = (cur: TrieNode, i: number): boolean => {\n const char = word[i];\n const child = cur.children.get(char);\n if (child) {\n if (i === word.length - 1) {\n if (child.isEnd) {\n if (child.children.size > 0) {\n child.isEnd = false;\n } else {\n cur.children.delete(char);\n }\n isDeleted = true;\n return true;\n }\n return false;\n }\n const res = dfs(child, i + 1);\n if (res && !cur.isEnd && child.children.size === 0) {\n cur.children.delete(char);\n return true;\n }\n return false;\n }\n return false;\n };\n\n dfs(this.root, 0);\n if (isDeleted) {\n this._size--;\n }\n return isDeleted;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(1)\n *\n * The function `getHeight` calculates the height of a trie data structure starting from the root\n * node.\n * @returns The `getHeight` method returns the maximum depth or height of the trie tree starting from\n * the root node. It calculates the depth using a breadth-first search (BFS) traversal of the trie\n * tree and returns the maximum depth found.\n */\n getHeight(): number {\n const startNode = this.root;\n let maxDepth = 0;\n if (startNode) {\n const bfs = (node: TrieNode, level: number) => {\n if (level > maxDepth) {\n maxDepth = level;\n }\n const { children } = node;\n if (children) {\n for (const child of children.entries()) {\n bfs(child[1], level + 1);\n }\n }\n };\n bfs(startNode, 0);\n }\n return maxDepth;\n }\n\n /**\n * Time Complexity: O(l), where l is the length of the input prefix.\n * Space Complexity: O(1) - Constant space.\n *\n * Check if a given input string has an absolute prefix in the Trie, meaning it's not a complete word.\n * @param {string} input - The input string to check.\n * @returns {boolean} True if it's an absolute prefix in the Trie.\n */\n hasPurePrefix(input: string): boolean {\n input = this._caseProcess(input);\n let cur = this.root;\n for (const c of input) {\n const nodeC = cur.children.get(c);\n if (!nodeC) return false;\n cur = nodeC;\n }\n return !cur.isEnd;\n }\n\n /**\n * Time Complexity: O(l), where l is the length of the input prefix.\n * Space Complexity: O(1) - Constant space.\n *\n * Check if a given input string is a prefix of any existing word in the Trie, whether as an absolute prefix or a complete word.\n * @param {string} input - The input string representing the prefix to check.\n * @returns {boolean} True if it's a prefix in the Trie.\n */\n hasPrefix(input: string): boolean {\n input = this._caseProcess(input);\n let cur = this.root;\n for (const c of input) {\n const nodeC = cur.children.get(c);\n if (!nodeC) return false;\n cur = nodeC;\n }\n return true;\n }\n\n /**\n * Time Complexity: O(n), where n is the total number of nodes in the trie.\n * Space Complexity: O(l), where l is the length of the input prefix.\n *\n * Check if the input string is a common prefix in the Trie, meaning it's a prefix shared by all words in the Trie.\n * @param {string} input - The input string representing the common prefix to check for.\n * @returns {boolean} True if it's a common prefix in the Trie.\n */\n hasCommonPrefix(input: string): boolean {\n input = this._caseProcess(input);\n let commonPre = '';\n const dfs = (cur: TrieNode) => {\n commonPre += cur.key;\n if (commonPre === input) return;\n if (cur.isEnd) return;\n if (cur && cur.children && cur.children.size === 1) dfs(Array.from(cur.children.values())[0]);\n else return;\n };\n dfs(this.root);\n return commonPre === input;\n }\n\n /**\n * Time Complexity: O(n), where n is the total number of nodes in the trie.\n * Space Complexity: O(l), where l is the length of the longest common prefix.\n *\n * Get the longest common prefix among all the words stored in the Trie.\n * @returns {string} The longest common prefix found in the Trie.\n */\n getLongestCommonPrefix(): string {\n let commonPre = '';\n const dfs = (cur: TrieNode) => {\n commonPre += cur.key;\n if (cur.isEnd) return;\n if (cur && cur.children && cur.children.size === 1) dfs(Array.from(cur.children.values())[0]);\n else return;\n };\n dfs(this.root);\n return commonPre;\n }\n\n /**\n * Time Complexity: O(w * l), where w is the number of words retrieved, and l is the average length of the words.\n * Space Complexity: O(w * l) - The space required for the output array.\n *\n * The `getAll` function returns an array of all words in a Trie data structure that start with a given prefix.\n * @param {string} prefix - The `prefix` parameter is a string that represents the prefix that we want to search for in the\n * trie. It is an optional parameter, so if no prefix is provided, it will default to an empty string.\n * @param {number} max - The max count of words will be found\n * @param isAllWhenEmptyPrefix - If true, when the prefix provided as '', returns all the words in the trie.\n * @returns {string[]} an array of strings.\n */\n getWords(prefix = '', max = Number.MAX_SAFE_INTEGER, isAllWhenEmptyPrefix = false): string[] {\n prefix = this._caseProcess(prefix);\n const words: string[] = [];\n let found = 0;\n\n function dfs(node: TrieNode, word: string) {\n for (const char of node.children.keys()) {\n const charNode = node.children.get(char);\n if (charNode !== undefined) {\n dfs(charNode, word.concat(char));\n }\n }\n if (node.isEnd) {\n if (found > max - 1) return;\n words.push(word);\n found++;\n }\n }\n\n let startNode = this.root;\n\n if (prefix) {\n for (const c of prefix) {\n const nodeC = startNode.children.get(c);\n if (nodeC) {\n startNode = nodeC;\n } else {\n // Early return if the whole prefix is not found\n return [];\n }\n }\n }\n\n if (isAllWhenEmptyPrefix || startNode !== this.root) dfs(startNode, prefix);\n\n return words;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `clone` function returns a new instance of the Trie class with the same values and case\n * sensitivity as the original Trie.\n * @returns A new instance of the Trie class is being returned.\n */\n clone(): Trie<R> {\n return new Trie<R>(this, { caseSensitive: this.caseSensitive, toElementFn: this.toElementFn });\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `filter` function takes a predicate function and returns a new array containing all the\n * elements for which the predicate function returns true.\n * @param predicate - The `predicate` parameter is a callback function that takes three arguments:\n * `word`, `index`, and `this`. It should return a boolean value indicating whether the current\n * element should be included in the filtered results or not.\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the `predicate` function. It is used when you want to bind a\n * specific object as the context for the `predicate` function. If `thisArg` is provided, it will be\n * @returns The `filter` method is returning an array of strings (`string[]`).\n */\n filter(predicate: ElementCallback<string, R, boolean>, thisArg?: any): Trie<R> {\n const results = new Trie<R>([], { toElementFn: this.toElementFn, caseSensitive: this.caseSensitive });\n let index = 0;\n for (const word of this) {\n if (predicate.call(thisArg, word, index, this)) {\n results.add(word);\n }\n index++;\n }\n return results;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The `map` function creates a new Trie by applying a callback function to each element in the\n * current Trie.\n * @param callback - The callback parameter is a function that will be called for each element in the\n * Trie. It takes four arguments:\n * @param [toElementFn] - The `toElementFn` parameter is an optional function that can be used to\n * convert the raw element (`RM`) into a string representation. This can be useful if the raw element\n * is not already a string or if you want to customize how the element is converted into a string. If\n * this parameter is\n * @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to\n * specify the value of `this` within the callback function. It is used to set the context or scope\n * in which the callback function will be executed. If `thisArg` is provided, it will be used as the\n * value of\n * @returns a new Trie object.\n */\n map<RM>(\n callback: ElementCallback<string, R, string>,\n toElementFn?: (rawElement: RM) => string,\n thisArg?: any\n ): Trie<RM> {\n const newTrie = new Trie<RM>([], { toElementFn, caseSensitive: this.caseSensitive });\n let index = 0;\n for (const word of this) {\n newTrie.add(callback.call(thisArg, word, index, this));\n index++;\n }\n return newTrie;\n }\n\n /**\n * Time Complexity: O(n)\n * Space Complexity: O(n)\n *\n * The function `_getIterator` returns an iterable iterator that performs a depth-first search on a\n * trie data structure and yields all the paths to the end nodes.\n */\n protected *_getIterator(): IterableIterator<string> {\n function* _dfs(node: TrieNode, path: string): IterableIterator<string> {\n if (node.isEnd) {\n yield path;\n }\n for (const [char, childNode] of node.children) {\n yield* _dfs(childNode, path + char);\n }\n }\n\n yield* _dfs(this.root, '');\n }\n\n protected get _total() {\n return this._size;\n }\n\n /**\n * Time Complexity: O(l), where l is the length of the input string.\n * Space Complexity: O(1) - Constant space.\n *\n * @param str\n * @protected\n */\n protected _caseProcess(str: string) {\n if (!this._caseSensitive) {\n str = str.toLowerCase(); // Convert str to lowercase if case-insensitive\n }\n return str;\n }\n}\n","export class TreeNode<V = any> {\n /**\n * The constructor function initializes a TreeNode object with a key, optional value, and optional\n * children.\n * @param {string} key - A string representing the key of the tree node.\n * @param {V} [value] - The `value` parameter is an optional parameter of type `V`. It represents the\n * value associated with the node. If no value is provided, it defaults to `undefined`.\n * @param {TreeNode<V>[]} [children] - The `children` parameter is an optional array of `TreeNode<V>`\n * objects. It represents the child nodes of the current node. If no children are provided, the\n * default value is an empty array.\n */\n constructor(key: string, value?: V, children?: TreeNode<V>[]) {\n this._key = key;\n this._value = value || undefined;\n if (children) this._children = children;\n }\n\n protected _key: string;\n\n /**\n * The function returns the value of the protected variable _key.\n * @returns The value of the `_key` property, which is a string.\n */\n get key(): string {\n return this._key;\n }\n\n /**\n * The above function sets the value of a protected variable called \"key\".\n * @param {string} value - The value parameter is a string that represents the value to be assigned\n * to the key.\n */\n set key(value: string) {\n this._key = value;\n }\n\n protected _value?: V | undefined;\n\n /**\n * The function returns the value stored in a variable, or undefined if the variable is empty.\n * @returns The value of the variable `_value` is being returned.\n */\n get value(): V | undefined {\n return this._value;\n }\n\n /**\n * The function sets the value of a variable.\n * @param {V | undefined} value - The parameter \"value\" is of type \"V | undefined\", which means it\n * can accept a value of type \"V\" or it can be undefined.\n */\n set value(value: V | undefined) {\n this._value = value;\n }\n\n protected _children?: TreeNode<V>[] | undefined;\n\n /**\n * The function returns an array of TreeNode objects or undefined.\n * @returns The `children` property is being returned. It is of type `TreeNode<V>[] | undefined`,\n * which means it can either be an array of `TreeNode<V>` objects or `undefined`.\n */\n get children(): TreeNode<V>[] | undefined {\n return this._children;\n }\n\n /**\n * The function sets the value of the children property of a TreeNode object.\n * @param {TreeNode<V>[] | undefined} value - The value parameter is of type TreeNode<V>[] |\n * undefined. This means that it can accept an array of TreeNode objects or undefined.\n */\n set children(value: TreeNode<V>[] | undefined) {\n this._children = value;\n }\n\n /**\n * The function `addChildren` adds one or more child nodes to the current node.\n * @param {TreeNode<V> | TreeNode<V>[]} children - The `children` parameter can be either a single\n * `TreeNode<V>` object or an array of `TreeNode<V>` objects.\n */\n addChildren(children: TreeNode<V> | TreeNode<V>[]) {\n if (!this._children) {\n this._children = [];\n }\n if (children instanceof TreeNode) {\n this._children.push(children);\n } else {\n this._children = this._children.concat(children);\n }\n }\n\n /**\n * The function `getHeight()` calculates the maximum depth of a tree structure by performing a\n * breadth-first search.\n * @returns the maximum depth or height of the tree.\n */\n getHeight() {\n let maxDepth = 0;\n if (this) {\n const bfs = (node: TreeNode<V>, level: number) => {\n if (level > maxDepth) {\n maxDepth = level;\n }\n const { _children } = node;\n if (_children) {\n for (let i = 0, len = _children.length; i < len; i++) {\n bfs(_children[i], level + 1);\n }\n }\n };\n bfs(this, 0);\n }\n return maxDepth;\n }\n}\n"],"mappings":"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","names":["src_exports","__export","AVLTree","AVLTreeCounter","AVLTreeCounterNode","AVLTreeMultiMap","AVLTreeMultiMapNode","AVLTreeNode","AbstractEdge","AbstractGraph","AbstractVertex","BST","BSTNode","BinaryIndexedTree","BinaryTree","BinaryTreeNode","Character","DFSOperation","Deque","DirectedEdge","DirectedGraph","DirectedVertex","DoublyLinkedList","DoublyLinkedListNode","FibonacciHeap","FibonacciHeapNode","HashMap","Heap","IterableElementBase","IterableEntryBase","LinkedHashMap","LinkedListQueue","MapEdge","MapGraph","MapVertex","Matrix","MaxHeap","MaxPriorityQueue","MinHeap","MinPriorityQueue","Navigator","PriorityQueue","Queue","Range","RedBlackTree","RedBlackTreeNode","SegmentTree","SegmentTreeNode","SinglyLinkedList","SinglyLinkedListNode","SkipList","SkipListNode","Stack","TreeCounter","TreeCounterNode","TreeMultiMap","TreeMultiMapNode","TreeNode","Trie","TrieNode","UndirectedEdge","UndirectedGraph","UndirectedVertex","arrayRemove","calcMinUnitsRequired","getMSB","isComparable","isThunk","isWeakKey","rangeCheck","roundFixed","throwRangeError","toBinaryString","trampoline","uuidV4","IterableEntryBase","args","__yieldStar","item","predicate","thisArg","index","callbackfn","key","value","itemKey","elementValue","initialValue","accumulator","IterableElementBase","options","__publicField","toElementFn","args","__yieldStar","item","predicate","thisArg","index","callbackfn","element","ele","initialValue","accumulator","uuidV4","c","arrayRemove","array","predicate","i","len","result","value","isThunk","trampoline","thunk","getMSB","rangeCheck","index","min","max","message","throwRangeError","isWeakKey","input","inputType","calcMinUnitsRequired","totalQuantity","unitSize","roundFixed","num","digit","multiplier","isPrimitiveComparable","valueType","tryObjectToPrimitive","obj","valueOfResult","stringResult","isComparable","isForceObjectComparable","comparableValue","toBinaryString","num","digit","binaryString","HashMap","_HashMap","IterableEntryBase","entryOrRawElements","options","__publicField","key","hashFn","toEntryFn","rawElement","value","strKey","results","rawEle","item","_a","callbackfn","thisArg","resultMap","index","predicate","filteredMap","node","keyType","LinkedHashMap","_LinkedHashMap","objHashFn","isNewKey","isWeakKey","hash","rangeCheck","cloned","entry","callback","mappedMap","newKey","newValue","prev","next","LinkedListNode","value","__publicField","LinearBase","_LinearBase","IterableElementBase","options","maxLen","searchElement","fromIndex","i","predicate","thisArg","item","items","newList","compareFn","arr","start","deleteCount","removedList","removed","separator","array","callbackfn","initialValue","accumulator","end","LinearLinkedBase","iterator","current","index","c","currentIndex","currentNode","previousNode","node","nextNode","SinglyLinkedListNode","LinkedListNode","value","__publicField","SinglyLinkedList","_SinglyLinkedList","LinearLinkedBase","elements","options","_a","data","singlyLinkedList","item","elementOrNode","newNode","current","removedNode","ans","el","elementNodeOrPredicate","predicate","index","i","deleted","targetNode","prevNode","node","newElementOrNode","prev","next","existingElementOrNode","existingNode","start","deleteCount","items","removedList","nextNode","lastInsertedNode","count","callback","thisArg","filteredList","toElementFn","mappedList","reversedArr","DoublyLinkedListNode","LinkedListNode","value","__publicField","DoublyLinkedList","_DoublyLinkedList","LinearLinkedBase","elements","options","maxLen","_a","data","elementNodeOrPredicate","elementOrNode","newNode","removedNode","ans","el","index","current","i","predicate","newElementOrNode","prevNode","nextNode","existingElementOrNode","existingNode","node","deleted","next","callback","thisArg","filteredList","toElementFn","mappedList","count","SkipListNode","key","value","level","__publicField","SkipList","elements","options","maxLevel","probability","firstNode","current","i","newNode","update","nextNode","lastLess","Stack","_Stack","IterableElementBase","elements","options","__publicField","element","ans","el","index","predicate","thisArg","newStack","callback","toElementFn","i","Queue","_Queue","LinearBase","elements","options","__publicField","autoCompactRatio","v","element","ans","el","first","index","deleted","newElement","start","deleteCount","items","removedQueue","globalStartIndex","removedElements","predicate","thisArg","newDeque","callback","toElementFn","item","i","cur","LinkedListQueue","_LinkedListQueue","SinglyLinkedList","Deque","_Deque","LinearBase","elements","options","__publicField","bucketSize","_size","calcMinUnitsRequired","i","needBucketNum","element","ans","el","pos","rangeCheck","bucketIndex","indexInBucket","num","length","arr","isCutSelf","newDeque","start","deleteCount","items","deletedElements","elementsAfter","item","deleted","targetBucket","targetPointer","curBucket","curPointer","nextBucket","nextPointer","size","index","oldElement","bucket","_bucketFirst","_bucketLast","_firstInBucket","_lastInBucket","prev","cur","newBuckets","predicate","thisArg","callback","toElementFn","addBucketNum","overallIndex","Heap","_Heap","IterableElementBase","elements","options","__publicField","a","b","comparator","_a","element","ans","el","value","last","index","order","result","_dfs","left","right","visitedNode","cloned","top","results","i","callback","thisArg","filteredList","current","toElementFn","mappedHeap","parent","parentItem","halfLength","minItem","FibonacciHeapNode","degree","FibonacciHeap","node","head","flag","z","heapToMerge","thisRoot","otherRoot","thisRootRight","otherRootLeft","y","x","A","d","t","MaxHeap","_MaxHeap","Heap","elements","options","__spreadValues","a","b","callback","thisArg","filteredList","index","current","comparator","toElementFn","mappedHeap","el","MinHeap","_MinHeap","Heap","elements","options","callback","thisArg","filteredList","index","current","comparator","toElementFn","mappedHeap","el","AbstractVertex","key","value","__publicField","AbstractEdge","weight","uuidV4","AbstractGraph","IterableEntryBase","v","vertexKey","vertexOrKey","keyOrVertex","newVertex","potentialKey","potentialKeyType","vertexMap","removed","v1","v2","srcOrEdge","dest","newEdge","srcOrKey","destOrKey","edge","limit","paths","vertex1","vertex2","stack","vertex","path","neighbors","neighbor","newPath","_a","sum","isWeight","allPaths","min","visited","queue","Queue","cost","i","cur","isDFS","_b","minIndex","index","pathSumWeight","minPath","dfs","visiting","src","getMinDist","genPaths","minDist","minDest","distMap","seen","preMap","srcVertex","destVertex","getMinOfNoSeen","minV","getPaths","parent","reversed","curFromMap","neighborFromMap","d","heap","Heap","a","b","curHeapNode","dist","distSrcToNeighbor","scanNegativeCycle","getMin","genPath","hasNegativeCycle","numOfVertices","edgeMap","numOfEdges","j","ends","s","sWeight","dWeight","idAndVertices","n","costs","predecessor","k","isInclude2Cycle","cycles","currentPath","uniqueCycles","cycle","sorted","cycleString","predicate","thisArg","filtered","callback","mapped","DirectedVertex","AbstractVertex","key","value","DirectedEdge","AbstractEdge","src","dest","weight","__publicField","DirectedGraph","_DirectedGraph","AbstractGraph","v","srcOrKey","destOrKey","edgeMap","srcOutEdges","edge","removed","arrayRemove","destInEdges","edgeOrSrcVertexKey","destVertexKey","vertexOrKey","vertexKey","vertex","neighbors","neighbor","v1","v2","v1ToV2","v2ToV1","target","destinations","outgoingEdges","outEdge","child","propertyName","statusMap","entry","sorted","hasCycle","dfs","cur","children","childStatus","outEdges","cloned","dfnMap","lowMap","SCCs","time","stack","inStack","SCC","poppedVertex","srcVertex","destVertex","UndirectedVertex","AbstractVertex","key","value","UndirectedEdge","AbstractEdge","v1","v2","weight","__publicField","UndirectedGraph","_UndirectedGraph","AbstractGraph","v","_a","edgeMap","vertex1","vertex2","e","v1Edges","removed","arrayRemove","v2Edges","edgeOrOneSideVertexKey","otherSideVertexKey","oneSide","otherSide","vertexOrKey","vertexKey","vertex","neighbors","neighbor","neighborEdges","restEdges","edge","edgeSet","cloned","dfnMap","lowMap","bridges","cutVertices","time","dfs","parent","childCount","end","endVertex","MapVertex","DirectedVertex","key","value","lat","long","__publicField","MapEdge","DirectedEdge","src","dest","weight","MapGraph","_MapGraph","DirectedGraph","originCoord","bottomRight","cloned","DFSOperation","Range","low","high","includeLow","includeHigh","isComparable","key","comparator","lowCheck","highCheck","BinaryTreeNode","key","value","__publicField","v","BinaryTree","_BinaryTree","IterableEntryBase","keysNodesEntriesOrRaws","options","node","iterationType","toEntryFn","isMapMode","isDuplicate","__spreadValues","keyNodeOrEntry","keyNodeEntryOrRaw","keyNodeEntryOrPredicate","Range","isComparable","newNode","newValue","queue","Queue","potentialParent","cur","values","inserted","valuesIterator","valueResult","anotherTree","deletedResult","curr","parent","needBalanced","orgCurrent","leftSubTreeRightMost","parentOfLeftSubTreeMax","fp","onlyOne","callback","startNode","predicate","ans","dfs","stack","_a","min","max","numKey","isStandardBST","isInverseBST","checkBST","checkMax","prev","dist","distEnsured","beginRootEnsured","depth","_getMaxHeight","leftHeight","rightHeight","maxHeight","_getMinHeight","leftMinHeight","rightMinHeight","last","depths","beginNode","isReverse","result","beginNodeEnsured","trampoline","predecessor","x","y","pattern","includeNull","level","current","levelSize","i","leaves","levelsNodes","_recursive","head","_reverseEdge","pre","next","_printEdge","tail","cloned","thisArg","newTree","index","opts","output","root","lines","paragraph","line","entryValue","finalValue","shouldVisitLeft","shouldVisitRight","shouldVisitRoot","shouldProcessRoot","visitLeft","visitRight","pushLeft","pushRight","pushRoot","__yieldStar","isShowNull","isShowUndefined","isShowRedBlackNIL","emptyDisplayLayout","width","_buildNodeDisplay","left","right","leftLines","leftWidth","leftMiddle","rightLines","rightWidth","rightMiddle","firstLine","secondLine","mergedLines","leftLine","rightLine","srcNode","destNode","tempNode","oldNode","p","BSTNode","BinaryTreeNode","key","value","__publicField","v","BST","_BST","BinaryTree","keysNodesEntriesOrRaws","options","a","b","isComparable","specifyComparable","isReverse","__spreadValues","keyNodeOrEntry","iterationType","_a","newNode","newValue","current","values","isBalanceAdd","inserted","valuesIterator","kve","realBTNExemplars","i","sorted","keyA","keyB","_dfs","arr","mid","orgIndex","entry","stack","popped","l","r","m","keyNodeEntryOrPredicate","onlyOne","callback","startNode","predicate","isRange","node","shouldVisitLeft","cur","range","leftS","leftI","benchmarkKey","shouldVisitRight","rightS","rightI","searchRange","Range","pattern","lesserOrGreater","targetNode","targetNodeEnsured","ans","targetKey","dfs","compared","queue","Queue","buildBalanceBST","midNode","balanced","_height","leftHeight","rightHeight","last","depths","left","right","thisArg","newTree","index","cloned","entryValue","BinaryIndexedTree","frequency","max","__publicField","getMSB","index","position","change","freqCur","freq","count","sum","x","y","i","delta","z","freqNew","before","left","right","sumT","middle","sumM","SegmentTreeNode","start","end","sum","value","__publicField","SegmentTree","values","mid","left","right","cur","index","root","dfs","indexA","indexB","i","j","leftSum","rightSum","AVLTreeNode","BSTNode","key","value","__publicField","v","AVLTree","_AVLTree","BST","keysNodesEntriesOrRaws","options","__spreadValues","keyNodeOrEntry","inserted","deletedResults","needBalanced","callback","thisArg","newTree","index","cloned","srcNode","destNode","srcNodeEnsured","destNodeEnsured","height","tempNode","node","rightHeight","A","parentOfA","B","C","path","i","oldNode","newNode","RedBlackTreeNode","BSTNode","key","value","color","__publicField","v","RedBlackTree","_RedBlackTree","BST","keysNodesEntriesOrRaws","options","__spreadValues","keyNodeOrEntry","newNode","newValue","insertStatus","results","nodeToDelete","originalColor","replacementNode","successor","node","callback","thisArg","newTree","index","cloned","oldNode","_a","_b","current","parent","compared","u","z","_c","_d","_e","y","sibling","x","AVLTreeMultiMapNode","AVLTreeNode","key","value","__publicField","v","AVLTreeMultiMap","_AVLTreeMultiMap","AVLTree","keysNodesEntriesOrRaws","options","__spreadProps","__spreadValues","keyNodeOrEntry","_commonAdd","values","_addToValues","existingValues","_addByNode","existingNode","index","cloned","TreeMultiMapNode","RedBlackTreeNode","key","value","__publicField","v","TreeMultiMap","_TreeMultiMap","RedBlackTree","keysNodesEntriesOrRaws","options","__spreadValues","keyNodeOrEntry","_commonAdd","values","_addToValues","existingValues","_addByNode","existingNode","index","cloned","TreeCounterNode","RedBlackTreeNode","key","value","count","color","__publicField","v","TreeCounter","_TreeCounter","RedBlackTree","keysNodesEntriesOrRaws","options","sum","node","__spreadValues","keyNodeOrEntry","newNode","newValue","orgCount","ignoreCount","results","nodeToDelete","originalColor","replacementNode","successor","iterationType","sorted","buildBalanceBST","l","r","m","midNode","stack","popped","cloned","callback","thisArg","newTree","index","entryValue","finalValue","srcNode","destNode","tempNode","oldNode","AVLTreeCounterNode","AVLTreeNode","key","value","count","__publicField","v","AVLTreeCounter","_AVLTreeCounter","AVLTree","keysNodesEntriesOrRaws","options","sum","node","__spreadValues","keyNodeOrEntry","newNode","newValue","orgNodeCount","ignoreCount","_a","deletedResult","curr","parent","needBalanced","orgCurrent","leftSubTreeRightMost","parentOfLeftSubTreeMax","fp","iterationType","sorted","buildBalanceBST","l","r","m","midNode","stack","popped","cloned","callback","thisArg","newTree","index","entryValue","finalValue","srcNode","destNode","height","tempNode","oldNode","PriorityQueue","_PriorityQueue","Heap","elements","options","callback","thisArg","filteredPriorityQueue","index","current","comparator","toElementFn","mappedPriorityQueue","el","MinPriorityQueue","_MinPriorityQueue","PriorityQueue","elements","options","callback","thisArg","filteredPriorityQueue","index","current","comparator","toElementFn","mappedPriorityQueue","el","MaxPriorityQueue","_MaxPriorityQueue","PriorityQueue","elements","options","__spreadValues","a","b","callback","thisArg","filteredPriorityQueue","index","current","comparator","toElementFn","mappedPriorityQueue","el","Matrix","_Matrix","data","options","__publicField","_a","_b","_c","rows","cols","addFn","subtractFn","multiplyFn","i","row","col","value","matrix","resultData","j","a","b","added","subtracted","sum","k","multiplied","trans","augmentedMatrixData","augmentedMatrix","pivotRow","pivotElement","factor","inverseData","row1","row2","temp","scalar","targetRow","sourceRow","scaledValue","Character","_Character","direction","turning","__publicField","Navigator","matrix","onMove","cur","charDir","VISITED","forward","row","j","i","TrieNode","key","__publicField","value","Trie","_Trie","IterableElementBase","words","options","caseSensitive","word","cur","isNewWord","c","nodeC","ans","isDeleted","dfs","i","char","child","startNode","maxDepth","bfs","node","level","children","input","commonPre","prefix","max","isAllWhenEmptyPrefix","found","charNode","predicate","thisArg","results","index","callback","toElementFn","newTrie","_dfs","path","childNode","__yieldStar","str","TreeNode","_TreeNode","key","value","children","__publicField","maxDepth","bfs","node","level","_children","i","len"]}