data-structure-typed 1.42.4 → 1.42.6

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 (38) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/CONTRIBUTING.md +66 -5
  3. package/README.md +212 -120
  4. package/benchmark/report.html +12 -12
  5. package/benchmark/report.json +106 -106
  6. package/dist/cjs/src/data-structures/binary-tree/index.d.ts +1 -1
  7. package/dist/cjs/src/data-structures/binary-tree/index.js +1 -1
  8. package/dist/cjs/src/data-structures/binary-tree/{tree-multiset.d.ts → tree-multimap.d.ts} +10 -10
  9. package/dist/cjs/src/data-structures/binary-tree/{tree-multiset.js → tree-multimap.js} +15 -15
  10. package/dist/cjs/src/data-structures/binary-tree/{tree-multiset.js.map → tree-multimap.js.map} +1 -1
  11. package/dist/cjs/src/types/data-structures/binary-tree/index.d.ts +1 -1
  12. package/dist/cjs/src/types/data-structures/binary-tree/index.js +1 -1
  13. package/dist/cjs/src/types/data-structures/binary-tree/tree-multimap.d.ts +4 -0
  14. package/dist/cjs/src/types/data-structures/binary-tree/{tree-multiset.js → tree-multimap.js} +1 -1
  15. package/dist/cjs/src/types/data-structures/binary-tree/tree-multimap.js.map +1 -0
  16. package/dist/mjs/src/data-structures/binary-tree/index.d.ts +1 -1
  17. package/dist/mjs/src/data-structures/binary-tree/index.js +1 -1
  18. package/dist/mjs/src/data-structures/binary-tree/{tree-multiset.d.ts → tree-multimap.d.ts} +10 -10
  19. package/dist/mjs/src/data-structures/binary-tree/{tree-multiset.js → tree-multimap.js} +14 -14
  20. package/dist/mjs/src/types/data-structures/binary-tree/index.d.ts +1 -1
  21. package/dist/mjs/src/types/data-structures/binary-tree/index.js +1 -1
  22. package/dist/mjs/src/types/data-structures/binary-tree/tree-multimap.d.ts +4 -0
  23. package/dist/umd/data-structure-typed.min.js +1 -1
  24. package/dist/umd/data-structure-typed.min.js.map +1 -1
  25. package/package.json +9 -7
  26. package/src/data-structures/binary-tree/index.ts +1 -1
  27. package/src/data-structures/binary-tree/{tree-multiset.ts → tree-multimap.ts} +14 -14
  28. package/src/types/data-structures/binary-tree/index.ts +1 -1
  29. package/src/types/data-structures/binary-tree/tree-multimap.ts +6 -0
  30. package/test/performance/data-structures/binary-tree/rb-tree.test.ts +2 -2
  31. package/test/performance/reportor.ts +2 -2
  32. package/test/unit/data-structures/binary-tree/{tree-multiset.test.ts → tree-multimap.test.ts} +182 -182
  33. package/dist/cjs/src/types/data-structures/binary-tree/tree-multiset.d.ts +0 -4
  34. package/dist/cjs/src/types/data-structures/binary-tree/tree-multiset.js.map +0 -1
  35. package/dist/mjs/src/types/data-structures/binary-tree/tree-multiset.d.ts +0 -4
  36. package/src/types/data-structures/binary-tree/tree-multiset.ts +0 -6
  37. /package/dist/mjs/src/types/data-structures/binary-tree/{tree-multiset.js → tree-multimap.js} +0 -0
  38. /package/test/performance/data-structures/binary-tree/{tree-multiset.test.ts → tree-multimap.test.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts","../../src/data-structures/hash/hash-table.ts","../../src/data-structures/hash/coordinate-map.ts","../../src/data-structures/hash/coordinate-set.ts","../../src/data-structures/hash/tree-map.ts","../../src/data-structures/hash/tree-set.ts","../../src/data-structures/hash/hash-map.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/utils/utils.ts","../../src/data-structures/heap/heap.ts","../../src/data-structures/heap/max-heap.ts","../../src/data-structures/heap/min-heap.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/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/types/data-structures/binary-tree/binary-tree.ts","../../src/types/data-structures/binary-tree/rb-tree.ts","../../src/types/data-structures/graph/directed-graph.ts","../../src/types/helpers.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/rb-tree.ts","../../src/data-structures/binary-tree/tree-multiset.ts","../../src/data-structures/tree/tree.ts","../../src/data-structures/matrix/matrix.ts","../../src/data-structures/matrix/vector2d.ts","../../src/data-structures/matrix/matrix2d.ts","../../src/data-structures/matrix/navigator.ts","../../src/data-structures/trie/trie.ts"],"sourcesContent":["export * from './data-structures';\nexport * from './utils';\nexport * from './interfaces';\nexport * from './types';\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n\nexport class HashTableNode<K, V> {\n key: K;\n value: V;\n next: HashTableNode<K, V> | null;\n\n constructor(key: K, value: V) {\n this.key = key;\n this.value = value;\n this.next = null;\n }\n}\n\nimport {HashFunction} from '../../types';\n\nexport class HashTable<K, V> {\n protected static readonly DEFAULT_CAPACITY = 16;\n protected static readonly LOAD_FACTOR = 0.75;\n\n constructor(capacity: number = HashTable.DEFAULT_CAPACITY, hashFn?: HashFunction<K>) {\n this._hashFn = hashFn || this._defaultHashFn;\n this._capacity = Math.max(capacity, HashTable.DEFAULT_CAPACITY);\n this._size = 0;\n this._buckets = new Array<HashTableNode<K, V> | null>(this._capacity).fill(null);\n }\n\n protected _capacity: number;\n\n get capacity(): number {\n return this._capacity;\n }\n\n protected _size: number;\n\n get size(): number {\n return this._size;\n }\n\n protected _buckets: Array<HashTableNode<K, V> | null>;\n\n get buckets(): Array<HashTableNode<K, V> | null> {\n return this._buckets;\n }\n\n protected _hashFn: HashFunction<K>;\n\n get hashFn(): HashFunction<K> {\n return this._hashFn;\n }\n\n /**\n * The set function adds a key-value pair to the hash table, handling collisions and resizing if necessary.\n * @param {K} key - The key parameter represents the key of the key-value pair that you want to insert into the hash\n * table. It is of type K, which is a generic type representing the key's data type.\n * @param {V} value - The parameter `value` represents the value that you want to associate with the given key in the hash\n * table.\n * @returns Nothing is being returned. The return type of the `put` method is `void`, which means it does not return any\n * value.\n */\n set(key: K, value: V): void {\n const index = this._hash(key);\n const newNode = new HashTableNode<K, V>(key, value);\n\n if (!this._buckets[index]) {\n this._buckets[index] = newNode;\n } else {\n // Handle collisions, consider using open addressing, etc.\n let currentNode = this._buckets[index]!;\n while (currentNode) {\n if (currentNode.key === key) {\n // If the key already exists, update the value\n currentNode.value = value;\n return;\n }\n if (!currentNode.next) {\n break;\n }\n currentNode = currentNode.next;\n }\n // Add to the end of the linked list\n currentNode.next = newNode;\n }\n this._size++;\n\n // If the load factor is too high, resize the hash table\n if (this._size / this._capacity >= HashTable.LOAD_FACTOR) {\n this._expand();\n }\n }\n\n /**\n * The `get` function retrieves the value associated with a given key from a hash table.\n * @param {K} key - The `key` parameter represents the key of the element that we want to retrieve from the data\n * structure.\n * @returns The method is returning the value associated with the given key if it exists in the hash table. If the key is\n * not found, it returns `undefined`.\n */\n get(key: K): V | undefined {\n const index = this._hash(key);\n let currentNode = this._buckets[index];\n\n while (currentNode) {\n if (currentNode.key === key) {\n return currentNode.value;\n }\n currentNode = currentNode.next;\n }\n return undefined; // Key not found\n }\n\n /**\n * The delete function removes a key-value pair from a hash table.\n * @param {K} key - The `key` parameter represents the key of the key-value pair that needs to be removed from the hash\n * table.\n * @returns Nothing is being returned. The `delete` method has a return type of `void`, which means it does not return\n * any value.\n */\n delete(key: K): void {\n const index = this._hash(key);\n let currentNode = this._buckets[index];\n let prevNode: HashTableNode<K, V> | null = null;\n\n while (currentNode) {\n if (currentNode.key === key) {\n if (prevNode) {\n prevNode.next = currentNode.next;\n } else {\n this._buckets[index] = currentNode.next;\n }\n this._size--;\n currentNode.next = null; // Release memory\n return;\n }\n prevNode = currentNode;\n currentNode = currentNode.next;\n }\n }\n\n /**\n * The function `_defaultHashFn` calculates the hash value of a given key and returns the remainder when divided by the\n * capacity of the data structure.\n * @param {K} key - The `key` parameter is the input value that needs to be hashed. It can be of any type, but in this\n * code snippet, it is checked whether the key is a string or an object. If it is a string, the `_murmurStringHashFn`\n * function is used to\n * @returns the hash value of the key modulo the capacity of the data structure.\n */\n protected _defaultHashFn(key: K): number {\n // Can be replaced with other hash functions as needed\n const hashValue = typeof key === 'string' ? this._murmurStringHashFn(key) : this._objectHash(key);\n return hashValue % this._capacity;\n }\n\n /**\n * The `_multiplicativeStringHashFn` function calculates a hash value for a given string key using the multiplicative\n * string hash function.\n * @param {K} key - The `key` parameter is the input value for which we want to calculate the hash. It can be of any\n * type, as it is generic (`K`). The function converts the `key` to a string using the `String()` function.\n * @returns a number, which is the result of the multiplicative string hash function applied to the input key.\n */\n protected _multiplicativeStringHashFn<K>(key: K): number {\n const keyString = String(key);\n let hash = 0;\n for (let i = 0; i < keyString.length; i++) {\n const charCode = keyString.charCodeAt(i);\n // Some constants for adjusting the hash function\n const A = 0.618033988749895;\n const M = 1 << 30; // 2^30\n hash = (hash * A + charCode) % M;\n }\n return Math.abs(hash); // Take absolute value to ensure non-negative numbers\n }\n\n /**\n * The function `_murmurStringHashFn` calculates a hash value for a given string key using the MurmurHash algorithm.\n * @param {K} key - The `key` parameter is the input value for which you want to calculate the hash. It can be of any\n * type, but it will be converted to a string using the `String()` function before calculating the hash.\n * @returns a number, which is the hash value calculated for the given key.\n */\n protected _murmurStringHashFn<K>(key: K): number {\n const keyString = String(key);\n const seed = 0;\n let hash = seed;\n\n for (let i = 0; i < keyString.length; i++) {\n const char = keyString.charCodeAt(i);\n hash = (hash ^ char) * 0x5bd1e995;\n hash = (hash ^ (hash >>> 15)) * 0x27d4eb2d;\n hash = hash ^ (hash >>> 15);\n }\n\n return Math.abs(hash);\n }\n\n /**\n * The _hash function takes a key and returns a number.\n * @param {K} key - The parameter \"key\" is of type K, which represents the type of the key that will be hashed.\n * @returns The hash function is returning a number.\n */\n protected _hash(key: K): number {\n return this.hashFn(key);\n }\n\n /**\n * The function calculates a hash value for a given string using the djb2 algorithm.\n * @param {string} key - The `key` parameter in the `stringHash` function is a string value that represents the input for\n * which we want to calculate the hash value.\n * @returns a number, which is the hash value of the input string.\n */\n protected _stringHash(key: string): number {\n let hash = 0;\n for (let i = 0; i < key.length; i++) {\n hash = (hash * 31 + key.charCodeAt(i)) & 0xffffffff;\n }\n return hash;\n }\n\n /**\n * The function `_objectHash` takes a key and returns a hash value, using a custom hash function for objects.\n * @param {K} key - The parameter \"key\" is of type \"K\", which means it can be any type. It could be a string, number,\n * boolean, object, or any other type of value. The purpose of the objectHash function is to generate a hash value for\n * the key, which can be used for\n * @returns a number, which is the hash value of the key.\n */\n protected _objectHash(key: K): number {\n // If the key is an object, you can write a custom hash function\n // For example, convert the object's properties to a string and use string hashing\n // This is just an example; you should write a specific object hash function as needed\n return this._stringHash(JSON.stringify(key));\n }\n\n /**\n * The `expand` function increases the capacity of a hash table by creating a new array of buckets with double the\n * capacity and rehashing all the existing key-value pairs into the new buckets.\n */\n protected _expand(): void {\n const newCapacity = this._capacity * 2;\n const newBuckets = new Array<HashTableNode<K, V> | null>(newCapacity).fill(null);\n\n for (const bucket of this._buckets) {\n let currentNode = bucket;\n while (currentNode) {\n const newIndex = this._hash(currentNode.key);\n const newNode = new HashTableNode<K, V>(currentNode.key, currentNode.value);\n\n if (!newBuckets[newIndex]) {\n newBuckets[newIndex] = newNode;\n } else {\n let currentNewNode = newBuckets[newIndex]!;\n while (currentNewNode.next) {\n currentNewNode = currentNewNode.next;\n }\n currentNewNode.next = newNode;\n }\n currentNode = currentNode.next;\n }\n }\n\n this._buckets = newBuckets;\n this._capacity = newCapacity;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nexport class CoordinateMap<V> extends Map<any, V> {\n constructor(joint?: string) {\n super();\n if (joint !== undefined) this._joint = joint;\n }\n\n protected _joint = '_';\n\n get joint(): string {\n return this._joint;\n }\n\n /**\n * The \"has\" function overrides the base class's \"has\" function and checks if a key exists in the map by joining the\n * key array with a specified delimiter.\n * @param {number[]} key - The parameter \"key\" is an array of numbers.\n * @returns The `has` method is being overridden to return the result of calling the `has` method of the superclass\n * (`super.has`) with the `key` array joined together using the `_joint` property.\n */\n override has(key: number[]) {\n return super.has(key.join(this._joint));\n }\n\n /**\n * The function overrides the set method of a Map object to convert the key from an array to a string using a specified\n * delimiter before calling the original set method.\n * @param {number[]} key - The key parameter is an array of numbers.\n * @param {V} value - The value parameter is the value that you want to associate with the specified key.\n * @returns The `set` method is returning the result of calling the `set` method of the superclass\n * (`super.set(key.join(this._joint), value)`).\n */\n override set(key: number[], value: V) {\n return super.set(key.join(this._joint), value);\n }\n\n /**\n * The function overrides the get method to join the key array with a specified joint and then calls the super get\n * method.\n * @param {number[]} key - An array of numbers\n * @returns The code is returning the value associated with the specified key in the map.\n */\n override get(key: number[]) {\n return super.get(key.join(this._joint));\n }\n\n /**\n * The function overrides the delete method and joins the key array using a specified joint character before calling\n * the super delete method.\n * @param {number[]} key - An array of numbers that represents the key to be deleted.\n * @returns The `delete` method is returning the result of calling the `delete` method on the superclass, with the\n * `key` array joined together using the `_joint` property.\n */\n override delete(key: number[]) {\n return super.delete(key.join(this._joint));\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nexport class CoordinateSet extends Set<any> {\n constructor(joint?: string) {\n super();\n if (joint !== undefined) this._joint = joint;\n }\n\n protected _joint = '_';\n\n get joint(): string {\n return this._joint;\n }\n\n /**\n * The \"has\" function overrides the \"has\" method of the superclass and checks if a value exists in an array after\n * joining its elements with a specified separator.\n * @param {number[]} value - The parameter \"value\" is an array of numbers.\n * @returns The overridden `has` method is returning the result of calling the `has` method of the superclass, passing\n * in the joined value as an argument.\n */\n override has(value: number[]) {\n return super.has(value.join(this._joint));\n }\n\n /**\n * The \"add\" function overrides the parent class's \"add\" function by joining the elements of the input array with a\n * specified delimiter before calling the parent class's \"add\" function.\n * @param {number[]} value - An array of numbers\n * @returns The overridden `add` method is returning the result of calling the `add` method of the superclass\n * (`super.add`) with the joined string representation of the `value` array (`value.join(this._joint)`).\n */\n override add(value: number[]) {\n return super.add(value.join(this._joint));\n }\n\n /**\n * The function overrides the delete method and deletes an element from a Set by joining the elements of the input\n * array with a specified joint and then calling the delete method of the parent class.\n * @param {number[]} value - An array of numbers\n * @returns The `delete` method is returning the result of calling the `delete` method of the superclass, with the\n * `value` array joined together using the `_joint` property.\n */\n override delete(value: number[]) {\n return super.delete(value.join(this._joint));\n }\n}\n","export class TreeMap {}\n","export class TreeSet {}\n","import {HashFunction} from '../../types';\n\n/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nexport class HashMap<K, V> {\n /**\n * The constructor initializes the properties of a hash table, including the initial capacity, load factor, capacity\n * multiplier, size, table array, and hash function.\n * @param [initialCapacity=16] - The initial capacity is the initial size of the hash table. It determines the number of\n * buckets or slots available for storing key-value pairs. The default value is 16.\n * @param [loadFactor=0.75] - The load factor is a measure of how full the hash table can be before it is resized. It is\n * a value between 0 and 1, where 1 means the hash table is completely full and 0 means it is completely empty. When the\n * load factor is reached, the hash table will\n * @param [hashFn] - The `hashFn` parameter is an optional parameter that represents the hash function used to calculate\n * the index of a key in the hash table. If a custom hash function is not provided, a default hash function is used. The\n * default hash function converts the key to a string, calculates the sum of the\n */\n constructor(initialCapacity = 16, loadFactor = 0.75, hashFn?: HashFunction<K>) {\n this._initialCapacity = initialCapacity;\n this._loadFactor = loadFactor;\n this._capacityMultiplier = 2;\n this._size = 0;\n this._table = new Array(initialCapacity);\n this._hashFn =\n hashFn ||\n ((key: K) => {\n const strKey = String(key);\n let hash = 0;\n for (let i = 0; i < strKey.length; i++) {\n hash += strKey.charCodeAt(i);\n }\n return hash % this.table.length;\n });\n }\n\n protected _initialCapacity: number;\n\n get initialCapacity(): number {\n return this._initialCapacity;\n }\n\n protected _loadFactor: number;\n\n get loadFactor(): number {\n return this._loadFactor;\n }\n\n protected _capacityMultiplier: number;\n\n get capacityMultiplier(): number {\n return this._capacityMultiplier;\n }\n\n protected _size: number;\n\n get size(): number {\n return this._size;\n }\n\n protected _table: Array<Array<[K, V]>>;\n\n get table(): Array<Array<[K, V]>> {\n return this._table;\n }\n\n protected _hashFn: HashFunction<K>;\n\n get hashFn(): HashFunction<K> {\n return this._hashFn;\n }\n\n set(key: K, value: V): void {\n const loadFactor = this.size / this.table.length;\n if (loadFactor >= this.loadFactor) {\n this.resizeTable(this.table.length * this.capacityMultiplier);\n }\n\n const index = this._hash(key);\n if (!this.table[index]) {\n this.table[index] = [];\n }\n\n // Check if the key already exists in the bucket\n for (let i = 0; i < this.table[index].length; i++) {\n if (this.table[index][i][0] === key) {\n this.table[index][i][1] = value;\n return;\n }\n }\n\n this.table[index].push([key, value]);\n this._size++;\n }\n\n get(key: K): V | undefined {\n const index = this._hash(key);\n if (!this.table[index]) {\n return undefined;\n }\n\n for (const [k, v] of this.table[index]) {\n if (k === key) {\n return v;\n }\n }\n\n return undefined;\n }\n\n delete(key: K): void {\n const index = this._hash(key);\n if (!this.table[index]) {\n return;\n }\n\n for (let i = 0; i < this.table[index].length; i++) {\n if (this.table[index][i][0] === key) {\n this.table[index].splice(i, 1);\n this._size--;\n\n // Check if the table needs to be resized down\n const loadFactor = this.size / this.table.length;\n if (loadFactor < this.loadFactor / this.capacityMultiplier) {\n this.resizeTable(this.table.length / this.capacityMultiplier);\n }\n return;\n }\n }\n }\n\n *entries(): IterableIterator<[K, V]> {\n for (const bucket of this.table) {\n if (bucket) {\n for (const [key, value] of bucket) {\n yield [key, value];\n }\n }\n }\n }\n\n [Symbol.iterator](): IterableIterator<[K, V]> {\n return this.entries();\n }\n\n clear(): void {\n this._size = 0;\n this._table = new Array(this.initialCapacity);\n }\n\n isEmpty(): boolean {\n return this.size === 0;\n }\n\n protected _hash(key: K): number {\n return this._hashFn(key);\n }\n\n /**\n * The `resizeTable` function resizes the table used in a hash map by creating a new table with a specified capacity and\n * rehashing the key-value pairs from the old table into the new table.\n * @param {number} newCapacity - The newCapacity parameter is the desired capacity for the resized table. It represents\n * the number of buckets that the new table should have.\n */\n protected resizeTable(newCapacity: number): void {\n const newTable = new Array(newCapacity);\n for (const bucket of this._table) {\n // Note that this is this._table\n if (bucket) {\n for (const [key, value] of bucket) {\n const newIndex = this._hash(key) % newCapacity;\n if (!newTable[newIndex]) {\n newTable[newIndex] = [];\n }\n newTable[newIndex].push([key, value]);\n }\n }\n }\n this._table = newTable; // Again, here is this._table\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nexport class SinglyLinkedListNode<E = any> {\n value: E;\n next: SinglyLinkedListNode<E> | null;\n\n /**\n * The constructor function initializes an instance of a class with a given value and sets the next property to null.\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 this.value = value;\n this.next = null;\n }\n}\n\nexport class SinglyLinkedList<E = any> {\n /**\n * The constructor initializes the linked list with an empty head, tail, and length.\n */\n constructor() {\n this._head = null;\n this._tail = null;\n this._length = 0;\n }\n\n protected _head: SinglyLinkedListNode<E> | null;\n\n get head(): SinglyLinkedListNode<E> | null {\n return this._head;\n }\n\n protected _tail: SinglyLinkedListNode<E> | null;\n\n get tail(): SinglyLinkedListNode<E> | null {\n return this._tail;\n }\n\n protected _length: number;\n\n get length(): number {\n return this._length;\n }\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 * The `push` function adds a new node with the given value to the end of a singly linked list.\n * @param {E} value - The \"value\" parameter represents the value that you want to add to the linked list. It can be of\n * any type (E) as specified in the generic type declaration of the class or function.\n */\n push(value: E): void {\n const newNode = new SinglyLinkedListNode(value);\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 }\n\n /**\n * The `push` function adds a new node with the given value to the end of a singly linked list.\n * @param {E} value - The \"value\" parameter represents the value that you want to add to the linked list. It can be of\n * any type (E) as specified in the generic type declaration of the class or function.\n */\n addLast(value: E): void {\n this.push(value);\n }\n\n /**\n * The `pop()` function removes and returns the value of the last element in a linked list, updating the head and tail\n * pointers accordingly.\n * @returns The method `pop()` returns the value of the node that is being removed from the end of the linked list. If\n * the linked list is empty, it returns `null`.\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 = null;\n this._tail = null;\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 = null;\n this._tail = current;\n this._length--;\n return value;\n }\n\n /**\n * The `popLast()` function removes and returns the value of the last element in a linked list, updating the head and tail\n * pointers accordingly.\n * @returns The method `pop()` returns the value of the node that is being removed from the end of the linked list. If\n * the linked list is empty, it returns `null`.\n */\n popLast(): E | undefined {\n return this.pop();\n }\n\n /**\n * The `shift()` function removes and returns the value of the first node in a linked list.\n * @returns The value of the node that is being removed from the beginning of the linked list.\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 * The `popFirst()` function removes and returns the value of the first node in a linked list.\n * @returns The value of the node that is being removed from the beginning of the linked list.\n */\n popFirst(): E | undefined {\n return this.shift();\n }\n\n /**\n * The unshift function adds a new node with the given value to the beginning of a singly linked list.\n * @param {E} value - The parameter \"value\" represents the value of the new node that will be added to the beginning of the\n * linked list.\n */\n unshift(value: E): void {\n const newNode = new SinglyLinkedListNode(value);\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 }\n\n /**\n * The addFirst function adds a new node with the given value to the beginning of a singly linked list.\n * @param {E} value - The parameter \"value\" represents the value of the new node that will be added to the beginning of the\n * linked list.\n */\n addFirst(value: E): void {\n this.unshift(value);\n }\n\n /**\n * The function `getAt` returns the value at a specified index in a linked list, or null 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 `getAt(index: number): E | null` returns the value at the specified index in the linked list, or\n * `null` if the index is out of bounds.\n */\n getAt(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 * 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 `null` if the index is out of bounds.\n */\n getNodeAt(index: number): SinglyLinkedListNode<E> | null {\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 * 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 `null` if the index is out of\n * bounds.\n */\n deleteAt(index: number): E | undefined {\n if (index < 0 || index >= this.length) return undefined;\n if (index === 0) return this.shift();\n if (index === this.length - 1) return this.pop();\n\n const prevNode = this.getNodeAt(index - 1);\n const removedNode = prevNode!.next;\n prevNode!.next = removedNode!.next;\n this._length--;\n return removedNode!.value;\n }\n\n /**\n * The delete function removes a node with a specific value from a singly linked list.\n * @param {E | SinglyLinkedListNode<E>} valueOrNode - The `valueOrNode` 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(valueOrNode: E | SinglyLinkedListNode<E> | null | undefined): boolean {\n if (!valueOrNode) return false;\n let value: E;\n if (valueOrNode instanceof SinglyLinkedListNode) {\n value = valueOrNode.value;\n } else {\n value = valueOrNode;\n }\n let current = this.head,\n prev = null;\n\n while (current) {\n if (current.value === value) {\n if (prev === null) {\n this._head = current.next;\n if (current === this.tail) {\n this._tail = null;\n }\n } else {\n prev.next = current.next;\n if (current === this.tail) {\n this._tail = prev;\n }\n }\n this._length--;\n return true;\n }\n prev = current;\n current = current.next;\n }\n\n return false;\n }\n\n /**\n * The `insertAt` function inserts a value at a specified index in a singly linked list.\n * @param {number} index - The index parameter represents the position at which the new value should be inserted in the\n * linked list. It is of type number.\n * @param {E} value - The `value` parameter represents the value that you want to insert into the linked list at the\n * specified index.\n * @returns The `insert` method returns a boolean value. It returns `true` if the insertion is successful, and `false`\n * if the index is out of bounds.\n */\n insertAt(index: number, value: E): boolean {\n if (index < 0 || index > this.length) return false;\n if (index === 0) {\n this.unshift(value);\n return true;\n }\n if (index === this.length) {\n this.push(value);\n return true;\n }\n\n const newNode = new SinglyLinkedListNode(value);\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 * 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 * The `clear` function resets the linked list by setting the head, tail, and length to null and 0 respectively.\n */\n clear(): void {\n this._head = null;\n this._tail = null;\n this._length = 0;\n }\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 const array: E[] = [];\n let current = this.head;\n while (current) {\n array.push(current.value);\n current = current.next;\n }\n return array;\n }\n\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(): void {\n if (!this.head || this.head === this.tail) return;\n\n let prev: SinglyLinkedListNode<E> | null = null;\n let current: SinglyLinkedListNode<E> | null = this.head;\n let next: SinglyLinkedListNode<E> | null = null;\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 }\n\n /**\n * The `find` function iterates through a linked list and returns the first element that satisfies a given condition.\n * @param callback - A function that takes a value of type E as its parameter and returns a boolean value. This\n * function is used to determine whether a particular value in the linked list satisfies a certain condition.\n * @returns The method `find` returns the first element in the linked list that satisfies the condition specified by\n * the callback function. If no element satisfies the condition, it returns `null`.\n */\n find(callback: (value: E) => boolean): E | null {\n let current = this.head;\n while (current) {\n if (callback(current.value)) {\n return current.value;\n }\n current = current.next;\n }\n return null;\n }\n\n /**\n * The `indexOf` function returns the index of the first occurrence of a given value in a linked list.\n * @param {E} value - The value parameter is the value that you want to find the index of in the linked list.\n * @returns The method is returning the index of the first occurrence of the specified value in the linked list. If the\n * value is not found, it returns -1.\n */\n indexOf(value: E): number {\n let index = 0;\n let current = this.head;\n\n while (current) {\n if (current.value === value) {\n return index;\n }\n index++;\n current = current.next;\n }\n\n return -1;\n }\n\n /**\n * The function finds a node in a singly linked list by its value and returns the node if found, otherwise returns\n * null.\n * @param {E} value - The value parameter is the value that we want to search for in the linked list.\n * @returns a `SinglyLinkedListNode<E>` if a node with the specified value is found in the linked list. If no node with\n * the specified value is found, the function returns `null`.\n */\n getNode(value: E): SinglyLinkedListNode<E> | null {\n let current = this.head;\n\n while (current) {\n if (current.value === value) {\n return current;\n }\n current = current.next;\n }\n\n return null;\n }\n\n /**\n * The `insertBefore` function inserts a new value before an existing value in a singly linked list.\n * @param {E | SinglyLinkedListNode<E>} existingValueOrNode - The existing value or node that you want to insert the\n * new value before. It can be either the value itself or a node containing the value in the linked list.\n * @param {E} newValue - The `newValue` parameter represents the value that you want to insert into the linked list.\n * @returns The method `insertBefore` returns a boolean value. It returns `true` if the new value was successfully\n * inserted before the existing value, and `false` otherwise.\n */\n insertBefore(existingValueOrNode: E | SinglyLinkedListNode<E>, newValue: E): boolean {\n if (!this.head) return false;\n\n let existingValue: E;\n if (existingValueOrNode instanceof SinglyLinkedListNode) {\n existingValue = existingValueOrNode.value;\n } else {\n existingValue = existingValueOrNode;\n }\n if (this.head.value === existingValue) {\n this.unshift(newValue);\n return true;\n }\n\n let current = this.head;\n while (current.next) {\n if (current.next.value === existingValue) {\n const newNode = new SinglyLinkedListNode(newValue);\n newNode.next = current.next;\n current.next = newNode;\n this._length++;\n return true;\n }\n current = current.next;\n }\n\n return false;\n }\n\n /**\n * The `insertAfter` function inserts a new node with a given value after an existing node in a singly linked list.\n * @param {E | SinglyLinkedListNode<E>} existingValueOrNode - The existing value or node in the linked list after which\n * the new value will be inserted. It can be either the value of the existing node or the existing node itself.\n * @param {E} newValue - The value that you want to insert into the linked list after the existing value or node.\n * @returns The method returns a boolean value. It returns true if the new value was successfully inserted after the\n * existing value or node, and false if the existing value or node was not found in the linked list.\n */\n insertAfter(existingValueOrNode: E | SinglyLinkedListNode<E>, newValue: E): boolean {\n let existingNode: E | SinglyLinkedListNode<E> | null;\n\n if (existingValueOrNode instanceof SinglyLinkedListNode) {\n existingNode = existingValueOrNode;\n } else {\n existingNode = this.getNode(existingValueOrNode);\n }\n\n if (existingNode) {\n const newNode = new SinglyLinkedListNode(newValue);\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 * The function counts the number of occurrences of a given value in a linked list.\n * @param {E} value - The value parameter is the value that you want to count the occurrences of in the linked list.\n * @returns The count of occurrences of the given value in the linked list.\n */\n countOccurrences(value: E): number {\n let count = 0;\n let current = this.head;\n\n while (current) {\n if (current.value === value) {\n count++;\n }\n current = current.next;\n }\n\n return count;\n }\n\n /**\n * The `forEach` function iterates over each element in a linked list and applies a callback function to each element.\n * @param callback - The callback parameter is a function that takes two arguments: value and index. The value argument\n * represents the value of the current node in the linked list, and the index argument represents the index of the\n * current node in the linked list.\n */\n forEach(callback: (value: E, index: number) => void): void {\n let current = this.head;\n let index = 0;\n while (current) {\n callback(current.value, index);\n current = current.next;\n index++;\n }\n }\n\n /**\n * The `map` function takes a callback function and applies it to each element in the SinglyLinkedList, returning a new\n * SinglyLinkedList with the transformed values.\n * @param callback - The callback parameter is a function that takes a value of type E (the type of values stored in\n * the original SinglyLinkedList) and returns a value of type U (the type of values that will be stored in the mapped\n * SinglyLinkedList).\n * @returns The `map` function is returning a new instance of `SinglyLinkedList<U>` that contains the mapped values.\n */\n map<U>(callback: (value: E) => U): SinglyLinkedList<U> {\n const mappedList = new SinglyLinkedList<U>();\n let current = this.head;\n while (current) {\n mappedList.push(callback(current.value));\n current = current.next;\n }\n return mappedList;\n }\n\n /**\n * The `filter` function iterates through a SinglyLinkedList and returns a new SinglyLinkedList containing only the\n * elements that satisfy the given callback function.\n * @param callback - The `callback` parameter is a function that takes a value of type `E` and returns a boolean value.\n * It is used to determine whether a value should be included in the filtered list or not.\n * @returns The filtered list, which is an instance of the SinglyLinkedList class.\n */\n filter(callback: (value: E) => boolean): SinglyLinkedList<E> {\n const filteredList = new SinglyLinkedList<E>();\n let current = this.head;\n while (current) {\n if (callback(current.value)) {\n filteredList.push(current.value);\n }\n current = current.next;\n }\n return filteredList;\n }\n\n /**\n * The `reduce` function iterates over a linked list and applies a callback function to each element, accumulating a\n * single value.\n * @param callback - The `callback` parameter is a function that takes two arguments: `accumulator` and `value`. It is\n * used to perform a specific operation on each element of the linked list.\n * @param {U} initialValue - The `initialValue` parameter is the initial value of the accumulator. It is the starting\n * point for the reduction operation.\n * @returns The `reduce` method is returning the final value of the accumulator after iterating through all the\n * elements in the linked list.\n */\n reduce<U>(callback: (accumulator: U, value: E) => U, initialValue: U): U {\n let accumulator = initialValue;\n let current = this.head;\n while (current) {\n accumulator = callback(accumulator, current.value);\n current = current.next;\n }\n return accumulator;\n }\n\n /**\n * The function returns an iterator that iterates over the values of a linked list.\n */\n *[Symbol.iterator]() {\n let current = this.head;\n\n while (current) {\n yield current.value;\n current = current.next;\n }\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nexport class DoublyLinkedListNode<E = any> {\n value: E;\n next: DoublyLinkedListNode<E> | null;\n prev: DoublyLinkedListNode<E> | null;\n\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 this.value = value;\n this.next = null;\n this.prev = null;\n }\n}\n\nexport class DoublyLinkedList<E = any> {\n /**\n * The constructor initializes the linked list with an empty head, tail, and length.\n */\n constructor() {\n this._head = null;\n this._tail = null;\n this._length = 0;\n }\n\n protected _head: DoublyLinkedListNode<E> | null;\n\n get head(): DoublyLinkedListNode<E> | null {\n return this._head;\n }\n\n protected _tail: DoublyLinkedListNode<E> | null;\n\n get tail(): DoublyLinkedListNode<E> | null {\n return this._tail;\n }\n\n protected _length: number;\n\n get length(): number {\n return this._length;\n }\n\n get size(): number {\n return this.length;\n }\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 const doublyLinkedList = new DoublyLinkedList<E>();\n for (const item of data) {\n doublyLinkedList.push(item);\n }\n return doublyLinkedList;\n }\n\n /**\n * The push function adds a new node with the given value to the end of the doubly linked list.\n * @param {E} value - The value to be added to the linked list.\n */\n push(value: E): void {\n const newNode = new DoublyLinkedListNode(value);\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 }\n\n /**\n * The addLast function adds a new node with the given value to the end of the doubly linked list.\n * @param {E} value - The value to be added to the linked list.\n */\n addLast(value: E): void {\n this.push(value);\n }\n\n /**\n * The `pop()` function removes and returns the value of the last node in a doubly linked list.\n * @returns The method is returning the value of the removed node (removedNode.value) if the list is not empty. If the\n * list is empty, it returns null.\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 = null;\n this._tail = null;\n } else {\n this._tail = removedNode.prev;\n this.tail!.next = null;\n }\n this._length--;\n return removedNode.value;\n }\n\n /**\n * The `popLast()` function removes and returns the value of the last node in a doubly linked list.\n * @returns The method is returning the value of the removed node (removedNode.value) if the list is not empty. If the\n * list is empty, it returns null.\n */\n popLast(): E | undefined {\n return this.pop();\n }\n\n /**\n * The `shift()` function removes and returns the value of the first node in a doubly linked list.\n * @returns The method `shift()` returns the value of the node that is removed from the beginning of the doubly linked\n * list.\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 = null;\n this._tail = null;\n } else {\n this._head = removedNode.next;\n this.head!.prev = null;\n }\n this._length--;\n return removedNode.value;\n }\n\n /**\n * The `popFirst()` function removes and returns the value of the first node in a doubly linked list.\n * @returns The method `shift()` returns the value of the node that is removed from the beginning of the doubly linked\n * list.\n */\n popFirst(): E | undefined {\n return this.shift();\n }\n\n /**\n * The unshift function adds a new node with the given value to the beginning of a doubly linked list.\n * @param {E} value - The `value` parameter represents the value of the new node that will be added to the beginning of the\n * doubly linked list.\n */\n unshift(value: E): void {\n const newNode = new DoublyLinkedListNode(value);\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 }\n\n /**\n * The addFirst function adds a new node with the given value to the beginning of a doubly linked list.\n * @param {E} value - The `value` parameter represents the value of the new node that will be added to the beginning of the\n * doubly linked list.\n */\n addFirst(value: E): void {\n this.unshift(value);\n }\n\n /**\n * The `getFirst` function returns the first node in a doubly linked list, or null if the list is empty.\n * @returns The method `getFirst()` returns the first node of the doubly linked list, or `null` if the list is empty.\n */\n getFirst(): E | undefined {\n return this.head?.value;\n }\n\n /**\n * The `getLast` function returns the last node in a doubly linked list, or null if the list is empty.\n * @returns The method `getLast()` returns the last node of the doubly linked list, or `null` if the list is empty.\n */\n getLast(): E | undefined {\n return this.tail?.value;\n }\n\n /**\n * The `getAt` function returns the value at a specified index in a linked list, or null 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 null.\n */\n getAt(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 * The function `getNodeAt` returns the node at a given index in a doubly linked list, or null 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 `null`.\n */\n getNodeAt(index: number): DoublyLinkedListNode<E> | null {\n if (index < 0 || index >= this.length) return null;\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 * The function `findNodeByValue` searches for a node with a specific value in a doubly linked list and returns the\n * node if found, otherwise it returns null.\n * @param {E} value - The `value` parameter is the value that we want to search for in the doubly linked list.\n * @returns The function `findNodeByValue` returns a `DoublyLinkedListNode<E>` if a node with the specified value `value`\n * is found in the linked list. If no such node is found, it returns `null`.\n */\n getNode(value: E | null): DoublyLinkedListNode<E> | null {\n let current = this.head;\n\n while (current) {\n if (current.value === value) {\n return current;\n }\n current = current.next;\n }\n\n return null;\n }\n\n /**\n * The `insert` function inserts a value at a specified index in a doubly linked list.\n * @param {number} index - The index parameter represents the position at which the new value should be inserted in the\n * DoublyLinkedList. It is of type number.\n * @param {E} value - The `value` parameter represents the value that you want to insert into the Doubly Linked List at the\n * specified index.\n * @returns The `insert` method returns a boolean value. It returns `true` if the insertion is successful, and `false`\n * if the index is out of bounds.\n */\n insertAt(index: number, value: E): boolean {\n if (index < 0 || index > this.length) return false;\n if (index === 0) {\n this.unshift(value);\n return true;\n }\n if (index === this.length) {\n this.push(value);\n return true;\n }\n\n const newNode = new DoublyLinkedListNode(value);\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 * The `insertBefore` function inserts a new value before an existing value or node in a doubly linked list.\n * @param {E | DoublyLinkedListNode<E>} existingValueOrNode - The existing value or node in the doubly linked list\n * before which the new value will be inserted. It can be either the value of the existing node or the existing node\n * itself.\n * @param {E} newValue - The `newValue` parameter represents the value that you want to insert into the doubly linked\n * list.\n * @returns The method returns a boolean value. It returns `true` if the insertion is successful, and `false` if the\n * insertion fails.\n */\n insertBefore(existingValueOrNode: E | DoublyLinkedListNode<E>, newValue: E): boolean {\n let existingNode;\n\n if (existingValueOrNode instanceof DoublyLinkedListNode) {\n existingNode = existingValueOrNode;\n } else {\n existingNode = this.getNode(existingValueOrNode);\n }\n\n if (existingNode) {\n const newNode = new DoublyLinkedListNode(newValue);\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 * 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 `null` if the index is out of\n * bounds.\n */\n deleteAt(index: number): E | undefined {\n if (index < 0 || index >= this.length) return undefined;\n if (index === 0) return this.shift();\n if (index === this.length - 1) return this.pop();\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 * The `delete` function removes a node from a doubly linked list based on either the node itself or its value.\n * @param {E | DoublyLinkedListNode<E>} valOrNode - The `valOrNode` parameter can accept either a value of type `E` or\n * a `DoublyLinkedListNode<E>` object.\n * @returns The `delete` method returns a boolean value. It returns `true` if the value or node was successfully\n * deleted from the doubly linked list, and `false` if the value or node was not found in the list.\n */\n delete(valOrNode: E | DoublyLinkedListNode<E> | null): boolean {\n let node: DoublyLinkedListNode<E> | null;\n\n if (valOrNode instanceof DoublyLinkedListNode) {\n node = valOrNode;\n } else {\n node = this.getNode(valOrNode);\n }\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 prevNode!.next = nextNode;\n nextNode!.prev = prevNode;\n this._length--;\n }\n return true;\n }\n return false;\n }\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 const array: E[] = [];\n let current = this.head;\n while (current) {\n array.push(current.value);\n current = current.next;\n }\n return array;\n }\n\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 * The `clear` function resets the linked list by setting the head, tail, and length to null and 0 respectively.\n */\n clear(): void {\n this._head = null;\n this._tail = null;\n this._length = 0;\n }\n\n /**\n * The `find` function iterates through a linked list and returns the first element that satisfies a given condition.\n * @param callback - A function that takes a value of type E as its parameter and returns a boolean value. This\n * function is used to determine whether a particular value in the linked list satisfies a certain condition.\n * @returns The method `find` returns the first element in the linked list that satisfies the condition specified by\n * the callback function. If no element satisfies the condition, it returns `null`.\n */\n find(callback: (value: E) => boolean): E | null {\n let current = this.head;\n while (current) {\n if (callback(current.value)) {\n return current.value;\n }\n current = current.next;\n }\n return null;\n }\n\n /**\n * The function returns the index of the first occurrence of a given value in a linked list.\n * @param {E} value - The parameter `value` is of type `E`, which means it can be any data type. It represents the value\n * that we are searching for in the linked list.\n * @returns The method `indexOf` returns the index of the first occurrence of the specified value `value` in the linked\n * list. If the value is not found, it returns -1.\n */\n indexOf(value: E): number {\n let index = 0;\n let current = this.head;\n while (current) {\n if (current.value === value) {\n return index;\n }\n index++;\n current = current.next;\n }\n return -1;\n }\n\n /**\n * The `findBackward` function iterates through a linked list from the last node to the first node and returns the last\n * value that satisfies the given callback function, or null if no value satisfies the callback.\n * @param callback - A function that takes a value of type E as its parameter and returns a boolean value. This\n * function is used to determine whether a given value satisfies a certain condition.\n * @returns The method `findBackward` returns the last value in the linked list that satisfies the condition specified by\n * the callback function. If no value satisfies the condition, it returns `null`.\n */\n findBackward(callback: (value: E) => boolean): E | null {\n let current = this.tail;\n while (current) {\n if (callback(current.value)) {\n return current.value;\n }\n current = current.prev;\n }\n return null;\n }\n\n /**\n * The `toArrayBackward` function converts a doubly linked list into an array in reverse order.\n * @returns The `toArrayBackward()` function returns an array of type `E[]`.\n */\n toArrayBackward(): E[] {\n const array: E[] = [];\n let current = this.tail;\n while (current) {\n array.push(current.value);\n current = current.prev;\n }\n return array;\n }\n\n /**\n * The `reverse` function reverses the order of the elements in a doubly linked list.\n */\n reverse(): void {\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 }\n\n /**\n * The `forEach` function iterates over each element in a linked list and applies a callback function to each element.\n * @param callback - The callback parameter is a function that takes two arguments: value and index. The value argument\n * represents the value of the current node in the linked list, and the index argument represents the index of the\n * current node in the linked list.\n */\n forEach(callback: (value: E, index: number) => void): void {\n let current = this.head;\n let index = 0;\n while (current) {\n callback(current.value, index);\n current = current.next;\n index++;\n }\n }\n\n /**\n * The `map` function takes a callback function and applies it to each element in the DoublyLinkedList, returning a new\n * DoublyLinkedList with the transformed values.\n * @param callback - The callback parameter is a function that takes a value of type E (the type of values stored in\n * the original DoublyLinkedList) and returns a value of type U (the type of values that will be stored in the mapped\n * DoublyLinkedList).\n * @returns The `map` function is returning a new instance of `DoublyLinkedList<U>` that contains the mapped values.\n */\n map<U>(callback: (value: E) => U): DoublyLinkedList<U> {\n const mappedList = new DoublyLinkedList<U>();\n let current = this.head;\n while (current) {\n mappedList.push(callback(current.value));\n current = current.next;\n }\n return mappedList;\n }\n\n /**\n * The `filter` function iterates through a DoublyLinkedList and returns a new DoublyLinkedList containing only the\n * elements that satisfy the given callback function.\n * @param callback - The `callback` parameter is a function that takes a value of type `E` and returns a boolean value.\n * It is used to determine whether a value should be included in the filtered list or not.\n * @returns The filtered list, which is an instance of the DoublyLinkedList class.\n */\n filter(callback: (value: E) => boolean): DoublyLinkedList<E> {\n const filteredList = new DoublyLinkedList<E>();\n let current = this.head;\n while (current) {\n if (callback(current.value)) {\n filteredList.push(current.value);\n }\n current = current.next;\n }\n return filteredList;\n }\n\n /**\n * The `reduce` function iterates over a linked list and applies a callback function to each element, accumulating a\n * single value.\n * @param callback - The `callback` parameter is a function that takes two arguments: `accumulator` and `value`. It is\n * used to perform a specific operation on each element of the linked list.\n * @param {U} initialValue - The `initialValue` parameter is the initial value of the accumulator. It is the starting\n * point for the reduction operation.\n * @returns The `reduce` method is returning the final value of the accumulator after iterating through all the\n * elements in the linked list.\n */\n reduce<U>(callback: (accumulator: U, value: E) => U, initialValue: U): U {\n let accumulator = initialValue;\n let current = this.head;\n while (current) {\n accumulator = callback(accumulator, current.value);\n current = current.next;\n }\n return accumulator;\n }\n\n /**\n * The `insertAfter` function inserts a new node with a given value after an existing node in a doubly linked list.\n * @param {E | DoublyLinkedListNode<E>} existingValueOrNode - The existing value or node in the doubly linked list\n * after which the new value will be inserted. It can be either the value of the existing node or the existing node\n * itself.\n * @param {E} newValue - The value that you want to insert into the doubly linked list.\n * @returns The method returns a boolean value. It returns true if the insertion is successful, and false if the\n * existing value or node is not found in the doubly linked list.\n */\n insertAfter(existingValueOrNode: E | DoublyLinkedListNode<E>, newValue: E): boolean {\n let existingNode;\n\n if (existingValueOrNode instanceof DoublyLinkedListNode) {\n existingNode = existingValueOrNode;\n } else {\n existingNode = this.getNode(existingValueOrNode);\n }\n\n if (existingNode) {\n const newNode = new DoublyLinkedListNode(newValue);\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 * The function returns an iterator that iterates over the values of a linked list.\n */\n *[Symbol.iterator]() {\n let current = this.head;\n\n while (current) {\n yield current.value;\n current = current.next;\n }\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\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\nexport class SkipList<K, V> {\n /**\n * The constructor initializes a SkipList with a specified maximum level and probability.\n * @param [maxLevel=16] - The `maxLevel` parameter represents the maximum level that a skip list can have. It determines\n * the maximum number of levels that can be created in the skip list.\n * @param [probability=0.5] - The probability parameter represents the probability of a node being promoted to a higher\n * level in the skip list. It is used to determine the height of each node in the skip list.\n */\n constructor(maxLevel = 16, probability = 0.5) {\n this._head = new SkipListNode<K, V>(null as any, null as any, maxLevel);\n this._level = 0;\n this._maxLevel = maxLevel;\n this._probability = probability;\n }\n\n protected _head: SkipListNode<K, V>;\n\n get head(): SkipListNode<K, V> {\n return this._head;\n }\n\n protected _level: number;\n\n get level(): number {\n return this._level;\n }\n\n protected _maxLevel: number;\n\n get maxLevel(): number {\n return this._maxLevel;\n }\n\n protected _probability: number;\n\n get probability(): number {\n return this._probability;\n }\n\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] !== null) {\n this._level = Math.max(this.level, newNode.forward.length);\n }\n }\n\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 has(key: K): boolean {\n return this.get(key) !== undefined;\n }\n\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] === null) {\n this._level--;\n }\n return true;\n }\n\n return false;\n }\n\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 getFirst(): V | undefined {\n const firstNode = this.head.forward[0];\n return firstNode ? firstNode.value : undefined;\n }\n\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 getLast(): 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 * 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 * 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 = null;\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 * 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 * @license MIT\n * @copyright Tyler Zeng <zrwusa@gmail.com>\n * @class\n */\nexport class Stack<E = any> {\n /**\n * The constructor initializes an array of elements, which can be provided as an optional parameter.\n * @param {E[]} [elements] - The `elements` parameter is an optional parameter of type `E[]`, which represents an array\n * of elements of type `E`. It is used to initialize the `_elements` property of the class. If the `elements` parameter\n * is provided and is an array, it is assigned to the `_elements\n */\n constructor(elements?: E[]) {\n this._elements = Array.isArray(elements) ? elements : [];\n }\n\n protected _elements: E[];\n\n get elements(): E[] {\n return this._elements;\n }\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 * 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 * The size() function returns the number of elements in an array.\n * @returns The size of the elements array.\n */\n size(): number {\n return this.elements.length;\n }\n\n /**\n * The `peek` function returns the last element of an array, or null if the array is empty.\n * @returns The `peek()` function returns the last element of the `_elements` array, or `null` if the array is empty.\n */\n peek(): E | null {\n if (this.isEmpty()) return null;\n\n return this.elements[this.elements.length - 1];\n }\n\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): Stack<E> {\n this.elements.push(element);\n return this;\n }\n\n /**\n * The `pop` function removes and returns the last element from an array, or returns null 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 `null`.\n */\n pop(): E | null {\n if (this.isEmpty()) return null;\n\n return this.elements.pop() || null;\n }\n\n /**\n * The toArray function returns a copy of the elements in an array.\n * @returns An array of type E.\n */\n toArray(): E[] {\n return this.elements.slice();\n }\n\n /**\n * The clear function clears the elements array.\n */\n clear(): void {\n this._elements = [];\n }\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> {\n return new Stack(this.elements.slice());\n }\n}\n","/**\n * @license MIT\n * @copyright Tyler Zeng <zrwusa@gmail.com>\n * @class\n */\nimport {SinglyLinkedList} from '../linked-list';\n\nexport class LinkedListQueue<E = any> extends SinglyLinkedList<E> {\n /**\n * The enqueue function adds a value to the end of an array.\n * @param {E} value - The value parameter represents the value that you want to add to the queue.\n */\n enqueue(value: E) {\n this.push(value);\n }\n\n /**\n * The `dequeue` function removes and returns the first element from a queue, or returns null if the queue is empty.\n * @returns The method is returning the element at the front of the queue, or null if the queue is empty.\n */\n dequeue(): E | undefined {\n return this.shift();\n }\n\n /**\n * The `getFirst` function returns the value of the head node in a linked list, or `undefined` if the list is empty.\n * @returns The `getFirst()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`.\n */\n getFirst(): E | undefined {\n return this.head?.value;\n }\n\n /**\n * The `peek` function returns the value of the head node in a linked list, or `undefined` if the list is empty.\n * @returns The `peek()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`.\n */\n peek(): E | undefined {\n return this.getFirst();\n }\n}\n\nexport class Queue<E = any> {\n /**\n * The constructor initializes an instance of a class with an optional array of elements and sets the offset to 0.\n * @param {E[]} [elements] - The `elements` parameter is an optional array of elements of type `E`. If provided, it\n * will be used to initialize the `_nodes` property of the class. If not provided, the `_nodes` property will be\n * initialized as an empty array.\n */\n constructor(elements?: E[]) {\n this._nodes = elements || [];\n this._offset = 0;\n }\n\n protected _nodes: E[];\n\n get nodes(): E[] {\n return this._nodes;\n }\n\n protected _offset: number;\n\n get offset(): number {\n return this._offset;\n }\n\n /**\n * The size function returns the number of elements in an array.\n * @returns {number} The size of the array, which is the difference between the length of the array and the offset.\n */\n get size(): number {\n return this.nodes.length - this.offset;\n }\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 * @static\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 * The push function adds an element to the end of the queue and returns the updated queue.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 The `add` method is returning a `Queue<E>` object.\n */\n push(element: E): Queue<E> {\n this.nodes.push(element);\n return this;\n }\n\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 `null` if the queue is empty.\n */\n shift(): E | undefined {\n if (this.size === 0) return undefined;\n\n const first = this.getFirst();\n this._offset += 1;\n\n if (this.offset * 2 < this.nodes.length) return first;\n\n // only delete dequeued elements when reaching half size\n // to decrease latency of shifting elements.\n this._nodes = this.nodes.slice(this.offset);\n this._offset = 0;\n return first;\n }\n\n /**\n * The `getFirst` function returns the first element of the array `_nodes` if it exists, otherwise it returns `null`.\n * @returns The `getFirst()` method returns the first element of the data structure, represented by the `_nodes` array at\n * the `_offset` index. If the data structure is empty (size is 0), it returns `null`.\n */\n getFirst(): E | undefined {\n return this.size > 0 ? this.nodes[this.offset] : undefined;\n }\n\n /**\n * The `peek` function returns the first element of the array `_nodes` if it exists, otherwise it returns `null`.\n * @returns The `peek()` method returns the first element of the data structure, represented by the `_nodes` array at\n * the `_offset` index. If the data structure is empty (size is 0), it returns `null`.\n */\n peek(): E | undefined {\n return this.getFirst();\n }\n\n /**\n * The `getLast` function returns the last element in an array-like data structure, or null if the structure is empty.\n * @returns The method `getLast()` returns the last element of the `_nodes` array if the array is not empty. If the\n * array is empty, it returns `null`.\n */\n getLast(): E | undefined {\n return this.size > 0 ? this.nodes[this.nodes.length - 1] : undefined;\n }\n\n /**\n * The `peekLast` function returns the last element in an array-like data structure, or null if the structure is empty.\n * @returns The method `peekLast()` returns the last element of the `_nodes` array if the array is not empty. If the\n * array is empty, it returns `null`.\n */\n peekLast(): E | undefined {\n return this.getLast();\n }\n\n /**\n * The enqueue function adds a value to the end of a queue.\n * @param {E} value - The value parameter represents the value that you want to add to the queue.\n */\n enqueue(value: E) {\n this.push(value);\n }\n\n /**\n * The `dequeue` function removes and returns the first element from a queue, or returns null if the queue is empty.\n * @returns The method is returning a value of type E or null.\n */\n dequeue(): E | undefined {\n return this.shift();\n }\n\n getAt(index: number): E | undefined {\n return this.nodes[index];\n }\n\n /**\n * The function checks if a data structure is empty by comparing its size to zero.\n * @returns {boolean} 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 * The toArray() function returns an array of elements from the current offset to the end of the _nodes array.\n * @returns An array of type E is being returned.\n */\n toArray(): E[] {\n return this.nodes.slice(this.offset);\n }\n\n /**\n * The clear function resets the nodes array and offset to their initial values.\n */\n clear(): void {\n this._nodes = [];\n this._offset = 0;\n }\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(): Queue<E> {\n return new Queue(this.nodes.slice(this.offset));\n }\n\n *[Symbol.iterator]() {\n for (const item of this.nodes) {\n yield item;\n }\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport {DoublyLinkedList} from '../linked-list';\n\n// O(n) time complexity of obtaining the value\n// O(1) time complexity of adding at the beginning and the end\nexport class Deque<E = any> extends DoublyLinkedList<E> {}\n\n// O(1) time complexity of obtaining the value\n// O(n) time complexity of adding at the beginning and the end\n// todo tested slowest one\nexport class ObjectDeque<E = number> {\n constructor(capacity?: number) {\n if (capacity !== undefined) this._capacity = capacity;\n }\n\n protected _nodes: {[key: number]: E} = {};\n\n get nodes(): {[p: number]: E} {\n return this._nodes;\n }\n\n protected _capacity = Number.MAX_SAFE_INTEGER;\n\n get capacity(): number {\n return this._capacity;\n }\n\n protected _first = -1;\n\n get first(): number {\n return this._first;\n }\n\n protected _last = -1;\n\n get last(): number {\n return this._last;\n }\n\n protected _size = 0;\n\n get size(): number {\n return this._size;\n }\n\n /**\n * The \"addFirst\" function adds a value to the beginning of an array-like data structure.\n * @param {E} value - The `value` parameter represents the value that you want to add to the beginning of the data\n * structure.\n */\n addFirst(value: E) {\n if (this.size === 0) {\n const mid = Math.floor(this.capacity / 2);\n this._first = mid;\n this._last = mid;\n } else {\n this._first--;\n }\n this.nodes[this.first] = value;\n this._size++;\n }\n\n /**\n * The addLast function adds a value to the end of an array-like data structure.\n * @param {E} value - The `value` parameter represents the value that you want to add to the end of the data structure.\n */\n addLast(value: E) {\n if (this.size === 0) {\n const mid = Math.floor(this.capacity / 2);\n this._first = mid;\n this._last = mid;\n } else {\n this._last++;\n }\n this.nodes[this.last] = value;\n this._size++;\n }\n\n /**\n * The function `popFirst()` removes and returns the first element in a data structure.\n * @returns The value of the first element in the data structure.\n */\n popFirst() {\n if (!this.size) return;\n const value = this.getFirst();\n delete this.nodes[this.first];\n this._first++;\n this._size--;\n return value;\n }\n\n /**\n * The `getFirst` function returns the first element in an array-like data structure if it exists.\n * @returns The element at the first position of the `_nodes` array.\n */\n getFirst() {\n if (this.size) return this.nodes[this.first];\n }\n\n /**\n * The `popLast()` function removes and returns the last element in a data structure.\n * @returns The value that was removed from the data structure.\n */\n popLast() {\n if (!this.size) return;\n const value = this.getLast();\n delete this.nodes[this.last];\n this._last--;\n this._size--;\n\n return value;\n }\n\n /**\n * The `getLast()` function returns the last element in an array-like data structure.\n * @returns The last element in the array \"_nodes\" is being returned.\n */\n getLast() {\n if (this.size) return this.nodes[this.last];\n }\n\n /**\n * The get function returns the element at the specified index in an array-like data structure.\n * @param {number} index - The index parameter is a number that represents the position of the element you want to\n * retrieve from the array.\n * @returns The element at the specified index in the `_nodes` array is being returned. If there is no element at that\n * index, `null` is returned.\n */\n get(index: number) {\n return this.nodes[this.first + index] || null;\n }\n\n /**\n * The function checks if the size of a data structure is less than or equal to zero.\n * @returns The method is returning a boolean value indicating whether the size of the object is less than or equal to 0.\n */\n isEmpty() {\n return this.size <= 0;\n }\n}\n\n// O(1) time complexity of obtaining the value\n// O(n) time complexity of adding at the beginning and the end\nexport class ArrayDeque<E> {\n protected _nodes: E[] = [];\n\n get nodes(): E[] {\n return this._nodes;\n }\n\n get size() {\n return this.nodes.length;\n }\n\n /**\n * O(n) time complexity of adding at the beginning and the end\n */\n\n /**\n * The function \"addLast\" adds a value to the end of an array.\n * @param {E} value - The value parameter represents the value that you want to add to the end of the array.\n * @returns The return value is the new length of the array after the value has been added.\n */\n addLast(value: E) {\n return this.nodes.push(value);\n }\n\n /**\n * The function \"popLast\" returns and removes the last element from an array, or returns null if the array is empty.\n * @returns The method `popLast()` returns the last element of the `_nodes` array, or `null` if the array is empty.\n */\n popLast(): E | null {\n return this.nodes.pop() ?? null;\n }\n\n /**\n * The `popFirst` function removes and returns the first element from an array, or returns null if the array is empty.\n * @returns The `popFirst()` function returns the first element of the `_nodes` array, or `null` if the array is\n * empty.\n */\n popFirst(): E | null {\n return this.nodes.shift() ?? null;\n }\n\n /**\n * O(n) time complexity of adding at the beginning and the end\n */\n\n /**\n * The function \"addFirst\" adds a value to the beginning of an array.\n * @param {E} value - The value parameter represents the value that you want to add to the beginning of the array.\n * @returns The return value of the `addFirst` function is the new length of the array `_nodes` after adding the\n * `value` at the beginning.\n */\n addFirst(value: E) {\n return this.nodes.unshift(value);\n }\n\n /**\n * The `getFirst` function returns the first element of an array or null if the array is empty.\n * @returns The function `getFirst()` is returning the first element (`E`) of the `_nodes` array. If the array is\n * empty, it will return `null`.\n */\n getFirst(): E | null {\n return this.nodes[0] ?? null;\n }\n\n /**\n * The `getLast` function returns the last element of an array or null if the array is empty.\n * @returns The method `getLast()` returns the last element of the `_nodes` array, or `null` if the array is empty.\n */\n getLast(): E | null {\n return this.nodes[this.nodes.length - 1] ?? null;\n }\n\n /**\n * O(1) time complexity of obtaining the value\n */\n\n /**\n * The get function returns the element at the specified index in an array, or null if the index is out of bounds.\n * @param {number} index - The index parameter is a number that represents the position of the element you want to\n * retrieve from the array.\n * @returns The method is returning the element at the specified index in the `_nodes` array. If the element exists, it\n * will be returned. If the element does not exist (i.e., the index is out of bounds), `null` will be returned.\n */\n get(index: number): E | null {\n return this.nodes[index] ?? null;\n }\n\n /**\n * The set function assigns a value to a specific index in an array.\n * @param {number} index - The index parameter is a number that represents the position of the element in the array\n * that you want to set a new value for.\n * @param {E} value - The value parameter represents the new value that you want to set at the specified index in the\n * _nodes array.\n * @returns The value that is being set at the specified index in the `_nodes` array.\n */\n set(index: number, value: E) {\n return (this.nodes[index] = value);\n }\n\n /**\n * The insert function adds a value at a specified index in an array.\n * @param {number} index - The index parameter specifies the position at which the value should be inserted in the\n * array. It is a number that represents the index of the array where the value should be inserted. The index starts\n * from 0, so the first element of the array has an index of 0, the second element has\n * @param {E} value - The value parameter represents the value that you want to insert into the array at the specified\n * index.\n * @returns The splice method returns an array containing the removed elements, if any. In this case, since no elements\n * are being removed, an empty array will be returned.\n */\n insert(index: number, value: E) {\n return this.nodes.splice(index, 0, value);\n }\n\n /**\n * The delete function removes an element from an array at a specified index.\n * @param {number} index - The index parameter specifies the position of the element to be removed from the array. It\n * is a number that represents the index of the element to be removed.\n * @returns The method is returning an array containing the removed element.\n */\n delete(index: number) {\n return this.nodes.splice(index, 1);\n }\n\n /**\n * The function checks if an array called \"_nodes\" is empty.\n * @returns The method `isEmpty()` is returning a boolean value. It returns `true` if the length of the `_nodes` array\n * is 0, indicating that the array is empty. Otherwise, it returns `false`.\n */\n isEmpty() {\n return this.nodes.length === 0;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type {Thunk, ToThunkFn, TrlAsyncFn, TrlFn} from '../types';\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\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\nexport const isThunk = (fnOrValue: any) => {\n return typeof fnOrValue === 'function' && fnOrValue.__THUNK__ === THUNK_SYMBOL;\n};\n\nexport const toThunk = (fn: ToThunkFn): Thunk => {\n const thunk = () => fn();\n thunk.__THUNK__ = THUNK_SYMBOL;\n return thunk;\n};\n\nexport const trampoline = (fn: TrlFn) => {\n const cont = (...args: [...Parameters<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\nexport const trampolineAsync = (fn: TrlAsyncFn) => {\n const cont = (...args: [...Parameters<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\nexport const getMSB = (value: number): number => {\n if (value <= 0) {\n return 0;\n }\n return 1 << (31 - Math.clz32(value));\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} from '../../types';\n\nexport class Heap<E = any> {\n constructor(options: {comparator: Comparator<E>; nodes?: E[]}) {\n this._comparator = options.comparator;\n if (options.nodes && options.nodes.length > 0) {\n this._nodes = options.nodes;\n this.fix();\n }\n }\n\n protected _nodes: E[] = [];\n\n get nodes(): E[] {\n return this._nodes;\n }\n\n protected _comparator: Comparator<E>;\n\n get comparator(): Comparator<E> {\n return this._comparator;\n }\n\n /**\n * Get the size (number of elements) of the heap.\n */\n get size(): number {\n return this.nodes.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.nodes[this.size - 1] ?? undefined;\n }\n\n /**\n * Static method that creates a binary heap from an array of nodes and a comparison function.\n * @returns A new Heap instance.\n * @param options\n */\n static heapify<E>(options: {nodes: E[]; comparator: Comparator<E>}): Heap<E> {\n return new Heap<E>(options);\n }\n\n /**\n * Insert an element into the heap and maintain the heap properties.\n * @param element - The element to be inserted.\n */\n add(element: E): Heap<E> {\n return this.push(element);\n }\n\n /**\n * Insert an element into the heap and maintain the heap properties.\n * @param element - The element to be inserted.\n */\n push(element: E): Heap<E> {\n this.nodes.push(element);\n this.bubbleUp(this.nodes.length - 1);\n return this;\n }\n\n /**\n * Remove and return the top element (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.nodes.length === 0) {\n return undefined;\n }\n if (this.nodes.length === 1) {\n return this.nodes.pop() as E;\n }\n\n const topValue = this.nodes[0];\n this.nodes[0] = this.nodes.pop() as E;\n this.sinkDown(0);\n return topValue;\n }\n\n /**\n * Remove and return the top element (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 return this.poll();\n }\n\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 if (this.nodes.length === 0) {\n return undefined;\n }\n return this.nodes[0];\n }\n\n /**\n * Check if the heap is empty.\n * @returns True if the heap is empty, otherwise false.\n */\n isEmpty() {\n return this.size === 0;\n }\n\n /**\n * Reset the nodes of the heap. Make the nodes empty.\n */\n clear() {\n this._nodes = [];\n }\n\n /**\n * Clear and add nodes of the heap\n * @param nodes\n */\n refill(nodes: E[]) {\n this._nodes = nodes;\n this.fix();\n }\n\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 has(element: E): boolean {\n return this.nodes.includes(element);\n }\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): E[] {\n const result: E[] = [];\n\n // Auxiliary recursive function, traverses the binary heap according to the traversal order\n const dfsHelper = (index: number) => {\n if (index < this.size) {\n if (order === 'in') {\n dfsHelper(2 * index + 1);\n result.push(this.nodes[index]);\n dfsHelper(2 * index + 2);\n } else if (order === 'pre') {\n result.push(this.nodes[index]);\n dfsHelper(2 * index + 1);\n dfsHelper(2 * index + 2);\n } else if (order === 'post') {\n dfsHelper(2 * index + 1);\n dfsHelper(2 * index + 2);\n result.push(this.nodes[index]);\n }\n }\n };\n\n dfsHelper(0); // Traverse starting from the root node\n\n return result;\n }\n\n /**\n * Convert the heap to an array.\n * @returns An array containing the elements of the heap.\n */\n toArray(): E[] {\n return [...this.nodes];\n }\n\n getNodes(): E[] {\n return this.nodes;\n }\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> {\n const clonedHeap = new Heap<E>({comparator: this.comparator});\n clonedHeap._nodes = [...this.nodes];\n return clonedHeap;\n }\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 = this.clone();\n while (cloned.size !== 0) {\n const top = cloned.poll();\n if (top) visitedNode.push(top);\n }\n return visitedNode;\n }\n\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): void {\n const element = this.nodes[index];\n while (index > 0) {\n const parentIndex = Math.floor((index - 1) / 2);\n const parent = this.nodes[parentIndex];\n if (this.comparator(element, parent) < 0) {\n this.nodes[index] = parent;\n this.nodes[parentIndex] = element;\n index = parentIndex;\n } else {\n break;\n }\n }\n }\n\n /**\n * Sinking operation to maintain heap properties after removing the top element.\n * @param index - The index from which to start sinking.\n */\n protected sinkDown(index: number): void {\n const leftChildIndex = 2 * index + 1;\n const rightChildIndex = 2 * index + 2;\n const length = this.nodes.length;\n let targetIndex = index;\n\n if (leftChildIndex < length && this.comparator(this.nodes[leftChildIndex], this.nodes[targetIndex]) < 0) {\n targetIndex = leftChildIndex;\n }\n if (rightChildIndex < length && this.comparator(this.nodes[rightChildIndex], this.nodes[targetIndex]) < 0) {\n targetIndex = rightChildIndex;\n }\n\n if (targetIndex !== index) {\n const temp = this.nodes[index];\n this.nodes[index] = this.nodes[targetIndex];\n this.nodes[targetIndex] = temp;\n this.sinkDown(targetIndex);\n }\n }\n\n /**\n * Fix the entire heap to maintain heap properties.\n */\n protected fix() {\n for (let i = Math.floor(this.size / 2); i >= 0; i--) this.sinkDown(i);\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 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 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 get root(): FibonacciHeapNode<E> | undefined {\n return this._root;\n }\n\n protected _size = 0;\n\n get size(): number {\n return this._size;\n }\n\n protected _min?: FibonacciHeapNode<E>;\n\n get min(): FibonacciHeapNode<E> | undefined {\n return this._min;\n }\n\n protected _comparator: Comparator<E>;\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 * O(1) time operation.\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 * O(1) time operation.\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 * O(1) time operation.\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 * O(1) time operation.\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 nodes of the linked list.\n */\n consumeLinkedList(head?: FibonacciHeapNode<E>): FibonacciHeapNode<E>[] {\n const nodes: FibonacciHeapNode<E>[] = [];\n if (!head) return nodes;\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 nodes.push(node);\n node = node.right;\n }\n }\n\n return nodes;\n }\n\n /**\n * O(log n) time operation.\n * Remove and return the top element (smallest or largest element) from the heap.\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 * O(log n) time operation.\n * Remove and return the top element (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 * O(log n) time operation.\n * Remove and return the top element (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 nodes = this.consumeLinkedList(z.child);\n for (const node of nodes) {\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 * O(log n) time operation.\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 * 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 * Create a new node.\n * @param element\n * @protected\n */\n protected createNode(element: E): FibonacciHeapNode<E> {\n return new FibonacciHeapNode<E>(element);\n }\n\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 * O(log n) time operation.\n * Remove and return the top element (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 * O(log n) time operation.\n * Remove and return the top element (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 * O(log n) time operation.\n * Remove and return the top element (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 nodes = 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 nodes) {\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 */\n\nimport {Heap} from './heap';\nimport type {Comparator} from '../../types';\n\nexport class MaxHeap<E = any> extends Heap<E> {\n constructor(\n options: {comparator: Comparator<E>; nodes?: E[]} = {\n comparator: (a: E, b: E) => {\n if (!(typeof a === 'number' && typeof b === 'number')) {\n throw new Error('The a, b params of compare function must be number');\n } else {\n return b - a;\n }\n }\n }\n ) {\n super(options);\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 */\n\nimport {Heap} from './heap';\nimport type {Comparator} from '../../types';\n\nexport class MinHeap<E = any> extends Heap<E> {\n constructor(\n options: {comparator: Comparator<E>; nodes?: E[]} = {\n comparator: (a: E, b: E) => {\n if (!(typeof a === 'number' && typeof b === 'number')) {\n throw new Error('The a, b params of compare function must be number');\n } else {\n return a - b;\n }\n }\n }\n ) {\n super(options);\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 */\n\nimport {Heap} from '../heap';\nimport {Comparator} from '../../types';\n\nexport class PriorityQueue<E = any> extends Heap<E> {\n constructor(options: {comparator: Comparator<E>; nodes?: E[]}) {\n super(options);\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 {PriorityQueue} from './priority-queue';\nimport type {Comparator} from '../../types';\n\nexport class MinPriorityQueue<E = any> extends PriorityQueue<E> {\n constructor(\n options: {comparator: Comparator<E>; nodes?: E[]} = {\n comparator: (a: E, b: E) => {\n if (!(typeof a === 'number' && typeof b === 'number')) {\n throw new Error('The a, b params of compare function must be number');\n } else {\n return a - b;\n }\n }\n }\n ) {\n super(options);\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 {PriorityQueue} from './priority-queue';\nimport type {Comparator} from '../../types';\n\nexport class MaxPriorityQueue<E = any> extends PriorityQueue<E> {\n constructor(\n options: {comparator: Comparator<E>; nodes?: E[]} = {\n comparator: (a: E, b: E) => {\n if (!(typeof a === 'number' && typeof b === 'number')) {\n throw new Error('The a, b params of compare function must be number');\n } else {\n return b - a;\n }\n }\n }\n ) {\n super(options);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport {uuidV4} from '../../utils';\nimport {PriorityQueue} from '../priority-queue';\nimport type {DijkstraResult, VertexKey} from '../../types';\nimport {IGraph} from '../../interfaces';\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> implements IGraph<V, E, VO, EO>\n{\n protected _vertices: Map<VertexKey, VO> = new Map<VertexKey, VO>();\n\n get vertices(): Map<VertexKey, VO> {\n return this._vertices;\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 | null;\n\n abstract getEdge(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | null;\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] | null;\n\n /**\n * The function \"getVertex\" returns the vertex with the specified ID or null 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 `_vertices` map.\n * @returns The method `getVertex` returns the vertex with the specified `vertexKey` if it exists in the `_vertices`\n * map. If the vertex does not exist, it returns `null`.\n */\n getVertex(vertexKey: VertexKey): VO | null {\n return this._vertices.get(vertexKey) || null;\n }\n\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._vertices.has(this._getVertexKey(vertexOrKey));\n }\n\n addVertex(vertex: VO): boolean;\n\n addVertex(key: VertexKey, value?: V): boolean;\n\n addVertex(keyOrVertex: VertexKey | VO, value?: V): boolean {\n if (keyOrVertex instanceof AbstractVertex) {\n return this._addVertexOnly(keyOrVertex);\n } else {\n const newVertex = this.createVertex(keyOrVertex, value);\n return this._addVertexOnly(newVertex);\n }\n }\n\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 const vertexKey = this._getVertexKey(vertexOrKey);\n return this._vertices.delete(vertexKey);\n }\n\n /**\n * The function removes all vertices from a graph and returns a boolean indicating if any vertices were removed.\n * @param {VO[] | VertexKey[]} vertices - The `vertices` parameter can be either an array of vertices (`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 vertices\n * were removed.\n */\n removeManyVertices(vertices: VO[] | VertexKey[]): boolean {\n const removed: boolean[] = [];\n for (const v of vertices) {\n removed.push(this.deleteVertex(v));\n }\n return removed.length > 0;\n }\n\n /**\n * The function checks if there is an edge between two vertices 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 addEdge(srcOrEdge: VO | VertexKey | EO, dest?: VO | VertexKey, weight?: number, value?: E): boolean {\n if (srcOrEdge instanceof AbstractEdge) {\n return this._addEdgeOnly(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._addEdgeOnly(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 * The function sets the weight of an edge between two vertices 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 vertices, 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 * The function `getAllPathsBetween` finds all paths between two vertices 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 vertices (`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 * The function calculates the sum of weights along a given path.\n * @param {VO[]} path - An array of vertices (VO) representing a path in a graph.\n * @returns The function `getPathSumWeight` returns the sum of the weights of the edges 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 * The function `getMinCostBetween` calculates the minimum cost between two vertices 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 edges 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 edges. 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 vertices (`v1`\n * and `v2`). If the `isWeight` parameter is `true`, it calculates the minimum weight among all paths between the\n * vertices. 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 | null {\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 null;\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.size > 0) {\n for (let i = 0; i < queue.size; 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 null;\n }\n }\n\n /**\n * The function `getMinPathBetween` returns the minimum path between two vertices 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 edges 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 vertices (`VO[]`) representing the minimum path between\n * two vertices (`v1` and `v2`). If there is no path between the vertices, it returns `null`.\n */\n getMinPathBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean, isDFS = false): VO[] | null {\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] || null;\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 * Dijkstra algorithm time: O(VE) space: O(VO + EO)\n * /\n\n /**\n * Dijkstra algorithm time: O(VE) space: O(VO + EO)\n * The function `dijkstraWithoutHeap` implements Dijkstra's algorithm to find the shortest path between two vertices 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 | null} [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 `null`.\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 vertices 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 | null,\n getMinDist?: boolean,\n genPaths?: boolean\n ): DijkstraResult<VO> {\n if (getMinDist === undefined) getMinDist = false;\n if (genPaths === undefined) genPaths = false;\n\n if (dest === undefined) dest = null;\n let minDist = Infinity;\n let minDest: VO | null = null;\n let minPath: VO[] = [];\n const paths: VO[][] = [];\n\n const vertices = this._vertices;\n const distMap: Map<VO, number> = new Map();\n const seen: Set<VO> = new Set();\n const preMap: Map<VO, VO | null> = new Map(); // predecessor\n const srcVertex = this._getVertex(src);\n\n const destVertex = dest ? this._getVertex(dest) : null;\n\n if (!srcVertex) {\n return null;\n }\n\n for (const vertex of vertices) {\n const vertexOrKey = vertex[1];\n if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Infinity);\n }\n distMap.set(srcVertex, 0);\n preMap.set(srcVertex, null);\n\n const getMinOfNoSeen = () => {\n let min = Infinity;\n let minV: VO | null = null;\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 | null) => {\n for (const vertex of vertices) {\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 < vertices.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-null-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 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 genPaths && getPaths(minDest);\n\n return {distMap, preMap, seen, paths, minDist, minPath};\n }\n\n /**\n * Dijkstra algorithm time: O(logVE) space: O(VO + EO)\n *\n * Dijkstra's algorithm only solves the single-source shortest path problem, while the Bellman-Ford algorithm and Floyd-Warshall algorithm can address shortest paths between all pairs of nodes.\n * Dijkstra's algorithm is suitable for graphs with non-negative edge weights, whereas the Bellman-Ford algorithm and Floyd-Warshall algorithm can handle negative-weight edges.\n * The time complexity of Dijkstra's algorithm and the Bellman-Ford algorithm depends on the size of the graph, while the time complexity of the Floyd-Warshall algorithm is O(VO^3), where VO is the number of nodes. For dense graphs, Floyd-Warshall might become slower.\n *\n * /\n\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 | null} [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 vertices 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 vertices 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 | null,\n getMinDist?: boolean,\n genPaths?: boolean\n ): DijkstraResult<VO> {\n if (getMinDist === undefined) getMinDist = false;\n if (genPaths === undefined) genPaths = false;\n\n if (dest === undefined) dest = null;\n let minDist = Infinity;\n let minDest: VO | null = null;\n let minPath: VO[] = [];\n const paths: VO[][] = [];\n const vertices = this._vertices;\n const distMap: Map<VO, number> = new Map();\n const seen: Set<VO> = new Set();\n const preMap: Map<VO, VO | null> = new Map(); // predecessor\n\n const srcVertex = this._getVertex(src);\n const destVertex = dest ? this._getVertex(dest) : null;\n\n if (!srcVertex) return null;\n\n for (const vertex of vertices) {\n const vertexOrKey = vertex[1];\n if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Infinity);\n }\n\n const heap = new PriorityQueue<{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, null);\n\n /**\n * The function `getPaths` retrieves all paths from vertices to a specified minimum vertex.\n * @param {VO | null} minV - The parameter `minV` is of type `VO | null`. It represents the minimum vertex value or\n * null.\n */\n const getPaths = (minV: VO | null) => {\n for (const vertex of vertices) {\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 * BellmanFord time:O(VE) space:O(VO)\n * one to rest pairs\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 edges for several rounds to gradually approximate the shortest paths. Due to its ability to handle negative-weight edges, 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 vertices 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 vertices 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 vertices 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 vertices = this._vertices;\n const numOfVertices = vertices.size;\n const edges = this.edgeSet();\n const numOfEdges = edges.length;\n\n this._vertices.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(edges[j]);\n if (ends) {\n const [s, d] = ends;\n const weight = edges[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 genPath && preMap.set(d, s);\n }\n }\n }\n }\n }\n\n let minDest: VO | null = null;\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 vertices) {\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(edges[j]);\n if (ends) {\n const [s] = ends;\n const weight = edges[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 edges for several rounds to gradually approximate the shortest paths. Due to its ability to handle negative-weight edges, 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 * Floyd algorithm time: O(VO^3) space: O(VO^2), 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 edges, and it can simultaneously compute shortest paths between any two nodes.\n * /\n\n /**\n * Floyd algorithm time: O(VO^3) space: O(VO^2), 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 edges, 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 vertices 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 vertices in a graph. The\n * `predecessor` property is a 2D array of vertices (or `null`) representing the predecessor vertices in the shortest\n * path between vertices in the\n */\n floydWarshall(): {costs: number[][]; predecessor: (VO | null)[][]} {\n const idAndVertices = [...this._vertices];\n const n = idAndVertices.length;\n\n const costs: number[][] = [];\n const predecessor: (VO | null)[][] = [];\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] = null;\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 * Tarjan is an algorithm based on dfs,which is used to solve the connectivity problem of graphs.\n * Tarjan can find cycles in directed or undirected graph\n * Tarjan can find the articulation points and bridges(critical edges) of undirected graphs in linear time,\n * Tarjan solve the bi-connected components of undirected graphs;\n * Tarjan can find the SSC(strongly connected components), articulation points, and bridges of directed graphs.\n * /\n\n /**\n * Tarjan is an algorithm based on dfs,which is used to solve the connectivity problem of graphs.\n * Tarjan can find cycles in directed or undirected graph\n * Tarjan can find the articulation points and bridges(critical edges) of undirected graphs in linear time,\n * Tarjan solve the bi-connected components of undirected graphs;\n * Tarjan can find the SSC(strongly connected components), articulation points, and bridges of directed graphs.\n * The `tarjan` function is used to perform various graph analysis tasks such as finding articulation points, bridges,\n * strongly connected components (SCCs), and cycles in a graph.\n * @param {boolean} [needCutVertexes] - A boolean value indicating whether or not to calculate and return the\n * articulation points in the graph. Articulation points are the vertices in a graph whose removal would increase the\n * number of connected components in the graph.\n * @param {boolean} [needBridges] - A boolean flag indicating whether the algorithm should find and return the bridges\n * (edges whose removal would increase the number of connected components in the graph).\n * @param {boolean} [needSCCs] - A boolean value indicating whether the Strongly Connected Components (SCCs) of the\n * graph are needed. If set to true, the function will calculate and return the SCCs of the graph. If set to false, the\n * SCCs will not be calculated or returned.\n * @param {boolean} [needCycles] - A boolean flag indicating whether the algorithm should find cycles in the graph. If\n * set to true, the algorithm will return a map of cycles, where the keys are the low values of the SCCs and the values\n * are arrays of vertices that form cycles within the SCCs.\n * @returns The function `tarjan` returns an object with the following properties:\n */\n tarjan(\n needCutVertexes: boolean = false,\n needBridges: boolean = false,\n needSCCs: boolean = true,\n needCycles: boolean = false\n ) {\n // !! in undirected graph we will not let child visit parent when dfs\n // !! articulation point(in dfs search tree not in graph): (cur !== root && cur.has(child)) && (low(child) >= dfn(cur)) || (cur === root && cur.children() >= 2)\n // !! bridge: low(child) > dfn(cur)\n\n const defaultConfig = false;\n if (needCutVertexes === undefined) needCutVertexes = defaultConfig;\n if (needBridges === undefined) needBridges = defaultConfig;\n if (needSCCs === undefined) needSCCs = defaultConfig;\n if (needCycles === undefined) needCycles = defaultConfig;\n\n const dfnMap: Map<VO, number> = new Map();\n const lowMap: Map<VO, number> = new Map();\n const vertices = this._vertices;\n vertices.forEach(v => {\n dfnMap.set(v, -1);\n lowMap.set(v, Infinity);\n });\n\n const [root] = vertices.values();\n\n const cutVertexes: VO[] = [];\n const bridges: EO[] = [];\n let dfn = 0;\n const dfs = (cur: VO, parent: VO | null) => {\n dfn++;\n dfnMap.set(cur, dfn);\n lowMap.set(cur, dfn);\n\n const neighbors = this.getNeighbors(cur);\n let childCount = 0; // child in dfs tree not child in graph\n for (const neighbor of neighbors) {\n if (neighbor !== parent) {\n if (dfnMap.get(neighbor) === -1) {\n childCount++;\n dfs(neighbor, cur);\n }\n const childLow = lowMap.get(neighbor);\n const curLow = lowMap.get(cur);\n // TODO after no-non-null-assertion not ensure the logic\n if (curLow !== undefined && childLow !== undefined) {\n lowMap.set(cur, Math.min(curLow, childLow));\n }\n const curFromMap = dfnMap.get(cur);\n if (childLow !== undefined && curFromMap !== undefined) {\n if (needCutVertexes) {\n if ((cur === root && childCount >= 2) || (cur !== root && childLow >= curFromMap)) {\n // todo not ensure the logic if (cur === root && childCount >= 2 || ((cur !== root) && (childLow >= curFromMap))) {\n cutVertexes.push(cur);\n }\n }\n\n if (needBridges) {\n if (childLow > curFromMap) {\n const edgeCurToNeighbor = this.getEdge(cur, neighbor);\n if (edgeCurToNeighbor) {\n bridges.push(edgeCurToNeighbor);\n }\n }\n }\n }\n }\n }\n };\n\n dfs(root, null);\n\n let SCCs: Map<number, VO[]> = new Map();\n\n const getSCCs = () => {\n const SCCs: Map<number, VO[]> = new Map();\n lowMap.forEach((low, vertex) => {\n if (!SCCs.has(low)) {\n SCCs.set(low, [vertex]);\n } else {\n SCCs.get(low)?.push(vertex);\n }\n });\n return SCCs;\n };\n\n if (needSCCs) {\n SCCs = getSCCs();\n }\n\n const cycles: Map<number, VO[]> = new Map();\n if (needCycles) {\n let SCCs: Map<number, VO[]> = new Map();\n if (SCCs.size < 1) {\n SCCs = getSCCs();\n }\n\n SCCs.forEach((SCC, low) => {\n if (SCC.length > 1) {\n cycles.set(low, SCC);\n }\n });\n }\n\n return {dfnMap, lowMap, bridges, cutVertexes, SCCs, cycles};\n }\n\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(false, false, false, false).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(false, false, false, false).lowMap;\n }\n\n /**\n * The function `getCycles` returns a map of cycles found using the Tarjan algorithm.\n * @returns The function `getCycles()` is returning a `Map<number, VO[]>`.\n */\n getCycles(): Map<number, VO[]> {\n return this.tarjan(false, false, false, true).cycles;\n }\n\n /**\n * The function \"getCutVertexes\" returns an array of cut vertexes using the Tarjan algorithm.\n * @returns an array of VO objects, specifically the cut vertexes.\n */\n getCutVertexes(): VO[] {\n return this.tarjan(true, false, false, false).cutVertexes;\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(false, false, true, false).SCCs;\n }\n\n /**\n * The function \"getBridges\" returns an array of bridges using the Tarjan algorithm.\n * @returns the bridges found using the Tarjan algorithm.\n */\n getBridges() {\n return this.tarjan(false, true, false, false).bridges;\n }\n\n protected abstract _addEdgeOnly(edge: EO): boolean;\n\n protected _addVertexOnly(newVertex: VO): boolean {\n if (this.hasVertex(newVertex)) {\n return false;\n // throw (new Error('Duplicated vertex key is not allowed'));\n }\n this._vertices.set(newVertex.key, newVertex);\n return true;\n }\n\n protected _getVertex(vertexOrKey: VertexKey | VO): VO | null {\n const vertexKey = this._getVertexKey(vertexOrKey);\n return this._vertices.get(vertexKey) || null;\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 Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport {arrayRemove} from '../../utils';\nimport {AbstractEdge, AbstractGraph, AbstractVertex} from './abstract-graph';\nimport type {TopologicalStatus, VertexKey} from '../../types';\nimport {IGraph} from '../../interfaces';\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 vertices 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\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 protected _inEdgeMap: Map<VO, EO[]> = new Map<VO, EO[]>();\n\n get inEdgeMap(): Map<VO, EO[]> {\n return this._inEdgeMap;\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 /**\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 vertices.\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 ?? key) as VO;\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 /**\n * The function creates a directed edge between two vertices 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 * The `getEdge` function retrieves an edge between two vertices based on their source and destination IDs.\n * @param {VO | VertexKey | null} srcOrKey - The source vertex or its ID. It can be either a vertex object or a vertex ID.\n * @param {VO | VertexKey | null} 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 `null` if the\n * destination is not specified.\n * @returns the first edge found between the source and destination vertices, or null if no such edge is found.\n */\n getEdge(srcOrKey: VO | VertexKey | null, destOrKey: VO | VertexKey | null): EO | null {\n let edges: EO[] = [];\n\n if (srcOrKey !== null && destOrKey !== null) {\n const src: VO | null = this._getVertex(srcOrKey);\n const dest: VO | null = this._getVertex(destOrKey);\n\n if (src && dest) {\n const srcOutEdges = this._outEdgeMap.get(src);\n if (srcOutEdges) {\n edges = srcOutEdges.filter(edge => edge.dest === dest.key);\n }\n }\n }\n\n return edges[0] || null;\n }\n\n /**\n * The function removes an edge between two vertices 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 null if either the source or destination vertex does not exist.\n */\n deleteEdgeSrcToDest(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | null {\n const src: VO | null = this._getVertex(srcOrKey);\n const dest: VO | null = this._getVertex(destOrKey);\n let removed: EO | null = null;\n if (!src || !dest) {\n return null;\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] || null;\n }\n return removed;\n }\n\n /**\n * The function removes an edge from a graph and returns the removed edge, or null if the edge was not found.\n * @param {EO} edge - The `edge` parameter is an object that represents an edge in a graph. It has two properties: `src`\n * and `dest`, which represent the source and destination vertices of the edge, respectively.\n * @returns The method `deleteEdge` returns the removed edge (`EO`) if it exists, or `null` if the edge does not exist.\n */\n deleteEdge(edge: EO): EO | null {\n let removed: EO | null = null;\n const src = this._getVertex(edge.src);\n const dest = this._getVertex(edge.dest);\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);\n }\n\n const destInEdges = this._inEdgeMap.get(dest);\n if (destInEdges && destInEdges.length > 0) {\n removed = arrayRemove(destInEdges, (edge: EO) => edge.dest === dest.key)[0];\n }\n }\n\n return removed;\n }\n\n /**\n * The function removes edges between two vertices and returns the removed edges.\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 edges (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 v1ToV2 && removed.push(v1ToV2);\n v2ToV1 && removed.push(v2ToV1);\n }\n\n return removed;\n }\n\n /**\n * The function `incomingEdgesOf` returns an array of incoming edges 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 edges (`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 * The function `outgoingEdgesOf` returns an array of outgoing edges 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 edges (`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 * 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 * The function \"inDegreeOf\" returns the number of incoming edges 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 edges of the specified vertex or vertex ID.\n */\n inDegreeOf(vertexOrKey: VertexKey | VO): number {\n return this.incomingEdgesOf(vertexOrKey).length;\n }\n\n /**\n * The function `outDegreeOf` returns the number of outgoing edges 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 edges from the specified vertex or vertex ID.\n */\n outDegreeOf(vertexOrKey: VertexKey | VO): number {\n return this.outgoingEdgesOf(vertexOrKey).length;\n }\n\n /**\n * The function \"edgesOf\" returns an array of both outgoing and incoming edges 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 edges.\n */\n edgesOf(vertexOrKey: VertexKey | VO): EO[] {\n return [...this.outgoingEdgesOf(vertexOrKey), ...this.incomingEdgesOf(vertexOrKey)];\n }\n\n /**\n * The function \"getEdgeSrc\" returns the source vertex of an edge, or null 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 null.\n */\n getEdgeSrc(e: EO): VO | null {\n return this._getVertex(e.src);\n }\n\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 null.\n */\n getEdgeDest(e: EO): VO | null {\n return this._getVertex(e.dest);\n }\n\n /**\n * The function `getDestinations` returns an array of destination vertices connected to a given vertex.\n * @param {VO | VertexKey | null} 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 `null`.\n * @returns an array of vertices (VO[]).\n */\n getDestinations(vertex: VO | VertexKey | null): VO[] {\n if (vertex === null) {\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 * The `topologicalSort` function performs a topological sort on a graph and returns an array of vertices or vertex IDs\n * in the sorted order, or null 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 vertices. It can have two possible values: 'vertex' or 'key'. If 'vertex' is\n * specified, the vertices themselves will be used for sorting. If 'key' is specified, the ids of\n * @returns an array of vertices or vertex IDs in topological order. If there is a cycle in the graph, it returns null.\n */\n topologicalSort(propertyName?: 'vertex' | 'key'): Array<VO | VertexKey> | null {\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.vertices) {\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.vertices) {\n if (statusMap.get(entry[1]) === 0) {\n dfs(entry[1]);\n }\n }\n\n if (hasCycle) return null;\n\n if (propertyName === 'key') sorted = sorted.map(vertex => (vertex instanceof DirectedVertex ? vertex.key : vertex));\n return sorted.reverse();\n }\n\n /**\n * The `edgeSet` function returns an array of all the edges in the graph.\n * @returns The `edgeSet()` method returns an array of edges (`EO[]`).\n */\n edgeSet(): EO[] {\n let edges: EO[] = [];\n this._outEdgeMap.forEach(outEdges => {\n edges = [...edges, ...outEdges];\n });\n return edges;\n }\n\n /**\n * The function `getNeighbors` returns an array of neighboring vertices 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 vertices (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-null-assertion not ensure the logic\n if (neighbor) {\n neighbors.push(neighbor);\n }\n }\n }\n return neighbors;\n }\n\n /**\n * The function \"getEndsOfEdge\" returns the source and destination vertices of an edge if it exists in the graph,\n * otherwise it returns null.\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 vertices `[VO, VO]` if the edge exists in the\n * graph. If the edge does not exist, it returns `null`.\n */\n getEndsOfEdge(edge: EO): [VO, VO] | null {\n if (!this.hasEdge(edge.src, edge.dest)) {\n return null;\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 null;\n }\n }\n\n /**\n * The function `_addEdgeOnly` adds an edge to a graph if the source and destination vertices 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 _addEdgeOnly(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-null-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 Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport {arrayRemove} from '../../utils';\nimport {AbstractEdge, AbstractGraph, AbstractVertex} from './abstract-graph';\nimport type {VertexKey} from '../../types';\nimport {IGraph} from '../../interfaces';\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 vertices: [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.vertices = [v1, v2];\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 edges.\n */\n constructor() {\n super();\n this._edges = new Map<VO, EO[]>();\n }\n\n protected _edges: Map<VO, EO[]>;\n\n get edges(): Map<VO, EO[]> {\n return this._edges;\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 vertices 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 * The function `getEdge` returns the first edge that connects two vertices, or null if no such edge exists.\n * @param {VO | VertexKey | null} v1 - The parameter `v1` represents a vertex or vertex ID. It can be of type `VO` (vertex\n * object), `null`, or `VertexKey` (a string or number representing the ID of a vertex).\n * @param {VO | VertexKey | null} v2 - The parameter `v2` represents a vertex or vertex ID. It can be of type `VO` (vertex\n * object), `null`, or `VertexKey` (vertex ID).\n * @returns an edge (EO) or null.\n */\n getEdge(v1: VO | VertexKey | null, v2: VO | VertexKey | null): EO | null {\n let edges: EO[] | undefined = [];\n\n if (v1 !== null && v2 !== null) {\n const vertex1: VO | null = this._getVertex(v1);\n const vertex2: VO | null = this._getVertex(v2);\n\n if (vertex1 && vertex2) {\n edges = this._edges.get(vertex1)?.filter(e => e.vertices.includes(vertex2.key));\n }\n }\n\n return edges ? edges[0] || null : null;\n }\n\n /**\n * The function removes an edge between two vertices 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 null if either of the vertices (VO) does not exist.\n */\n deleteEdgeBetween(v1: VO | VertexKey, v2: VO | VertexKey): EO | null {\n const vertex1: VO | null = this._getVertex(v1);\n const vertex2: VO | null = this._getVertex(v2);\n\n if (!vertex1 || !vertex2) {\n return null;\n }\n\n const v1Edges = this._edges.get(vertex1);\n let removed: EO | null = null;\n if (v1Edges) {\n removed = arrayRemove<EO>(v1Edges, (e: EO) => e.vertices.includes(vertex2.key))[0] || null;\n }\n const v2Edges = this._edges.get(vertex2);\n if (v2Edges) {\n arrayRemove<EO>(v2Edges, (e: EO) => e.vertices.includes(vertex1.key));\n }\n return removed;\n }\n\n /**\n * The deleteEdge function removes an edge between two vertices in a graph.\n * @param {EO} edge - The parameter \"edge\" is of type EO, which represents an edge in a graph.\n * @returns The method is returning either the removed edge (of type EO) or null if the edge was not found.\n */\n deleteEdge(edge: EO): EO | null {\n return this.deleteEdgeBetween(edge.vertices[0], edge.vertices[1]);\n }\n\n /**\n * The function `degreeOf` returns the degree of a vertex in a graph, which is the number of edges 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 * edges connected to that vertex.\n */\n degreeOf(vertexOrKey: VertexKey | VO): number {\n const vertex = this._getVertex(vertexOrKey);\n if (vertex) {\n return this._edges.get(vertex)?.length || 0;\n } else {\n return 0;\n }\n }\n\n /**\n * The function returns the edges 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 edges.\n */\n edgesOf(vertexOrKey: VertexKey | VO): EO[] {\n const vertex = this._getVertex(vertexOrKey);\n if (vertex) {\n return this._edges.get(vertex) || [];\n } else {\n return [];\n }\n }\n\n /**\n * The function \"edgeSet\" returns an array of unique edges from a set of edges.\n * @returns The method `edgeSet()` returns an array of type `EO[]`.\n */\n edgeSet(): EO[] {\n const edgeSet: Set<EO> = new Set();\n this._edges.forEach(edges => {\n edges.forEach(edge => {\n edgeSet.add(edge);\n });\n });\n return [...edgeSet];\n }\n\n /**\n * The function \"getNeighbors\" returns an array of neighboring vertices 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 vertices (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.vertices.filter(e => e !== vertex.key)[0]);\n if (neighbor) {\n neighbors.push(neighbor);\n }\n }\n }\n return neighbors;\n }\n\n /**\n * The function \"getEndsOfEdge\" returns the vertices at the ends of an edge if the edge exists in the graph, otherwise\n * it returns null.\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 vertices `[VO, VO]` if the edge exists in the\n * graph. If the edge does not exist, it returns `null`.\n */\n getEndsOfEdge(edge: EO): [VO, VO] | null {\n if (!this.hasEdge(edge.vertices[0], edge.vertices[1])) {\n return null;\n }\n const v1 = this._getVertex(edge.vertices[0]);\n const v2 = this._getVertex(edge.vertices[1]);\n if (v1 && v2) {\n return [v1, v2];\n } else {\n return null;\n }\n }\n\n /**\n * The function adds an edge to the graph by updating the adjacency list with the vertices 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 _addEdgeOnly(edge: EO): boolean {\n for (const end of edge.vertices) {\n const endVertex = this._getVertex(end);\n if (endVertex === null) return false;\n if (endVertex) {\n const edges = this._edges.get(endVertex);\n if (edges) {\n edges.push(edge);\n } else {\n this._edges.set(endVertex, [edge]);\n }\n }\n }\n return true;\n }\n}\n","import {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\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 origin and bottomRight properties of a MapGraphCoordinate object.\n * @param {MapGraphCoordinate} origin - The `origin` 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(origin: MapGraphCoordinate, bottomRight?: MapGraphCoordinate) {\n super();\n this._origin = origin;\n this._bottomRight = bottomRight;\n }\n\n protected _origin: MapGraphCoordinate = [0, 0];\n\n get origin(): MapGraphCoordinate {\n return this._origin;\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(key: VertexKey, value?: V, lat: number = this.origin[0], long: number = this.origin[1]): 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","import {BinaryTreeNode} from '../../../data-structures';\n\n/**\n * Enum representing different loop types.\n *\n * - `iterative`: Indicates the iterative loop type (with loops that use iterations).\n * - `recursive`: Indicates the recursive loop type (with loops that call themselves).\n */\n\nexport enum IterationType {\n ITERATIVE = 'ITERATIVE',\n RECURSIVE = 'RECURSIVE'\n}\n\nexport enum FamilyPosition {\n ROOT = 'ROOT',\n LEFT = 'LEFT',\n RIGHT = 'RIGHT',\n ROOT_LEFT = 'ROOT_LEFT',\n ROOT_RIGHT = 'ROOT_RIGHT',\n ISOLATED = 'ISOLATED',\n MAL_NODE = 'MAL_NODE'\n}\n\nexport type BTNKey = number;\n\nexport type BinaryTreeDeletedResult<N> = { deleted: N | null | undefined; needBalanced: N | null | undefined };\n\nexport type BinaryTreeNodeNested<T> = BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\nexport type BinaryTreeOptions = { iterationType?: IterationType }\n","import {RBTreeNode} from '../../../data-structures';\nimport {BSTOptions} from \"./bst\";\n\nexport enum RBTNColor { RED = 1, BLACK = 0}\n\nexport type RBTreeNodeNested<T> = RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\nexport type RBTreeOptions = BSTOptions & {};","// 0 means unknown, 1 means visiting, 2 means visited;\nexport type TopologicalStatus = 0 | 1 | 2;\n\nexport enum TopologicalProperty {\n VAL = 'VAL',\n NODE = 'NODE',\n ID = 'ID'\n}\n","export type Comparator<T> = (a: T, b: T) => number;\n\nexport type DFSOrderPattern = 'pre' | 'in' | 'post';\n\nexport type BTNCallback<N, D = any> = (node: N) => D;\n\nexport enum CP {\n lt = 'lt',\n eq = 'eq',\n gt = 'gt'\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n\nimport type {BinaryTreeNodeNested, BinaryTreeOptions, BTNCallback, BTNKey} from '../../types';\nimport {BinaryTreeDeletedResult, DFSOrderPattern, FamilyPosition, IterationType} from '../../types';\nimport {IBinaryTree} from '../../interfaces';\nimport {trampoline} from '../../utils';\nimport {Queue} from '../queue';\n\n/**\n * Represents a node in a binary tree.\n * @template V - The type of data stored in the node.\n * @template N - The type of the family relationship in the binary tree.\n */\nexport class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>> {\n /**\n * The key associated with the node.\n */\n key: BTNKey;\n\n /**\n * The value stored in the node.\n */\n value: V | undefined;\n\n /**\n * The parent node of the current node.\n */\n parent: N | null | undefined;\n\n /**\n * Creates a new instance of BinaryTreeNode.\n * @param {BTNKey} key - The key associated with the node.\n * @param {V} value - The value stored in the node.\n */\n constructor(key: BTNKey, value?: V) {\n this.key = key;\n this.value = value;\n }\n\n protected _left: N | null | undefined;\n\n /**\n * Get the left child node.\n */\n get left(): N | null | undefined {\n return this._left;\n }\n\n /**\n * Set the left child node.\n * @param {N | null | undefined} v - The left child node.\n */\n set left(v: N | null | undefined) {\n if (v) {\n v.parent = this as unknown as N;\n }\n this._left = v;\n }\n\n protected _right: N | null | undefined;\n\n /**\n * Get the right child node.\n */\n get right(): N | null | undefined {\n return this._right;\n }\n\n /**\n * Set the right child node.\n * @param {N | null | undefined} v - The right child node.\n */\n set right(v: N | null | undefined) {\n if (v) {\n v.parent = this as unknown as N;\n }\n this._right = v;\n }\n\n /**\n * Get the position of the node within its family.\n * @returns {FamilyPosition} - The family position of the node.\n */\n get familyPosition(): FamilyPosition {\n const that = this as unknown as N;\n if (!this.parent) {\n return this.left || this.right ? FamilyPosition.ROOT : FamilyPosition.ISOLATED;\n }\n\n if (this.parent.left === that) {\n return this.left || this.right ? FamilyPosition.ROOT_LEFT : FamilyPosition.LEFT;\n } else if (this.parent.right === that) {\n return this.left || this.right ? FamilyPosition.ROOT_RIGHT : FamilyPosition.RIGHT;\n }\n\n return FamilyPosition.MAL_NODE;\n }\n}\n\n/**\n * Represents a binary tree data structure.\n * @template N - The type of the binary tree's nodes.\n */\nexport class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>>\n implements IBinaryTree<V, N>\n{\n iterationType: IterationType = IterationType.ITERATIVE;\n\n /**\n * Creates a new instance of BinaryTree.\n * @param {BinaryTreeOptions} [options] - The options for the binary tree.\n */\n constructor(options?: BinaryTreeOptions) {\n if (options !== undefined) {\n const {iterationType = IterationType.ITERATIVE} = options;\n this.iterationType = iterationType;\n }\n }\n\n protected _root: N | null | undefined = undefined;\n\n /**\n * Get the root node of the binary tree.\n */\n get root(): N | null | undefined {\n return this._root;\n }\n\n protected _size = 0;\n\n /**\n * Get the number of nodes in the binary tree.\n */\n get size(): number {\n return this._size;\n }\n\n /**\n * Creates a new instance of BinaryTreeNode with the given key and value.\n * @param {BTNKey} key - The key for the new node.\n * @param {V} value - The value for the new node.\n * @returns {N} - The newly created BinaryTreeNode.\n */\n createNode(key: BTNKey, value?: V): N {\n return new BinaryTreeNode<V, N>(key, value) as N;\n }\n\n /**\n * Clear the binary tree, removing all nodes.\n */\n clear() {\n this._setRoot(undefined);\n this._size = 0;\n }\n\n /**\n * Check if the binary tree is empty.\n * @returns {boolean} - True if the binary tree is empty, false otherwise.\n */\n isEmpty(): boolean {\n return this.size === 0;\n }\n\n /**\n * Add a node with the given key and value to the binary tree.\n * @param {BTNKey | N | null} keyOrNode - The key or node to add to the binary tree.\n * @param {V} value - The value for the new node (optional).\n * @returns {N | null | undefined} - The inserted node, or null if nothing was inserted, or undefined if the operation failed.\n */\n add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | null | undefined {\n const _bfs = (root: N, newNode: N | null): N | undefined | null => {\n const queue = new Queue<N | null>([root]);\n while (queue.size > 0) {\n const cur = queue.shift();\n if (cur) {\n if (newNode && cur.key === newNode.key) {\n cur.value = newNode.value;\n return;\n }\n const inserted = this._addTo(newNode, cur);\n if (inserted !== undefined) return inserted;\n if (cur.left) queue.push(cur.left);\n if (cur.right) queue.push(cur.right);\n } else return;\n }\n return;\n };\n\n let inserted: N | null | undefined, needInsert: N | null;\n\n if (keyOrNode === null) {\n needInsert = null;\n } else if (typeof keyOrNode === 'number') {\n needInsert = this.createNode(keyOrNode, value);\n } else if (keyOrNode instanceof BinaryTreeNode) {\n needInsert = keyOrNode;\n } else {\n return;\n }\n\n // const key = typeof keyOrNode === 'number' ? keyOrNode : keyOrNode ? keyOrNode.key : undefined;\n // const existNode = key !== undefined ? this.getNode(key, (node: N) => node.key) : undefined;\n\n if (this.root) {\n // if (existNode) {\n // existNode.value = value;\n // inserted = existNode;\n // } else {\n inserted = _bfs(this.root, needInsert);\n // }\n } else {\n this._setRoot(needInsert);\n if (needInsert !== null) {\n this._size = 1;\n } else {\n this._size = 0;\n }\n inserted = this.root;\n }\n return inserted;\n }\n\n /**\n * The `addMany` function takes an array of binary tree node IDs or nodes, and optionally an array of corresponding data\n * values, and adds them to the binary tree.\n * @param {(BTNKey | null)[] | (N | null)[]} keysOrNodes - An array of BTNKey or BinaryTreeNode\n * objects, or null values.\n * @param {V[]} [values] - The `values` parameter is an optional array of values (`V[]`) that corresponds to\n * the nodes or node IDs being added. It is used to set the value of each node being added. If `values` is not provided,\n * the value of the nodes will be `undefined`.\n * @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.\n */\n addMany(keysOrNodes: (BTNKey | null | undefined)[] | (N | null | undefined)[], values?: V[]): (N | null | undefined)[] {\n // TODO not sure addMany not be run multi times\n return keysOrNodes.map((keyOrNode, i) => {\n if (keyOrNode instanceof BinaryTreeNode) {\n return this.add(keyOrNode.key, keyOrNode.value);\n }\n\n if (keyOrNode === null) {\n return this.add(null);\n }\n\n const value = values?.[i];\n return this.add(keyOrNode, value);\n });\n }\n\n /**\n * The `refill` function clears the binary tree and adds multiple nodes with the given IDs or nodes and optional data.\n * @param {(BTNKey | N)[]} keysOrNodes - The `keysOrNodes` parameter is an array that can contain either\n * `BTNKey` or `N` values.\n * @param {N[] | Array<V>} [data] - The `data` parameter is an optional array of values that will be assigned to\n * the nodes being added. If provided, the length of the `data` array should be equal to the length of the `keysOrNodes`\n * array. Each value in the `data` array will be assigned to the\n * @returns The method is returning a boolean value.\n */\n refill(keysOrNodes: (BTNKey | null | undefined)[] | (N | null | undefined)[], data?: Array<V>): boolean {\n this.clear();\n return keysOrNodes.length === this.addMany(keysOrNodes, data).length;\n }\n\n delete<C extends BTNCallback<N, BTNKey>>(identifier: BTNKey, callback?: C): BinaryTreeDeletedResult<N>[];\n\n delete<C extends BTNCallback<N, N>>(identifier: N | null | undefined, callback?: C): BinaryTreeDeletedResult<N>[];\n\n delete<C extends BTNCallback<N>>(identifier: ReturnType<C>, callback: C): BinaryTreeDeletedResult<N>[];\n\n /**\n * The `delete` function removes a node from a binary search tree and returns the deleted node along\n * with the parent node that needs to be balanced.\n * a key (`BTNKey`). If it is a key, the function will find the corresponding node in the\n * binary tree.\n * @returns an array of `BinaryTreeDeletedResult<N>` objects.\n * @param {ReturnType<C>} identifier - The `identifier` parameter is either a\n * `BTNKey` or a generic type `N`. It represents the property of the node that we are\n * searching for. It can be a specific key value or any other property of the node.\n * @param callback - The `callback` parameter is a function that takes a node as input and returns a\n * value. This value is compared with the `identifier` parameter to determine if the node should be\n * included in the result. The `callback` parameter has a default value of\n * `this.defaultOneParamCallback`, which\n */\n delete<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | null | undefined,\n callback: C = this.defaultOneParamCallback as C\n ): BinaryTreeDeletedResult<N>[] {\n const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];\n if (!this.root) return bstDeletedResult;\n if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;\n\n const curr = this.getNode(identifier, callback);\n if (!curr) return bstDeletedResult;\n\n const parent: N | null | undefined = curr?.parent ? curr.parent : null;\n let needBalanced: N | null | undefined = null,\n orgCurrent = curr;\n\n if (!curr.left) {\n if (!parent) {\n // Handle the case when there's only one root node\n this._setRoot(null);\n } else {\n const {familyPosition: fp} = curr;\n if (fp === FamilyPosition.LEFT || fp === FamilyPosition.ROOT_LEFT) {\n parent.left = curr.right;\n } else if (fp === FamilyPosition.RIGHT || fp === FamilyPosition.ROOT_RIGHT) {\n parent.right = curr.right;\n }\n needBalanced = parent;\n }\n } else {\n const leftSubTreeRightMost = curr.left ? this.getRightMost(curr.left) : null;\n if (leftSubTreeRightMost) {\n const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;\n orgCurrent = this._swap(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 }\n this._size = this.size - 1;\n\n bstDeletedResult.push({deleted: orgCurrent, needBalanced});\n return bstDeletedResult;\n }\n\n /**\n * The function `getDepth` calculates the depth of a given node in a binary tree relative to a\n * specified root node.\n * @param {BTNKey | N | null | undefined} distNode - The `distNode` parameter represents the node\n * whose depth we want to find in the binary tree. It can be either a node object (`N`), a key value\n * of the node (`BTNKey`), or `null`.\n * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the\n * starting node from which we want to calculate the depth. It can be either a node object or the key\n * of a node in the binary tree. If no value is provided for `beginRoot`, it defaults to the root\n * node of the binary tree.\n * @returns the depth of the `distNode` relative to the `beginRoot`.\n */\n getDepth(distNode: BTNKey | N | null | undefined, beginRoot: BTNKey | N | null | undefined = this.root): number {\n if (typeof distNode === 'number') distNode = this.getNode(distNode);\n if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);\n let depth = 0;\n while (distNode?.parent) {\n if (distNode === beginRoot) {\n return depth;\n }\n depth++;\n distNode = distNode.parent;\n }\n return depth;\n }\n\n /**\n * The `getHeight` function calculates the maximum height of a binary tree using either recursive or\n * iterative approach.\n * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the\n * starting node from which the height of the binary tree is calculated. It can be either a node\n * object (`N`), a key value of a node in the tree (`BTNKey`), or `null` if no starting\n * node is specified. If `\n * @param iterationType - The `iterationType` parameter is used to determine whether to calculate the\n * height of the binary tree using a recursive approach or an iterative approach. It can have two\n * possible values:\n * @returns the height of the binary tree.\n */\n getHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): number {\n if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);\n if (!beginRoot) return -1;\n\n if (iterationType === IterationType.RECURSIVE) {\n const _getMaxHeight = (cur: N | null | undefined): number => {\n if (!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(beginRoot);\n } else {\n if (!beginRoot) {\n return -1;\n }\n\n const stack: {node: N; depth: number}[] = [{node: beginRoot, depth: 0}];\n let maxHeight = 0;\n\n while (stack.length > 0) {\n const {node, depth} = stack.pop()!;\n\n if (node.left) {\n stack.push({node: node.left, depth: depth + 1});\n }\n\n if (node.right) {\n stack.push({node: node.right, depth: depth + 1});\n }\n\n maxHeight = Math.max(maxHeight, depth);\n }\n\n return maxHeight;\n }\n }\n\n /**\n * The `getMinHeight` function calculates the minimum height of a binary tree using either a\n * recursive or iterative approach.\n * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which we want to\n * calculate the minimum height of the tree. It is optional and defaults to the root of the tree if\n * not provided.\n * @param iterationType - The `iterationType` parameter is used to determine the method of iteration\n * to calculate the minimum height of a binary tree. It can have two possible values:\n * @returns The function `getMinHeight` returns the minimum height of a binary tree.\n */\n getMinHeight(beginRoot: N | null | undefined = this.root, iterationType = this.iterationType): number {\n if (!beginRoot) return -1;\n\n if (iterationType === IterationType.RECURSIVE) {\n const _getMinHeight = (cur: N | null | undefined): number => {\n if (!cur) return 0;\n if (!cur.left && !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(beginRoot);\n } else {\n const stack: N[] = [];\n let node: N | null | undefined = beginRoot,\n last: N | null | undefined = null;\n const depths: Map<N, number> = new Map();\n\n while (stack.length > 0 || node) {\n if (node) {\n stack.push(node);\n 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 leftMinHeight = node.left ? depths.get(node.left) ?? -1 : -1;\n const rightMinHeight = node.right ? depths.get(node.right) ?? -1 : -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(beginRoot) ?? -1;\n }\n }\n\n /**\n * The function checks if a binary tree is perfectly balanced by comparing the minimum height and the\n * height of the tree.\n * @param {N | null | undefined} beginRoot - The parameter `beginRoot` is of type `N | null | undefined`, which means it can\n * either be of type `N` (representing a node in a tree) or `null` (representing an empty tree).\n * @returns The method is returning a boolean value.\n */\n isPerfectlyBalanced(beginRoot: N | null | undefined = this.root): boolean {\n return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);\n }\n\n getNodes<C extends BTNCallback<N, BTNKey>>(\n identifier: BTNKey,\n callback?: C,\n onlyOne?: boolean,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): N[];\n\n getNodes<C extends BTNCallback<N, N>>(\n identifier: N | null | undefined,\n callback?: C,\n onlyOne?: boolean,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): N[];\n\n getNodes<C extends BTNCallback<N>>(\n identifier: ReturnType<C>,\n callback: C,\n onlyOne?: boolean,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): N[];\n\n /**\n * The function `getNodes` returns an array of nodes that match a given node property, using either\n * recursive or iterative traversal.\n * @param {ReturnType<C>} identifier - The `identifier` parameter is either a\n * `BTNKey` or a generic type `N`. It represents the property of the node that we are\n * searching for. It can be a specific key value or any other property of the node.\n * @param callback - The `callback` parameter is a function that takes a node as input and returns a\n * value. This value is compared with the `identifier` parameter to determine if the node should be\n * included in the result. The `callback` parameter has a default value of\n * `this.defaultOneParamCallback`, which\n * @param [onlyOne=false] - A boolean value indicating whether to stop searching after finding the\n * first node that matches the identifier. If set to true, the function will return an array with\n * only one element (or an empty array if no matching node is found). If set to false (default), the\n * function will continue searching for all\n * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which the\n * traversal of the binary tree will begin. It is optional and defaults to the root of the binary\n * tree.\n * @param iterationType - The `iterationType` parameter determines the type of iteration used to\n * traverse the binary tree. It can have two possible values:\n * @returns The function `getNodes` returns an array of nodes (`N[]`).\n */\n getNodes<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | null | undefined,\n callback: C = this.defaultOneParamCallback as C,\n onlyOne = false,\n beginRoot: N | null | undefined = this.root,\n iterationType = this.iterationType\n ): N[] {\n if (!beginRoot) return [];\n if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;\n const ans: N[] = [];\n\n if (iterationType === IterationType.RECURSIVE) {\n const _traverse = (cur: N) => {\n if (callback(cur) === identifier) {\n ans.push(cur);\n if (onlyOne) return;\n }\n if (!cur.left && !cur.right) return;\n cur.left && _traverse(cur.left);\n cur.right && _traverse(cur.right);\n };\n\n _traverse(beginRoot);\n } else {\n const queue = new Queue<N>([beginRoot]);\n while (queue.size > 0) {\n const cur = queue.shift();\n if (cur) {\n if (callback(cur) === identifier) {\n ans.push(cur);\n if (onlyOne) return ans;\n }\n cur.left && queue.push(cur.left);\n cur.right && queue.push(cur.right);\n }\n }\n }\n\n return ans;\n }\n\n has<C extends BTNCallback<N, BTNKey>>(\n identifier: BTNKey,\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): boolean;\n\n has<C extends BTNCallback<N, N>>(\n identifier: N | null | undefined,\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): boolean;\n\n has<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | null | undefined,\n callback: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): boolean;\n\n /**\n * The function checks if a binary tree has a node with a given property or key.\n * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of\n * the node that you want to find in the binary tree. It can be either a `BTNKey` or a\n * generic type `N`.\n * @param callback - The `callback` parameter is a function that is used to determine whether a node\n * matches the desired criteria. It takes a node as input and returns a boolean value indicating\n * whether the node matches the criteria or not. The default callback function\n * `this.defaultOneParamCallback` is used if no callback function is\n * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies\n * the node from which the search should begin. By default, it is set to `this.root`, which means the\n * search will start from the root node of the binary tree. However, you can provide a different node\n * as\n * @param iterationType - The `iterationType` parameter specifies the type of iteration to be\n * performed when searching for nodes in the binary tree. It can have one of the following values:\n * @returns a boolean value.\n */\n has<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | null | undefined,\n callback: C = this.defaultOneParamCallback as C,\n beginRoot = this.root,\n iterationType = this.iterationType\n ): boolean {\n if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;\n\n return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;\n }\n\n getNode<C extends BTNCallback<N, BTNKey>>(\n identifier: BTNKey,\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): N | null | undefined;\n\n getNode<C extends BTNCallback<N, N>>(\n identifier: N | null | undefined,\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): N | null | undefined;\n\n getNode<C extends BTNCallback<N>>(\n identifier: ReturnType<C>,\n callback: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): N | null | undefined;\n\n /**\n * The function `get` returns the first node in a binary tree that matches the given property or key.\n * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of\n * the node that you want to find in the binary tree. It can be either a `BTNKey` or `N`\n * type.\n * @param callback - The `callback` parameter is a function that is used to determine whether a node\n * matches the desired criteria. It takes a node as input and returns a boolean value indicating\n * whether the node matches the criteria or not. The default callback function\n * (`this.defaultOneParamCallback`) is used if no callback function is\n * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies\n * the root node from which the search should begin.\n * @param iterationType - The `iterationType` parameter specifies the type of iteration to be\n * performed when searching for a node in the binary tree. It can have one of the following values:\n * @returns either the found node (of type N) or null if no node is found.\n */\n getNode<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | null | undefined,\n callback: C = this.defaultOneParamCallback as C,\n beginRoot = this.root,\n iterationType = this.iterationType\n ): N | null | undefined {\n if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;\n\n return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;\n }\n\n get<C extends BTNCallback<N, BTNKey>>(\n identifier: BTNKey,\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): V | undefined;\n\n get<C extends BTNCallback<N, N>>(\n identifier: N | null | undefined,\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): V | undefined;\n\n get<C extends BTNCallback<N>>(\n identifier: ReturnType<C>,\n callback: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): V | undefined;\n\n /**\n * The function `get` returns the first node value in a binary tree that matches the given property or key.\n * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of\n * the node that you want to find in the binary tree. It can be either a `BTNKey` or `N`\n * type.\n * @param callback - The `callback` parameter is a function that is used to determine whether a node\n * matches the desired criteria. It takes a node as input and returns a boolean value indicating\n * whether the node matches the criteria or not. The default callback function\n * (`this.defaultOneParamCallback`) is used if no callback function is\n * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies\n * the root node from which the search should begin.\n * @param iterationType - The `iterationType` parameter specifies the type of iteration to be\n * performed when searching for a node in the binary tree. It can have one of the following values:\n * @returns either the found value (of type V) or undefined if no node value is found.\n */\n get<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | null | undefined,\n callback: C = this.defaultOneParamCallback as C,\n beginRoot = this.root,\n iterationType = this.iterationType\n ): V | undefined {\n if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;\n\n return this.getNode(identifier, callback, beginRoot, iterationType)?.value ?? undefined;\n }\n\n /**\n * The function `getPathToRoot` returns an array of nodes starting from a given node and traversing\n * up to the root node, with the option to reverse the order of the nodes.\n * @param {N} beginRoot - The `beginRoot` parameter represents the starting node from which you want\n * to find the path to the root node.\n * @param [isReverse=true] - The `isReverse` parameter is a boolean flag that determines whether the\n * resulting path should be reversed or not. If `isReverse` is set to `true`, the path will be\n * reversed before returning it. If `isReverse` is set to `false` or not provided, the path will\n * @returns The function `getPathToRoot` returns an array of type `N[]`.\n */\n getPathToRoot(beginRoot: N, isReverse = true): N[] {\n // TODO to support get path through passing key\n const result: N[] = [];\n while (beginRoot.parent) {\n // Array.push + Array.reverse is more efficient than Array.unshift\n // TODO may consider using Deque, so far this is not the performance bottleneck\n result.push(beginRoot);\n beginRoot = beginRoot.parent;\n }\n result.push(beginRoot);\n return isReverse ? result.reverse() : result;\n }\n\n /**\n * The function `getLeftMost` returns the leftmost node in a binary tree, either using recursive or\n * iterative traversal.\n * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point\n * for finding the leftmost node in a binary tree. It can be either a node object (`N`), a key value\n * of a node (`BTNKey`), or `null` if the tree is empty.\n * @param iterationType - The `iterationType` parameter is used to determine the type of iteration to\n * be performed when finding the leftmost node in a binary tree. It can have two possible values:\n * @returns The function `getLeftMost` returns the leftmost node (`N`) in a binary tree. If there is\n * no leftmost node, it returns `null`.\n */\n getLeftMost(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {\n if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);\n\n if (!beginRoot) return beginRoot;\n\n if (iterationType === IterationType.RECURSIVE) {\n const _traverse = (cur: N): N => {\n if (!cur.left) return cur;\n return _traverse(cur.left);\n };\n\n return _traverse(beginRoot);\n } else {\n // Indirect implementation of iteration using tail recursion optimization\n const _traverse = trampoline((cur: N) => {\n if (!cur.left) return cur;\n return _traverse.cont(cur.left);\n });\n\n return _traverse(beginRoot);\n }\n }\n\n /**\n * The function `getRightMost` returns the rightmost node in a binary tree, either recursively or\n * iteratively.\n * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which we want to\n * find the rightmost node. It is of type `N | null | undefined`, which means it can either be a node of type `N`\n * or `null`. If it is `null`, it means there is no starting node\n * @param iterationType - The `iterationType` parameter is used to determine the type of iteration to\n * be performed when finding the rightmost node in a binary tree. It can have two possible values:\n * @returns The function `getRightMost` returns the rightmost node (`N`) in a binary tree. If the\n * `beginRoot` parameter is `null`, it returns `null`.\n */\n getRightMost(beginRoot: N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {\n // TODO support get right most by passing key in\n if (!beginRoot) return beginRoot;\n\n if (iterationType === IterationType.RECURSIVE) {\n const _traverse = (cur: N): N => {\n if (!cur.right) return cur;\n return _traverse(cur.right);\n };\n\n return _traverse(beginRoot);\n } else {\n // Indirect implementation of iteration using tail recursion optimization\n const _traverse = trampoline((cur: N) => {\n if (!cur.right) return cur;\n return _traverse.cont(cur.right);\n });\n\n return _traverse(beginRoot);\n }\n }\n\n /**\n * The function `isSubtreeBST` checks if a given binary tree is a valid binary search tree.\n * @param {N} beginRoot - The `beginRoot` parameter is the root node of the binary tree that you want\n * to check if it is a binary search tree (BST) subtree.\n * @param iterationType - The `iterationType` parameter is an optional parameter that specifies the\n * type of iteration to use when checking if a subtree is a binary search tree (BST). It can have two\n * possible values:\n * @returns The function `isSubtreeBST` returns a boolean value.\n */\n isSubtreeBST(beginRoot: N | null | undefined, iterationType = this.iterationType): boolean {\n // TODO there is a bug\n if (!beginRoot) return true;\n\n if (iterationType === IterationType.RECURSIVE) {\n const dfs = (cur: N | null | undefined, min: BTNKey, max: BTNKey): boolean => {\n if (!cur) return true;\n if (cur.key <= min || cur.key >= max) return false;\n return dfs(cur.left, min, cur.key) && dfs(cur.right, cur.key, max);\n };\n\n return dfs(beginRoot, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);\n } else {\n const stack = [];\n let prev = Number.MIN_SAFE_INTEGER,\n curr: N | null | undefined = beginRoot;\n while (curr || stack.length > 0) {\n while (curr) {\n stack.push(curr);\n curr = curr.left;\n }\n curr = stack.pop()!;\n if (!curr || prev >= curr.key) return false;\n prev = curr.key;\n curr = curr.right;\n }\n return true;\n }\n }\n\n /**\n * The function checks if a binary tree is a binary search tree.\n * @param iterationType - The parameter \"iterationType\" is used to specify the type of iteration to\n * be used when checking if the binary tree is a binary search tree (BST). It is an optional\n * parameter with a default value of \"this.iterationType\". The value of \"this.iterationType\" is not\n * provided in\n * @returns a boolean value.\n */\n isBST(iterationType = this.iterationType): boolean {\n if (this.root === null) return true;\n return this.isSubtreeBST(this.root, iterationType);\n }\n\n subTreeTraverse<C extends BTNCallback<N>>(\n callback?: C,\n beginRoot?: BTNKey | N | null | undefined,\n iterationType?: IterationType,\n includeNull?: false\n ): ReturnType<C>[];\n\n subTreeTraverse<C extends BTNCallback<N>>(\n callback?: C,\n beginRoot?: BTNKey | N | null | undefined,\n iterationType?: IterationType,\n includeNull?: undefined\n ): ReturnType<C>[];\n\n subTreeTraverse<C extends BTNCallback<N | null | undefined>>(\n callback?: C,\n beginRoot?: BTNKey | N | null | undefined,\n iterationType?: IterationType,\n includeNull?: true\n ): ReturnType<C>[];\n\n /**\n * The function `subTreeTraverse` traverses a binary tree and applies a callback function to each\n * node, either recursively or iteratively.\n * @param callback - The `callback` parameter is a function that will be called on each node in the\n * subtree traversal. It takes a single argument, which is the current node being traversed, and\n * returns a value. The return values from each callback invocation will be collected and returned as\n * an array.\n * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point\n * for traversing the subtree. It can be either a node object, a key value of a node, or `null` to\n * start from the root of the tree.\n * @param iterationType - The `iterationType` parameter determines the type of traversal to be\n * performed on the binary tree. It can have two possible values:\n * @param includeNull - The choice to output null values during binary tree traversal should be provided.\n * @returns The function `subTreeTraverse` returns an array of `ReturnType<BTNCallback<N>>`.\n */\n subTreeTraverse<C extends BTNCallback<N | null | undefined>>(\n callback: C = this.defaultOneParamCallback as C,\n beginRoot: BTNKey | N | null | undefined = this.root,\n iterationType = this.iterationType,\n includeNull = false\n ): ReturnType<C>[] {\n if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);\n\n const ans: (ReturnType<BTNCallback<N>> | null | undefined)[] = [];\n if (!beginRoot) return ans;\n\n if (iterationType === IterationType.RECURSIVE) {\n const _traverse = (cur: N | null | undefined) => {\n if (cur !== undefined) {\n ans.push(callback(cur));\n if (includeNull) {\n cur && this.isNodeOrNull(cur.left) && _traverse(cur.left);\n cur && this.isNodeOrNull(cur.right) && _traverse(cur.right);\n } else {\n cur && cur.left && _traverse(cur.left);\n cur && cur.right && _traverse(cur.right);\n }\n }\n };\n\n _traverse(beginRoot);\n } else {\n const stack: (N | null | undefined)[] = [beginRoot];\n\n while (stack.length > 0) {\n const cur = stack.pop();\n if (cur !== undefined) {\n ans.push(callback(cur));\n if (includeNull) {\n cur && this.isNodeOrNull(cur.right) && stack.push(cur.right);\n cur && this.isNodeOrNull(cur.left) && stack.push(cur.left);\n } else {\n cur && cur.right && stack.push(cur.right);\n cur && cur.left && stack.push(cur.left);\n }\n }\n }\n }\n return ans;\n }\n \n isNode(node: any): node is N {\n return node instanceof BinaryTreeNode && node.key.toString() !== 'NaN';\n }\n\n isNIL(node: any) {\n return node instanceof BinaryTreeNode && node.key.toString() === 'NaN';\n }\n\n isNodeOrNull(node: any): node is (N | null){\n return this.isNode(node) || node === null;\n }\n\n dfs<C extends BTNCallback<N>>(\n callback?: C,\n pattern?: DFSOrderPattern,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: false\n ): ReturnType<C>[];\n\n dfs<C extends BTNCallback<N>>(\n callback?: C,\n pattern?: DFSOrderPattern,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: undefined\n ): ReturnType<C>[];\n\n dfs<C extends BTNCallback<N | null | undefined>>(\n callback?: C,\n pattern?: DFSOrderPattern,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: true\n ): ReturnType<C>[];\n\n /**\n * The `dfs` function performs a depth-first search traversal on a binary tree, executing a callback\n * function on each node according to a specified order pattern.\n * @param callback - The `callback` parameter is a function that will be called on each node during\n * the depth-first search traversal. It takes a node as input and returns a value. The default value\n * is `this.defaultOneParamCallback`, which is a callback function defined elsewhere in the code.\n * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter determines the order in which the\n * nodes are visited during the depth-first search. There are three possible values for `pattern`:\n * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the depth-first\n * search. It determines where the search will begin in the tree or graph structure. If `beginRoot`\n * is `null`, an empty array will be returned.\n * @param {IterationType} iterationType - The `iterationType` parameter determines the type of\n * iteration used in the depth-first search algorithm. It can have two possible values:\n * @param includeNull - The choice to output null values during binary tree traversal should be provided.\n * @returns The function `dfs` returns an array of `ReturnType<BTNCallback<N>>` values.\n */\n dfs<C extends BTNCallback<N | null | undefined>>(\n callback: C = this.defaultOneParamCallback as C,\n pattern: DFSOrderPattern = 'in',\n beginRoot: N | null | undefined = this.root,\n iterationType: IterationType = IterationType.ITERATIVE,\n includeNull = false\n ): ReturnType<C>[] {\n if (!beginRoot) return [];\n const ans: ReturnType<C>[] = [];\n if (iterationType === IterationType.RECURSIVE) {\n const _traverse = (node: N | null | undefined) => {\n switch (pattern) {\n case 'in':\n if (includeNull) {\n if (node && this.isNodeOrNull(node.left)) _traverse(node.left);\n this.isNodeOrNull(node) && ans.push(callback(node));\n if (node && this.isNodeOrNull(node.right)) _traverse(node.right);\n } else {\n if (node && node.left) _traverse(node.left);\n this.isNode(node) && ans.push(callback(node));\n if (node && node.right) _traverse(node.right);\n }\n break;\n case 'pre':\n if (includeNull) {\n this.isNodeOrNull(node) && ans.push(callback(node));\n if (node && this.isNodeOrNull(node.left)) _traverse(node.left);\n if (node && this.isNodeOrNull(node.right)) _traverse(node.right);\n } else {\n this.isNode(node) && ans.push(callback(node));\n if (node && node.left) _traverse(node.left);\n if (node && node.right) _traverse(node.right);\n }\n break;\n case 'post':\n if (includeNull) {\n if (node && this.isNodeOrNull(node.left)) _traverse(node.left);\n if (node && this.isNodeOrNull(node.right)) _traverse(node.right);\n this.isNodeOrNull(node) && ans.push(callback(node));\n } else {\n if (node && node.left) _traverse(node.left);\n if (node && node.right) _traverse(node.right);\n this.isNode(node) && ans.push(callback(node));\n }\n\n break;\n }\n };\n\n _traverse(beginRoot);\n } else {\n // 0: visit, 1: print\n const stack: {opt: 0 | 1; node: N | null | undefined}[] = [{opt: 0, node: beginRoot}];\n\n while (stack.length > 0) {\n const cur = stack.pop();\n if (cur === undefined || this.isNIL(cur.node)) continue;\n if (includeNull) {\n if (cur.node === undefined) continue;\n } else {\n if (cur.node === null || cur.node === undefined) continue;\n }\n if (cur.opt === 1) {\n ans.push(callback(cur.node));\n } else {\n switch (pattern) {\n case 'in':\n cur.node && stack.push({opt: 0, node: cur.node.right});\n stack.push({opt: 1, node: cur.node});\n cur.node && stack.push({opt: 0, node: cur.node.left});\n break;\n case 'pre':\n cur.node && stack.push({opt: 0, node: cur.node.right});\n cur.node && stack.push({opt: 0, node: cur.node.left});\n stack.push({opt: 1, node: cur.node});\n break;\n case 'post':\n stack.push({opt: 1, node: cur.node});\n cur.node && stack.push({opt: 0, node: cur.node.right});\n cur.node && stack.push({opt: 0, node: cur.node.left});\n break;\n default:\n cur.node && stack.push({opt: 0, node: cur.node.right});\n stack.push({opt: 1, node: cur.node});\n cur.node && stack.push({opt: 0, node: cur.node.left});\n break;\n }\n }\n }\n }\n\n return ans;\n }\n\n bfs<C extends BTNCallback<N>>(\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: false\n ): ReturnType<C>[];\n\n bfs<C extends BTNCallback<N>>(\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: undefined\n ): ReturnType<C>[];\n\n bfs<C extends BTNCallback<N | null | undefined>>(\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: true\n ): ReturnType<C>[];\n\n /**\n * The bfs function performs a breadth-first search traversal on a binary tree, executing a callback\n * function on each node.\n * @param callback - The `callback` parameter is a function that will be called for each node in the\n * breadth-first search. It takes a node of type `N` as its argument and returns a value of type\n * `ReturnType<BTNCallback<N>>`. The default value for this parameter is `this.defaultOneParamCallback\n * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the breadth-first\n * search. It determines from which node the search will begin. If `beginRoot` is `null`, the search\n * will not be performed and an empty array will be returned.\n * @param iterationType - The `iterationType` parameter determines the type of iteration to be used\n * in the breadth-first search (BFS) algorithm. It can have two possible values:\n * @param includeNull - The choice to output null values during binary tree traversal should be provided.\n * @returns The function `bfs` returns an array of `ReturnType<BTNCallback<N>>[]`.\n */\n bfs<C extends BTNCallback<N | null | undefined>>(\n callback: C = this.defaultOneParamCallback as C,\n beginRoot: N | null | undefined = this.root,\n iterationType = this.iterationType,\n includeNull = false\n ): ReturnType<C>[] {\n if (!beginRoot) return [];\n\n const ans: ReturnType<BTNCallback<N>>[] = [];\n\n if (iterationType === IterationType.RECURSIVE) {\n const queue: Queue<N | null | undefined> = new Queue<N | null | undefined>([beginRoot]);\n\n const traverse = (level: number) => {\n if (queue.size === 0) return;\n\n const current = queue.shift()!;\n ans.push(callback(current));\n\n if (includeNull) {\n if (current && this.isNodeOrNull(current.left)) queue.push(current.left);\n if (current && this.isNodeOrNull(current.right)) queue.push(current.right);\n } else {\n if (current.left) queue.push(current.left);\n if (current.right) queue.push(current.right);\n }\n\n traverse(level + 1);\n };\n\n traverse(0);\n } else {\n const queue = new Queue<N | null | undefined>([beginRoot]);\n while (queue.size > 0) {\n const levelSize = queue.size;\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.isNodeOrNull(current.left)) queue.push(current.left);\n if (current && this.isNodeOrNull(current.right)) queue.push(current.right);\n } else {\n if (current.left) queue.push(current.left);\n if (current.right) queue.push(current.right);\n }\n }\n }\n }\n return ans;\n }\n\n listLevels<C extends BTNCallback<N>>(\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: false\n ): ReturnType<C>[][];\n\n listLevels<C extends BTNCallback<N>>(\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: undefined\n ): ReturnType<C>[][];\n\n listLevels<C extends BTNCallback<N | null | undefined>>(\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: true\n ): ReturnType<C>[][];\n\n /**\n * The `listLevels` function takes a binary tree node and a callback function, and returns an array\n * of arrays representing the levels of the tree.\n * @param {C} callback - The `callback` parameter is a function that will be called on each node in\n * the tree. It takes a node as input and returns a value. The return type of the callback function\n * is determined by the generic type `C`.\n * @param {N | null | undefined} beginRoot - The `beginRoot` parameter represents the starting node of the binary tree\n * traversal. It can be any node in the binary tree. If no node is provided, the traversal will start\n * from the root node of the binary tree.\n * @param iterationType - The `iterationType` parameter determines whether the tree traversal is done\n * recursively or iteratively. It can have two possible values:\n * @param includeNull - The choice to output null values during binary tree traversal should be provided.\n * @returns The function `listLevels` returns an array of arrays, where each inner array represents a\n * level in a binary tree. Each inner array contains the return type of the provided callback\n * function `C` applied to the nodes at that level.\n */\n listLevels<C extends BTNCallback<N | null | undefined>>(\n callback: C = this.defaultOneParamCallback as C,\n beginRoot: N | null | undefined = this.root,\n iterationType = this.iterationType,\n includeNull = false\n ): ReturnType<C>[][] {\n if (!beginRoot) return [];\n const levelsNodes: ReturnType<C>[][] = [];\n\n if (iterationType === IterationType.RECURSIVE) {\n const _recursive = (node: N | null | undefined, level: number) => {\n if (!levelsNodes[level]) levelsNodes[level] = [];\n levelsNodes[level].push(callback(node));\n if (includeNull) {\n if (node && this.isNodeOrNull(node.left)) _recursive(node.left, level + 1);\n if (node && this.isNodeOrNull(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(beginRoot, 0);\n } else {\n const stack: [N | null | undefined, number][] = [[beginRoot, 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.isNodeOrNull(node.right)) stack.push([node.right, level + 1]);\n if (node && this.isNodeOrNull(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 /**\n * The function returns the predecessor node of a given node in a binary tree.\n * @param {N} node - The parameter \"node\" represents a node in a binary tree.\n * @returns The function `getPredecessor` returns the predecessor node of the given node `node`.\n */\n getPredecessor(node: N): N {\n if (node.left) {\n let predecessor: N | null | undefined = node.left;\n while (!predecessor || (predecessor.right && predecessor.right !== node)) {\n if (predecessor) {\n predecessor = predecessor.right;\n }\n }\n return predecessor;\n } else {\n return node;\n }\n }\n\n /**\n * The function `getSuccessor` returns the next node in a binary tree given a node `x`, or `null` if\n * `x` is the last node.\n * @param {N} x - N - a node in a binary tree\n * @returns The function `getSuccessor` returns a value of type `N` (the successor node), or `null`\n * if there is no successor, or `undefined` if the input `x` is `undefined`.\n */\n getSuccessor(x: N): N | null | undefined {\n if (x.right) {\n return this.getLeftMost(x.right);\n }\n\n let y: N | null | undefined = x.parent;\n while (y && y && x === y.right) {\n x = y;\n y = y.parent;\n }\n return y;\n }\n\n /**\n * The `morris` function performs a depth-first traversal of a binary tree using the Morris traversal\n * algorithm and returns an array of values obtained by applying a callback function to each node.\n * @param callback - The `callback` parameter is a function that will be called on each node in the\n * tree. It takes a node of type `N` as input and returns a value of type `ReturnType<BTNCallback<N>>`. The\n * default value for this parameter is `this.defaultOneParamCallback`.\n * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter in the `morris` function\n * determines the order in which the nodes of a binary tree are traversed. It can have one of the\n * following values:\n * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the Morris\n * traversal. It specifies the root node of the tree from which the traversal should begin. If\n * `beginRoot` is `null`, an empty array will be returned.\n * @returns The `morris` function returns an array of `ReturnType<BTNCallback<N>>` values.\n */\n morris<C extends BTNCallback<N>>(\n callback: C = this.defaultOneParamCallback as C,\n pattern: DFSOrderPattern = 'in',\n beginRoot: N | null | undefined = this.root\n ): ReturnType<C>[] {\n if (beginRoot === null) return [];\n const ans: ReturnType<BTNCallback<N>>[] = [];\n\n let cur: N | null | undefined = beginRoot;\n const _reverseEdge = (node: N | null | undefined) => {\n let pre: N | null | undefined = null;\n let next: N | 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: N | null | undefined) => {\n const tail: N | null | undefined = _reverseEdge(node);\n let cur: N | 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(beginRoot);\n break;\n }\n return ans;\n }\n\n // --- start additional methods ---\n\n /**\n * The above function is an iterator for a binary tree that can be used to traverse the tree in\n * either an iterative or recursive manner.\n * @param node - The `node` parameter represents the current node in the binary tree from which the\n * iteration starts. It is an optional parameter with a default value of `this.root`, which means\n * that if no node is provided, the iteration will start from the root of the binary tree.\n * @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the\n * binary tree nodes in a specific order.\n */\n *[Symbol.iterator](node = this.root): Generator<BTNKey, void, undefined> {\n if (!node) {\n return;\n }\n\n if (this.iterationType === IterationType.ITERATIVE) {\n const stack: (N | null | undefined)[] = [];\n let current: N | null | undefined = node;\n\n while (current || stack.length > 0) {\n while (current) {\n stack.push(current);\n current = current.left;\n }\n\n current = stack.pop();\n\n if (current) yield current.key;\n if (current) current = current.right;\n }\n } else {\n if (node.left) {\n // @ts-ignore\n yield* this[Symbol.iterator](node.left);\n }\n yield node.key;\n if (node.right) {\n // @ts-ignore\n yield* this[Symbol.iterator](node.right);\n }\n }\n }\n\n protected defaultOneParamCallback = (node: N) => node.key;\n\n /**\n * Swap the data of two nodes in the binary tree.\n * @param {N} srcNode - The source node to swap.\n * @param {N} destNode - The destination node to swap.\n * @returns {N} - The destination node after the swap.\n */\n protected _swap(srcNode: N, destNode: N): N {\n const {key, value} = destNode;\n const tempNode = this.createNode(key, value);\n\n if (tempNode) {\n destNode.key = srcNode.key;\n destNode.value = srcNode.value;\n\n srcNode.key = tempNode.key;\n srcNode.value = tempNode.value;\n }\n\n return destNode;\n }\n\n /**\n * The function `_addTo` adds a new node to a binary tree if there is an available position.\n * @param {N | null | undefined} newNode - The `newNode` parameter represents the node that you want to add to\n * the binary tree. It can be either a node object or `null`.\n * @param {N} parent - The `parent` parameter represents the parent node to which the new node will\n * be added as a child.\n * @returns either the left or right child node of the parent node, depending on which child is\n * available for adding the new node. If a new node is added, the function also updates the size of\n * the binary tree. If neither the left nor right child is available, the function returns undefined.\n * If the parent node is null, the function also returns undefined.\n */\n protected _addTo(newNode: N | null | undefined, parent: N): N | null | undefined {\n if (parent) {\n // When all leaf nodes are null, it will no longer be possible to add new entity nodes to this binary tree.\n // In this scenario, null nodes serve as \"sentinel nodes,\" \"virtual nodes,\" or \"placeholder nodes.\"\n if (parent.left === undefined) {\n parent.left = newNode;\n if (newNode) {\n this._size = this.size + 1;\n }\n return parent.left;\n } else if (parent.right === undefined) {\n parent.right = newNode;\n if (newNode) {\n this._size = this.size + 1;\n }\n return parent.right;\n } else {\n return;\n }\n } else {\n return;\n }\n }\n\n /**\n * The function sets the root property of an object to a given value, and if the value is not null,\n * it also sets the parent property of the value to undefined.\n * @param {N | null | undefined} v - The parameter `v` is of type `N | null | undefined`, which means it can either be of\n * type `N` or `null`.\n */\n protected _setRoot(v: N | null | undefined) {\n if (v) {\n v.parent = undefined;\n }\n this._root = v;\n }\n\n print(beginRoot: N | null | undefined = this.root) {\n const display = (root: N | null | undefined): void => {\n const [lines, , ,] = _displayAux(root);\n for (const line of lines) {\n console.log(line);\n }\n };\n\n const _displayAux = (node: N | null | undefined): [string[], number, number, number] => {\n if (node === undefined || node === null) {\n return [[], 0, 0, 0];\n }\n\n if (node && node.right === undefined && node.left === undefined) {\n const line = `${node.key}`;\n const width = line.length;\n const height = 1;\n const middle = Math.floor(width / 2);\n return [[line], width, height, middle];\n }\n\n if (node && node.right === undefined) {\n const [lines, n, p, x] = _displayAux(node.left);\n const s = `${node.key}`;\n const u = s.length;\n const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s;\n const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u);\n const shifted_lines = lines.map(line => line + ' '.repeat(u));\n return [[first_line, second_line, ...shifted_lines], n + u, p + 2, n + Math.floor(u / 2)];\n }\n\n if (node && node.left === undefined) {\n const [lines, n, p, u] = _displayAux(node.right);\n const s = `${node.key}`;\n const x = s.length;\n const first_line = s + '_'.repeat(x) + ' '.repeat(n - x);\n const second_line = ' '.repeat(u + x) + '\\\\' + ' '.repeat(n - x - 1);\n const shifted_lines = lines.map(line => ' '.repeat(u) + line);\n return [[first_line, second_line, ...shifted_lines], n + x, p + 2, Math.floor(u / 2)];\n }\n\n const [left, n, p, x] = _displayAux(node.left);\n const [right, m, q, y] = _displayAux(node.right);\n const s = `${node.key}`;\n const u = s.length;\n const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s + '_'.repeat(y) + ' '.repeat(m - y);\n const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u + y) + '\\\\' + ' '.repeat(m - y - 1);\n if (p < q) {\n left.push(...new Array(q - p).fill(' '.repeat(n)));\n } else if (q < p) {\n right.push(...new Array(p - q).fill(' '.repeat(m)));\n }\n const zipped_lines = left.map((a, i) => a + ' '.repeat(u) + right[i]);\n return [[first_line, second_line, ...zipped_lines], n + m + u, Math.max(p, q) + 2, n + Math.floor(u / 2)];\n };\n\n display(beginRoot);\n }\n // --- end additional methods ---\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type {BSTComparator, BSTNodeNested, BSTOptions, BTNCallback, BTNKey} from '../../types';\nimport {CP, IterationType} from '../../types';\nimport {BinaryTree, BinaryTreeNode} from './binary-tree';\nimport {IBinaryTree} from '../../interfaces';\nimport {Queue} from '../queue';\n\nexport class BSTNode<V = any, N extends BSTNode<V, N> = BSTNodeNested<V>> extends BinaryTreeNode<V, N> {\n override parent: N | undefined;\n constructor(key: BTNKey, value?: V) {\n super(key, value);\n this.parent = undefined;\n this._left = undefined;\n this._right = undefined;\n }\n\n protected override _left: N | undefined;\n\n /**\n * Get the left child node.\n */\n override get left(): N | undefined {\n return this._left;\n }\n\n /**\n * Set the left child node.\n * @param {N | undefined} v - The left child node.\n */\n override set left(v: N | undefined) {\n if (v) {\n v.parent = this as unknown as N;\n }\n this._left = v;\n }\n\n\n protected override _right: N | undefined;\n\n /**\n * Get the right child node.\n */\n override get right(): N | undefined {\n return this._right;\n }\n\n /**\n * Set the right child node.\n * @param {N | undefined} v - The right child node.\n */\n override set right(v: N | undefined) {\n if (v) {\n v.parent = this as unknown as N;\n }\n this._right = v;\n }\n}\n\nexport class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>>\n extends BinaryTree<V, N>\n implements IBinaryTree<V, N>\n{\n /**\n * The constructor function initializes a binary search tree object with an optional comparator\n * function.\n * @param {BSTOptions} [options] - An optional object that contains configuration options for the\n * binary search tree.\n */\n constructor(options?: BSTOptions) {\n super(options);\n this._root = undefined;\n if (options !== undefined) {\n const {comparator} = options;\n if (comparator !== undefined) {\n this._comparator = comparator;\n }\n }\n }\n protected override _root: N | undefined = undefined;\n\n /**\n * Get the root node of the binary tree.\n */\n override get root(): N | undefined {\n return this._root;\n }\n\n /**\n * The function creates a new binary search tree node with the given key and value.\n * @param {BTNKey} key - The key parameter is the key value that will be associated with\n * the new node. It is used to determine the position of the node in the binary search tree.\n * @param [value] - The parameter `value` is an optional value that can be assigned to the node. It\n * represents the value associated with the node in a binary search tree.\n * @returns a new instance of the BSTNode class with the specified key and value.\n */\n override createNode(key: BTNKey, value?: V): N {\n return new BSTNode<V, N>(key, value) as N;\n }\n\n /**\n * The `add` function in a binary search tree class inserts a new node with a given key and value\n * into the tree.\n * @param {BTNKey | N | undefined} keyOrNode - The `keyOrNode` parameter can be either a\n * `BTNKey` (which can be a number or a string), a `BSTNode` object, or `undefined`.\n * @param [value] - The `value` parameter is the value to be assigned to the new node being added to the\n * binary search tree.\n * @returns the inserted node (N) if it was successfully added to the binary search tree. If the node\n * was not added or if the parameters were invalid, it returns undefined or undefined.\n */\n override add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | undefined {\n if (keyOrNode === 8) {\n debugger\n }\n if (keyOrNode === null) return undefined;\n // TODO support node as a parameter\n let inserted:N | undefined;\n let newNode:N | undefined;\n if (keyOrNode instanceof BSTNode) {\n newNode = keyOrNode;\n } else if (typeof keyOrNode === 'number') {\n newNode = this.createNode(keyOrNode, value);\n } else {\n newNode = undefined;\n }\n if (this.root === undefined) {\n this._setRoot(newNode);\n this._size = this.size + 1;\n inserted = this.root;\n } else {\n let cur = this.root;\n let traversing = true;\n while (traversing) {\n if (cur !== undefined && newNode !== undefined) {\n if (this._compare(cur.key, newNode.key) === CP.eq) {\n if (newNode) {\n cur.value = newNode.value;\n }\n //Duplicates are not accepted.\n traversing = false;\n inserted = cur;\n } else if (this._compare(cur.key, newNode.key) === CP.gt) {\n // Traverse left of the node\n if (cur.left === undefined) {\n if (newNode) {\n newNode.parent = cur;\n }\n //Add to the left of the current node\n cur.left = newNode;\n this._size = this.size + 1;\n traversing = false;\n inserted = cur.left;\n } else {\n //Traverse the left of the current node\n if (cur.left) cur = cur.left;\n }\n } else if (this._compare(cur.key, newNode.key) === CP.lt) {\n // Traverse right of the node\n if (cur.right === undefined) {\n if (newNode) {\n newNode.parent = cur;\n }\n //Add to the right of the current node\n cur.right = newNode;\n this._size = this.size + 1;\n traversing = false;\n inserted = cur.right;\n } else {\n //Traverse the left of the current node\n if (cur.right) cur = cur.right;\n }\n }\n } else {\n traversing = false;\n }\n }\n }\n return inserted;\n }\n\n /**\n * The `addMany` function is used to efficiently add multiple nodes to a binary search tree while\n * maintaining balance.\n * @param {[BTNKey | N, V][]} keysOrNodes - The `arr` parameter in the `addMany` function\n * represents an array of keys or nodes that need to be added to the binary search tree. It can be an\n * array of `BTNKey` or `N` (which represents the node type in the binary search tree) or\n * `undefined\n * @param {V[]} data - The values of tree nodes\n * @param {boolean} isBalanceAdd - If true the nodes will be balance inserted in binary search method.\n * @param iterationType - The `iterationType` parameter determines the type of iteration to be used.\n * It can have two possible values:\n * @returns The `addMany` function returns an array of `N`, `undefined`, or `undefined` values.\n */\n\n override addMany(\n keysOrNodes: (BTNKey | undefined)[] | (N | undefined)[],\n data?: V[],\n isBalanceAdd = true,\n iterationType = this.iterationType\n ): (N | undefined)[] {\n // TODO this addMany function is inefficient, it should be optimized\n function hasNoNull(arr: (BTNKey | undefined)[] | (N | undefined)[]): arr is BTNKey[] | N[] {\n return arr.indexOf(undefined) === -1;\n }\n\n if (!isBalanceAdd || !hasNoNull(keysOrNodes)) {\n return super.addMany(keysOrNodes, data).map(n => n ?? undefined);\n }\n const inserted: (N | undefined)[] = [];\n const combinedArr: [BTNKey | N, V][] = keysOrNodes.map(\n (value: BTNKey | N, index) => [value, data?.[index]] as [BTNKey | N, V]\n );\n let sorted = [];\n\n function isNodeOrNullTuple(arr: [BTNKey | N, V][]): arr is [N, V][] {\n for (const [keyOrNode] of arr) if (keyOrNode instanceof BSTNode) return true;\n return false;\n }\n\n function isBinaryTreeKeyOrNullTuple(arr: [BTNKey | N, V][]): arr is [BTNKey, V][] {\n for (const [keyOrNode] of arr) if (typeof keyOrNode === 'number') return true;\n return false;\n }\n\n let sortedKeysOrNodes: (number | N | undefined)[] = [],\n sortedData: (V | undefined)[] | undefined = [];\n\n if (isNodeOrNullTuple(combinedArr)) {\n sorted = combinedArr.sort((a, b) => a[0].key - b[0].key);\n } else if (isBinaryTreeKeyOrNullTuple(combinedArr)) {\n sorted = combinedArr.sort((a, b) => a[0] - b[0]);\n } else {\n throw new Error('Invalid input keysOrNodes');\n }\n sortedKeysOrNodes = sorted.map(([keyOrNode]) => keyOrNode);\n sortedData = sorted.map(([, value]) => value);\n const recursive = (arr: (BTNKey | undefined | N)[], data?: (V | undefined)[]) => {\n if (arr.length === 0) return;\n\n const mid = Math.floor((arr.length - 1) / 2);\n const newNode = this.add(arr[mid], data?.[mid]);\n inserted.push(newNode);\n recursive(arr.slice(0, mid), data?.slice(0, mid));\n recursive(arr.slice(mid + 1), data?.slice(mid + 1));\n };\n const iterative = () => {\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 newNode = this.add(sortedKeysOrNodes[m], sortedData?.[m]);\n inserted.push(newNode);\n stack.push([m + 1, r]);\n stack.push([l, m - 1]);\n }\n }\n }\n };\n if (iterationType === IterationType.RECURSIVE) {\n recursive(sortedKeysOrNodes, sortedData);\n } else {\n iterative();\n }\n\n return inserted;\n }\n\n /**\n * The function `lastKey` returns the key of the rightmost node if the comparison result is less\n * than, the key of the leftmost node if the comparison result is greater than, and the key of the\n * rightmost node otherwise.\n * @param {N | undefined} beginRoot - The `beginRoot` parameter is the starting point for finding the last\n * key in a binary tree. It represents the root node of the subtree from which the search for the\n * last key should begin. If no specific `beginRoot` is provided, the search will start from the root\n * of the entire binary\n * @param iterationType - The `iterationType` parameter is used to specify the type of iteration to\n * be performed when finding the last key. It determines whether the iteration should be performed in\n * pre-order, in-order, or post-order.\n * @returns the key of the rightmost node in the binary tree if the comparison result is less than,\n * the key of the leftmost node if the comparison result is greater than, and the key of the\n * rightmost node otherwise. If no node is found, it returns 0.\n */\n lastKey(beginRoot: N | undefined = this.root, iterationType = this.iterationType): BTNKey {\n if (this._compare(0, 1) === CP.lt) return this.getRightMost(beginRoot, iterationType)?.key ?? 0;\n else if (this._compare(0, 1) === CP.gt) return this.getLeftMost(beginRoot, iterationType)?.key ?? 0;\n else return this.getRightMost(beginRoot, iterationType)?.key ?? 0;\n }\n\n /**\n * The function `getNodes` retrieves nodes from a binary tree based on a given node property or key,\n * using either recursive or iterative traversal.\n * @param {ReturnType<C> | N} identifier - The `nodeProperty` parameter represents the property\n * of the binary tree node that you want to search for. It can be either a `BTNKey` or a\n * generic type `N`.\n * @param callback - The `callback` parameter is a function that takes a node as input and returns a\n * value. This value is compared with the `nodeProperty` parameter to determine if the node should be\n * included in the result. The default value for `callback` is `this.defaultOneParamCallback`, which is\n * a\n * @param [onlyOne=false] - A boolean value indicating whether to stop the traversal after finding\n * the first node that matches the nodeProperty. If set to true, the function will return an array\n * containing only that node. If set to false (default), the function will continue the traversal and\n * return an array containing all nodes that match the node\n * @param {N | undefined} beginRoot - The `beginRoot` parameter is the starting node for the traversal. It\n * specifies the root node of the binary tree from which the traversal should begin. If `beginRoot`\n * is `undefined`, an empty array will be returned.\n * @param iterationType - The `iterationType` parameter determines the type of iteration used to\n * traverse the binary tree. It can have one of the following values:\n * @returns an array of nodes (N[]).\n */\n override getNodes<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | undefined,\n callback: C = this.defaultOneParamCallback as C,\n onlyOne = false,\n beginRoot: N | undefined = this.root,\n iterationType = this.iterationType\n ): N[] {\n if (!beginRoot) return [];\n const ans: N[] = [];\n\n if (iterationType === IterationType.RECURSIVE) {\n const _traverse = (cur: N) => {\n const callbackResult = callback(cur);\n if (callbackResult === identifier) {\n ans.push(cur);\n if (onlyOne) return;\n }\n\n if (!cur.left && !cur.right) return;\n // TODO potential bug\n if (callback === this.defaultOneParamCallback) {\n if (this._compare(cur.key, identifier as number) === CP.gt) cur.left && _traverse(cur.left);\n if (this._compare(cur.key, identifier as number) === CP.lt) cur.right && _traverse(cur.right);\n } else {\n cur.left && _traverse(cur.left);\n cur.right && _traverse(cur.right);\n }\n };\n\n _traverse(beginRoot);\n } else {\n const queue = new Queue<N>([beginRoot]);\n while (queue.size > 0) {\n const cur = queue.shift();\n if (cur) {\n const callbackResult = callback(cur);\n if (callbackResult === identifier) {\n ans.push(cur);\n if (onlyOne) return ans;\n }\n // TODO potential bug\n if (callback === this.defaultOneParamCallback) {\n if (this._compare(cur.key, identifier as number) === CP.gt) cur.left && queue.push(cur.left);\n if (this._compare(cur.key, identifier as number) === CP.lt) cur.right && queue.push(cur.right);\n } else {\n cur.left && queue.push(cur.left);\n cur.right && queue.push(cur.right);\n }\n }\n }\n }\n\n return ans;\n }\n\n // --- start additional functions\n\n /**\n * The `lesserOrGreaterTraverse` function traverses a binary tree and applies a callback function to\n * nodes that have a key value lesser or greater than a target key value.\n * @param callback - The `callback` parameter is a function that will be called for each node that\n * meets the condition specified by the `lesserOrGreater` parameter. It takes a node as an argument\n * and returns a value.\n * @param {CP} lesserOrGreater - The `lesserOrGreater` parameter is used to determine whether to\n * traverse nodes that are lesser than, greater than, or equal to the `targetNode`. It can take one\n * of the following values:\n * @param {BTNKey | N | undefined} targetNode - The `targetNode` parameter in the\n * `lesserOrGreaterTraverse` function is used to specify the node from which the traversal should\n * start. It can be either a reference to a specific node (`N`), the key of a node\n * (`BTNKey`), or `undefined` to\n * @param iterationType - The `iterationType` parameter determines whether the traversal should be\n * done recursively or iteratively. It can have two possible values:\n * @returns The function `lesserOrGreaterTraverse` returns an array of `ReturnType<BTNCallback<N>>`.\n */\n lesserOrGreaterTraverse<C extends BTNCallback<N>>(\n callback: C = this.defaultOneParamCallback as C,\n lesserOrGreater: CP = CP.lt,\n targetNode: BTNKey | N | undefined = this.root,\n iterationType = this.iterationType\n ): ReturnType<C>[] {\n if (typeof targetNode === 'number') targetNode = this.getNode(targetNode) ?? undefined;\n const ans: ReturnType<BTNCallback<N>>[] = [];\n if (!targetNode) return ans;\n const targetKey = targetNode.key;\n if (!this.root) return ans;\n\n if (iterationType === IterationType.RECURSIVE) {\n const _traverse = (cur: N) => {\n const compared = this._compare(cur.key, targetKey);\n if (compared === lesserOrGreater) ans.push(callback(cur));\n\n if (!cur.left && !cur.right) return;\n if (cur.left && this._compare(cur.left.key, targetKey) === lesserOrGreater) _traverse(cur.left);\n if (cur.right && this._compare(cur.right.key, targetKey) === lesserOrGreater) _traverse(cur.right);\n };\n\n _traverse(this.root);\n return ans;\n } else {\n const queue = new Queue<N>([this.root]);\n while (queue.size > 0) {\n const cur = queue.shift();\n if (cur) {\n const compared = this._compare(cur.key, targetKey);\n if (compared === lesserOrGreater) ans.push(callback(cur));\n\n if (cur.left && this._compare(cur.left.key, targetKey) === lesserOrGreater) queue.push(cur.left);\n if (cur.right && this._compare(cur.right.key, targetKey) === lesserOrGreater) queue.push(cur.right);\n }\n }\n return ans;\n }\n }\n\n /**\n * Balancing Adjustment:\n * Perfectly Balanced Binary Tree: Since the balance of a perfectly balanced binary tree is already fixed, no additional balancing adjustment is needed. Any insertion or deletion operation will disrupt the perfect balance, often requiring a complete reconstruction of the tree.\n * AVL Tree: After insertion or deletion operations, an AVL tree performs rotation adjustments based on the balance factor of nodes to restore the tree's balance. These rotations can be left rotations, right rotations, left-right rotations, or right-left rotations, performed as needed.\n *\n * Use Cases and Efficiency:\n * Perfectly Balanced Binary Tree: Perfectly balanced binary trees are typically used in specific scenarios such as complete binary heaps in heap sort or certain types of Huffman trees. However, they are not suitable for dynamic operations requiring frequent insertions and deletions, as these operations often necessitate full tree reconstruction.\n * AVL Tree: AVL trees are well-suited for scenarios involving frequent searching, insertion, and deletion operations. Through rotation adjustments, AVL trees maintain their balance, ensuring average and worst-case time complexity of O(log n).\n */\n\n /**\n * The `perfectlyBalance` function balances a binary search tree by adding nodes in a way that\n * ensures the tree is perfectly balanced.\n * @param iterationType - The `iterationType` parameter is an optional parameter that specifies the\n * type of iteration to use when building a balanced binary search tree. It can have two possible\n * values:\n * @returns The function `perfectlyBalance` returns a boolean value.\n */\n perfectlyBalance(iterationType = this.iterationType): boolean {\n const sorted = this.dfs(node => node, 'in'),\n n = sorted.length;\n this.clear();\n\n if (sorted.length < 1) return false;\n if (iterationType === 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 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 debugger\n 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 * The function checks if a binary tree is AVL balanced using either recursive or iterative approach.\n * @param iterationType - The `iterationType` parameter is used to determine the method of iteration\n * to check if the AVL tree is balanced. It can have two possible values:\n * @returns a boolean value.\n */\n isAVLBalanced(iterationType = this.iterationType): boolean {\n if (!this.root) return true;\n\n let balanced = true;\n\n if (iterationType === IterationType.RECURSIVE) {\n const _height = (cur: N | 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: N[] = [];\n let node: N | undefined = this.root,\n last:N | undefined = undefined;\n const depths: Map<N, number> = new Map();\n\n while (stack.length > 0 || node) {\n if (node) {\n stack.push(node);\n 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 : -1;\n const right = node.right ? depths.get(node.right) ?? -1 : -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 protected _comparator: BSTComparator = (a, b) => a - b;\n\n protected _setRoot(v: N | undefined) {\n if (v) {\n v.parent = undefined;\n }\n this._root = v;\n }\n\n /**\n * The function compares two values using a comparator function and returns whether the first value\n * is greater than, less than, or equal to the second value.\n * @param {BTNKey} a - The parameter \"a\" is of type BTNKey.\n * @param {BTNKey} b - The parameter \"b\" in the above code represents a BTNKey.\n * @returns a value of type CP (ComparisonResult). The possible return values are CP.gt (greater\n * than), CP.lt (less than), or CP.eq (equal).\n */\n protected _compare(a: BTNKey, b: BTNKey): CP {\n const compared = this._comparator(a, b);\n if (compared > 0) return CP.gt;\n else if (compared < 0) return CP.lt;\n else return CP.eq;\n }\n\n // --- end additional functions\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport {getMSB} from '../../utils';\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 get freqMap(): Record<number, number> {\n return this._freqMap;\n }\n\n protected _msb: number;\n\n get msb(): number {\n return this._msb;\n }\n\n protected _negativeCount: number;\n\n get negativeCount(): number {\n return this._negativeCount;\n }\n\n get freq(): number {\n return this._freq;\n }\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 Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n\nimport type {SegmentTreeNodeVal} from '../../types';\n\nexport class SegmentTreeNode {\n start = 0;\n end = 0;\n value: SegmentTreeNodeVal | null = null;\n sum = 0;\n left: SegmentTreeNode | null = null;\n right: SegmentTreeNode | null = null;\n\n constructor(start: number, end: number, sum: number, value?: SegmentTreeNodeVal | null) {\n this.start = start;\n this.end = end;\n this.sum = sum;\n this.value = value || null;\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 = null;\n this._values = [];\n }\n }\n\n protected _values: number[] = [];\n\n get values(): number[] {\n return this._values;\n }\n\n protected _start = 0;\n\n get start(): number {\n return this._start;\n }\n\n protected _end: number;\n\n get end(): number {\n return this._end;\n }\n\n protected _root: SegmentTreeNode | null;\n\n get root(): SegmentTreeNode | null {\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 || null;\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 || null;\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 Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport {BST, BSTNode} from './bst';\nimport type {AVLTreeNodeNested, AVLTreeOptions, BinaryTreeDeletedResult, BTNKey} from '../../types';\nimport {BTNCallback} from '../../types';\nimport {IBinaryTree} from '../../interfaces';\n\nexport class AVLTreeNode<V = any, N extends AVLTreeNode<V, N> = AVLTreeNodeNested<V>> extends BSTNode<V, N> {\n height: number;\n\n constructor(key: BTNKey, value?: V) {\n super(key, value);\n this.height = 0;\n }\n}\n\nexport class AVLTree<V = any, N extends AVLTreeNode<V, N> = AVLTreeNode<V, AVLTreeNodeNested<V>>>\n extends BST<V, N>\n implements IBinaryTree<V, N>\n{\n /**\n * This is a constructor function for an AVL tree data structure in TypeScript.\n * @param {AVLTreeOptions} [options] - The `options` parameter is an optional object that can be passed to the\n * constructor of the AVLTree class. It allows you to customize the behavior of the AVL tree by providing different\n * options.\n */\n constructor(options?: AVLTreeOptions) {\n super(options);\n }\n\n /**\n * The function creates a new AVL tree node with the specified key and value.\n * @param {BTNKey} key - The key parameter is the key value that will be associated with\n * the new node. It is used to determine the position of the node in the binary search tree.\n * @param [value] - The parameter `value` is an optional value that can be assigned to the node. It is of\n * type `V`, which means it can be any value that is assignable to the `value` property of the\n * node type `N`.\n * @returns a new AVLTreeNode object with the specified key and value.\n */\n override createNode(key: BTNKey, value?: V): N {\n return new AVLTreeNode<V, N>(key, value) as N;\n }\n\n /**\n * The function overrides the add method of a binary tree node and balances the tree after inserting\n * a new node.\n * @param {BTNKey | N | undefined} keyOrNode - The `keyOrNode` parameter can accept either a\n * `BTNKey` or a `N` (which represents a node in the binary tree) or `null`.\n * @param [value] - The `value` parameter is the value that you want to assign to the new node that you\n * are adding to the binary search tree.\n * @returns The method is returning the inserted node (`N`), `null`, or `undefined`.\n */\n override add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | undefined {\n if (keyOrNode === null) return undefined;\n const inserted = super.add(keyOrNode, value);\n if (inserted) this._balancePath(inserted);\n return inserted;\n }\n\n /**\n * The function overrides the delete method of a binary tree and balances the tree after deleting a\n * node if necessary.\n * @param {ReturnType<C>} identifier - The `identifier` parameter is either a\n * `BTNKey` or a generic type `N`. It represents the property of the node that we are\n * searching for. It can be a specific key value or any other property of the node.\n * @param callback - The `callback` parameter is a function that takes a node as input and returns a\n * value. This value is compared with the `identifier` parameter to determine if the node should be\n * included in the result. The `callback` parameter has a default value of\n * `this.defaultOneParamCallback`\n * @returns The method is returning an array of `BinaryTreeDeletedResult<N>` objects.\n */\n override delete<C extends BTNCallback<N>>(\n identifier: ReturnType<C>,\n callback: C = this.defaultOneParamCallback as C\n ): BinaryTreeDeletedResult<N>[] {\n if ((identifier as any) instanceof AVLTreeNode) callback = (node => node) as C;\n const deletedResults = super.delete(identifier, callback);\n for (const {needBalanced} of deletedResults) {\n if (needBalanced) {\n this._balancePath(needBalanced);\n }\n }\n return deletedResults;\n }\n\n /**\n * The function swaps the key, value, and height properties between two nodes in a binary tree.\n * @param {N} srcNode - The `srcNode` parameter represents the source node that needs to be swapped\n * with the `destNode`.\n * @param {N} destNode - The `destNode` parameter represents the destination node where the values\n * from the source node (`srcNode`) will be swapped to.\n * @returns The method is returning the `destNode` after swapping its properties with the `srcNode`.\n */\n protected override _swap(srcNode: N, destNode: N): N {\n const {key, value, height} = destNode;\n const tempNode = this.createNode(key, value);\n\n if (tempNode) {\n tempNode.height = height;\n\n destNode.key = srcNode.key;\n destNode.value = srcNode.value;\n destNode.height = srcNode.height;\n\n srcNode.key = tempNode.key;\n srcNode.value = tempNode.value;\n srcNode.height = tempNode.height;\n }\n\n return destNode;\n }\n\n /**\n * The function calculates the balance factor of a node in a binary tree.\n * @param {N} node - The parameter \"node\" represents a node in a 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: N): 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 * 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 {N} node - The parameter \"node\" represents a node in a binary tree data structure.\n */\n protected _updateHeight(node: N): 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 * 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 {N} node - The `node` parameter in the `_balancePath` function represents the node in the\n * AVL tree that needs to be balanced.\n */\n protected _balancePath(node: N): void {\n const path = this.getPathToRoot(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 // 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 * The function `_balanceLL` performs a left-left rotation to balance a binary tree.\n * @param {N} A - A is a node in a binary tree.\n */\n protected _balanceLL(A: N): void {\n const parentOfA = A.parent;\n const B = A.left;\n 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 * The `_balanceLR` function performs a left-right rotation to balance a binary tree.\n * @param {N} A - A is a node in a binary tree.\n */\n protected _balanceLR(A: N): 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) A.parent = C;\n if (B) B.parent = C;\n\n if (C) {\n if (C.left) {\n 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 B && this._updateHeight(B);\n C && this._updateHeight(C);\n }\n\n /**\n * The function `_balanceRR` performs a right-right rotation to balance a binary tree.\n * @param {N} A - A is a node in a binary tree.\n */\n protected _balanceRR(A: N): void {\n const parentOfA = A.parent;\n const B = A.right;\n 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 B && this._updateHeight(B);\n }\n\n /**\n * The function `_balanceRL` performs a right-left rotation to balance a binary tree.\n * @param {N} A - A is a node in a binary tree.\n */\n protected _balanceRL(A: N): 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 A.parent = C;\n if (B) B.parent = C;\n\n if (C) {\n if (C.left) {\n C.left.parent = A;\n }\n if (C.right) {\n 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 B && this._updateHeight(B);\n C && this._updateHeight(C);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n\nimport {\n BinaryTreeDeletedResult,\n BTNCallback,\n BTNKey,\n IterationType,\n RBTNColor,\n RBTreeNodeNested,\n RBTreeOptions\n} from '../../types';\nimport {BST, BSTNode} from \"./bst\";\nimport {IBinaryTree} from \"../../interfaces\";\nimport {BinaryTreeNode} from \"./binary-tree\";\n\nexport class RBTreeNode<V = any, N extends RBTreeNode<V, N> = RBTreeNodeNested<V>> extends BSTNode<V, N> {\n color: RBTNColor;\n constructor(key: BTNKey, value?: V, color: RBTNColor = RBTNColor.BLACK) {\n super(key, value);\n this.color = color;\n }\n}\n\n/**\n * 1. Each node is either red or black.\n * 2. The root node is always black.\n * 3. Leaf nodes are typically NIL nodes and are considered black.\n * 4. Red nodes must have black children.\n * 5. Black balance: Every path from any node to each of its leaf nodes contains the same number of black nodes.\n */\nexport class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RBTreeNodeNested<V>>>\n extends BST<V, N>\n implements IBinaryTree<V, N>\n{\n\n constructor(options?: RBTreeOptions) {\n super(options);\n this._root = this.NIL;\n }\n\n protected _root: N;\n\n get root(): N {\n return this._root;\n }\n\n protected _size: number = 0;\n\n get size(): number {\n return this._size;\n }\n\n NIL: N = new RBTreeNode<V>(NaN) as unknown as N;\n\n override add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | undefined {\n let node: N;\n if (typeof keyOrNode === 'number') {\n node = this.createNode(keyOrNode, value, RBTNColor.RED);\n } else if(keyOrNode instanceof RBTreeNode) {\n node = keyOrNode;\n } else if (keyOrNode === null) {\n return;\n } else if (keyOrNode === undefined) {\n return;\n } else {\n return;\n }\n\n node.left = this.NIL;\n node.right = this.NIL;\n\n let y: N | undefined = undefined;\n let x: N | undefined = this.root;\n\n while (x !== this.NIL) {\n y = x;\n if (x && node.key < x.key) {\n x = x.left;\n } else {\n x = x?.right;\n }\n }\n\n node.parent = y;\n if (y === undefined) {\n this._setRoot(node);\n } else if (node.key < y.key) {\n y.left = node;\n } else {\n y.right = node;\n }\n\n if (node.parent === undefined) {\n node.color = RBTNColor.BLACK;\n this._size++;\n return;\n }\n\n if (node.parent.parent === undefined) {\n this._size++;\n return;\n }\n\n this._fixInsert(node);\n this._size++;\n }\n\n override createNode(key: BTNKey, value?: V, color: RBTNColor = RBTNColor.BLACK): N {\n return new RBTreeNode<V, N>(key, value, color) as N;\n }\n\n\n delete<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | null | undefined,\n callback: C = this.defaultOneParamCallback as C\n ): BinaryTreeDeletedResult<N>[] {\n const ans: BinaryTreeDeletedResult<N>[] = [];\n if (identifier === null) return ans;\n const helper = (node: N | undefined): void => {\n let z: N = this.NIL;\n let x: N | undefined, y: N;\n while (node !== this.NIL) {\n if (node && callback(node) === identifier) {\n z = node;\n }\n\n if (node && identifier && callback(node) <= identifier) {\n node = node.right;\n } else {\n node = node?.left;\n }\n }\n\n if (z === this.NIL) {\n this._size--;\n return;\n }\n\n y = z;\n let yOriginalColor: number = y.color;\n if (z.left === this.NIL) {\n x = z.right;\n this._rbTransplant(z, z.right!);\n } else if (z.right === this.NIL) {\n x = z.left;\n this._rbTransplant(z, z.left!);\n } else {\n y = this.getLeftMost(z.right);\n yOriginalColor = y.color;\n x = y.right;\n if (y.parent === z) {\n x!.parent = y;\n } else {\n this._rbTransplant(y, y.right!);\n y.right = z.right;\n y.right!.parent = y;\n }\n\n this._rbTransplant(z, y);\n y.left = z.left;\n y.left!.parent = y;\n y.color = z.color;\n }\n if (yOriginalColor === RBTNColor.BLACK) {\n this._fixDelete(x!);\n }\n this._size--;\n };\n helper(this.root);\n // TODO\n return ans;\n }\n\n isNode(node: N | undefined): node is N {\n return node !== this.NIL && node !== undefined;\n }\n\n getNode<C extends BTNCallback<N, BTNKey>>(\n identifier: BTNKey,\n callback?: C,\n beginRoot?: N | undefined,\n iterationType?: IterationType\n ): N | undefined;\n\n getNode<C extends BTNCallback<N, N>>(\n identifier: N | undefined,\n callback?: C,\n beginRoot?: N | undefined,\n iterationType?: IterationType\n ): N | undefined;\n\n getNode<C extends BTNCallback<N>>(\n identifier: ReturnType<C>,\n callback: C,\n beginRoot?: N | undefined,\n iterationType?: IterationType\n ): N | undefined;\n\n /**\n * The function `get` returns the first node in a binary tree that matches the given property or key.\n * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of\n * the node that you want to find in the binary tree. It can be either a `BTNKey` or `N`\n * type.\n * @param callback - The `callback` parameter is a function that is used to determine whether a node\n * matches the desired criteria. It takes a node as input and returns a boolean value indicating\n * whether the node matches the criteria or not. The default callback function\n * (`this.defaultOneParamCallback`) is used if no callback function is\n * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies\n * the root node from which the search should begin.\n * @param iterationType - The `iterationType` parameter specifies the type of iteration to be\n * performed when searching for a node in the binary tree. It can have one of the following values:\n * @returns either the found node (of type N) or null if no node is found.\n */\n getNode<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | undefined,\n callback: C = this.defaultOneParamCallback as C,\n beginRoot = this.root,\n iterationType = this.iterationType\n ): N | null | undefined {\n if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;\n\n return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;\n }\n\n /**\n * The function returns the leftmost node in a red-black tree.\n * @param {RBTreeNode} node - The parameter \"node\" is of type RBTreeNode, which represents a node in\n * a Red-Black Tree.\n * @returns The leftmost node in the given RBTreeNode.\n */\n getLeftMost(node: N = this.root): N {\n while (node.left !== undefined && node.left !== this.NIL) {\n node = node.left;\n }\n return node;\n }\n\n /**\n * The function returns the rightmost node in a red-black tree.\n * @param {RBTreeNode} node - The parameter \"node\" is of type RBTreeNode.\n * @returns the rightmost node in a red-black tree.\n */\n getRightMost(node: N): N {\n while (node.right !== undefined && node.right !== this.NIL) {\n node = node.right;\n }\n return node;\n }\n\n /**\n * The function returns the successor of a given node in a red-black tree.\n * @param {RBTreeNode} x - RBTreeNode - The node for which we want to find the successor.\n * @returns the successor of the given RBTreeNode.\n */\n getSuccessor(x: N): N | undefined {\n if (x.right !== this.NIL) {\n return this.getLeftMost(x.right);\n }\n\n let y: N | undefined = x.parent;\n while (y !== this.NIL && y !== undefined && x === y.right) {\n x = y;\n y = y.parent;\n }\n return y;\n }\n\n /**\n * The function returns the predecessor of a given node in a red-black tree.\n * @param {RBTreeNode} x - The parameter `x` is of type `RBTreeNode`, which represents a node in a\n * Red-Black Tree.\n * @returns the predecessor of the given RBTreeNode 'x'.\n */\n getPredecessor(x: N): N {\n if (x.left !== this.NIL) {\n return this.getRightMost(x.left!);\n }\n\n let y: N | undefined = x.parent;\n while (y !== this.NIL && x === y!.left) {\n x = y!;\n y = y!.parent;\n }\n\n return y!;\n }\n\n override clear() {\n this._root = this.NIL;\n this._size = 0;\n }\n\n protected override _setRoot(v: N) {\n if (v) {\n v.parent = undefined;\n }\n this._root = v;\n }\n\n /**\n * The function performs a left rotation on a red-black tree node.\n * @param {RBTreeNode} x - The parameter `x` is a RBTreeNode object.\n */\n protected _leftRotate(x: N): void {\n if (x.right) {\n const y: N = x.right;\n x.right = y.left;\n if (y.left !== this.NIL) {\n if (y.left) y.left.parent = x;\n }\n y.parent = x.parent;\n if (x.parent === undefined) {\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 y.left = x;\n x.parent = y;\n }\n }\n\n /**\n * The function performs a right rotation on a red-black tree node.\n * @param {RBTreeNode} x - x is a RBTreeNode, which represents the node that needs to be right\n * rotated.\n */\n protected _rightRotate(x: N): void {\n if (x.left) {\n const y: N = x.left;\n x.left = y.right;\n if (y.right !== this.NIL) {\n if (y.right) y.right.parent = x;\n }\n y.parent = x.parent;\n if (x.parent === undefined) {\n this._setRoot(y);\n } else if (x === x.parent.right) {\n x.parent.right = y;\n } else {\n x.parent.left = y;\n }\n y.right = x;\n x.parent = y;\n }\n }\n\n /**\n * The _fixDelete function is used to rebalance the Red-Black Tree after a node deletion.\n * @param {RBTreeNode} x - The parameter `x` is of type `RBTreeNode`, which represents a node in a\n * red-black tree.\n */\n protected _fixDelete(x: N): void {\n let s: N | undefined;\n while (x !== this.root && x.color === RBTNColor.BLACK) {\n if (x.parent && x === x.parent.left) {\n s = x.parent.right!;\n if (s.color === 1) {\n s.color = RBTNColor.BLACK;\n x.parent.color = RBTNColor.RED;\n this._leftRotate(x.parent);\n s = x.parent.right!;\n }\n\n if (s.left !== undefined && s.left.color === RBTNColor.BLACK && s.right && s.right.color === RBTNColor.BLACK) {\n s.color = RBTNColor.RED;\n x = x.parent;\n } else {\n if (s.right && s.right.color === RBTNColor.BLACK) {\n if (s.left) s.left.color = RBTNColor.BLACK;\n s.color = RBTNColor.RED;\n this._rightRotate(s);\n s = x.parent.right;\n }\n\n if (s) s.color = x.parent.color;\n x.parent.color = RBTNColor.BLACK;\n if (s && s.right) s.right.color = RBTNColor.BLACK;\n this._leftRotate(x.parent);\n x = this.root;\n }\n } else {\n s = x.parent!.left!;\n if (s.color === 1) {\n s.color = RBTNColor.BLACK;\n x.parent!.color = RBTNColor.RED;\n this._rightRotate(x.parent!);\n s = x.parent!.left;\n }\n\n if (s && s.right && s.right.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {\n s.color = RBTNColor.RED;\n x = x.parent!;\n } else {\n if (s && s.left && s.left.color === RBTNColor.BLACK) {\n if (s.right) s.right.color = RBTNColor.BLACK;\n s.color = RBTNColor.RED;\n this._leftRotate(s);\n s = x.parent!.left;\n }\n\n if (s) s.color = x.parent!.color;\n x.parent!.color = RBTNColor.BLACK;\n if (s && s.left) s.left.color = RBTNColor.BLACK;\n this._rightRotate(x.parent!);\n x = this.root;\n }\n }\n }\n x.color = RBTNColor.BLACK;\n }\n\n /**\n * The function `_rbTransplant` replaces one node in a red-black tree with another node.\n * @param {RBTreeNode} u - The parameter \"u\" represents a RBTreeNode object.\n * @param {RBTreeNode} v - The parameter \"v\" is a RBTreeNode object.\n */\n protected _rbTransplant(u: N, v: N): void {\n if (u.parent === undefined) {\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 v.parent = u.parent;\n }\n\n /**\n * The `_fixInsert` function is used to fix the red-black tree after an insertion operation.\n * @param {RBTreeNode} k - The parameter `k` is a RBTreeNode object, which represents a node in a\n * red-black tree.\n */\n protected _fixInsert(k: N): void {\n let u: N | undefined;\n while (k.parent && k.parent.color === 1) {\n if (k.parent.parent && k.parent === k.parent.parent.right) {\n u = k.parent.parent.left;\n if (u && u.color === 1) {\n u.color = RBTNColor.BLACK;\n k.parent.color = RBTNColor.BLACK;\n k.parent.parent.color = RBTNColor.RED;\n k = k.parent.parent;\n } else {\n if (k === k.parent.left) {\n k = k.parent;\n this._rightRotate(k);\n }\n\n k.parent!.color = RBTNColor.BLACK;\n k.parent!.parent!.color = RBTNColor.RED;\n this._leftRotate(k.parent!.parent!);\n }\n } else {\n u = k.parent.parent!.right;\n\n if (u && u.color === 1) {\n u.color = RBTNColor.BLACK;\n k.parent.color = RBTNColor.BLACK;\n k.parent.parent!.color = RBTNColor.RED;\n k = k.parent.parent!;\n } else {\n if (k === k.parent.right) {\n k = k.parent;\n this._leftRotate(k);\n }\n\n k.parent!.color = RBTNColor.BLACK;\n k.parent!.parent!.color = RBTNColor.RED;\n this._rightRotate(k.parent!.parent!);\n }\n }\n if (k === this.root) {\n break;\n }\n }\n this.root.color = RBTNColor.BLACK;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type {BTNKey, TreeMultisetNodeNested, TreeMultisetOptions} from '../../types';\nimport {BinaryTreeDeletedResult, BTNCallback, CP, FamilyPosition, IterationType} from '../../types';\nimport {IBinaryTree} from '../../interfaces';\nimport {AVLTree, AVLTreeNode} from './avl-tree';\n\nexport class TreeMultisetNode<\n V = any,\n N extends TreeMultisetNode<V, N> = TreeMultisetNodeNested<V>\n> extends AVLTreeNode<V, N> {\n count: number;\n\n /**\n * The constructor function initializes a BinaryTreeNode object with a key, value, and count.\n * @param {BTNKey} key - The `key` parameter is of type `BTNKey` 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: BTNKey, value?: V, count = 1) {\n super(key, value);\n this.count = count;\n }\n}\n\n/**\n * The only distinction between a TreeMultiset and a AVLTree lies in the ability of the former to store duplicate nodes through the utilization of counters.\n */\nexport class TreeMultiset<V = any, N extends TreeMultisetNode<V, N> = TreeMultisetNode<V, TreeMultisetNodeNested<V>>>\n extends AVLTree<V, N>\n implements IBinaryTree<V, N>\n{\n /**\n * The constructor function for a TreeMultiset class in TypeScript, which extends another class and sets an option to\n * merge duplicated values.\n * @param {TreeMultisetOptions} [options] - An optional object that contains additional configuration options for the\n * TreeMultiset.\n */\n constructor(options?: TreeMultisetOptions) {\n super(options);\n }\n\n private _count = 0;\n\n get count(): number {\n return this._count;\n }\n\n /**\n * The function creates a new BSTNode with the given key, value, and count.\n * @param {BTNKey} key - The key parameter is the unique identifier for the binary tree node. It is used to\n * distinguish one node from another in the tree.\n * @param {N} value - The `value` parameter represents the value that will be stored in the binary search tree node.\n * @param {number} [count] - The \"count\" parameter is an optional parameter of type number. It represents the number of\n * occurrences of the value in the binary search tree node. If not provided, the count will default to 1.\n * @returns A new instance of the BSTNode class with the specified key, value, and count (if provided).\n */\n override createNode(key: BTNKey, value?: V, count?: number): N {\n return new TreeMultisetNode(key, value, count) as N;\n }\n\n /**\n * The `add` function adds a new node to a binary search tree, updating the count if the key already\n * exists, and balancing the tree if necessary.\n * @param {BTNKey | N | undefined} keyOrNode - The `keyOrNode` parameter can be either a\n * `BTNKey` (which represents the key of the node to be added), a `N` (which represents a\n * node to be added), or `undefined` (which represents a undefined node).\n * @param [value] - The `value` parameter represents the value associated with the key that is being\n * added to the binary tree.\n * @param [count=1] - The `count` parameter represents the number of occurrences of the key/value\n * pair that will be added to the binary tree. It has a default value of 1, which means that if no\n * count is specified, the default count will be 1.\n * @returns The function `add` returns a value of type `N | undefined | undefined`.\n */\n override add(keyOrNode: BTNKey | N | null | undefined, value?: V, count = 1): N | undefined {\n if(keyOrNode === null) return undefined;\n let inserted: N | undefined = undefined,\n newNode: N | undefined;\n if (keyOrNode instanceof TreeMultisetNode) {\n newNode = this.createNode(keyOrNode.key, keyOrNode.value, keyOrNode.count);\n } else if (keyOrNode === undefined) {\n newNode = undefined;\n } else {\n newNode = this.createNode(keyOrNode, value, count);\n }\n if (!this.root) {\n this._setRoot(newNode);\n this._size = this.size + 1;\n newNode && this._setCount(this.count + newNode.count);\n inserted = this.root;\n } else {\n let cur = this.root;\n let traversing = true;\n while (traversing) {\n if (cur) {\n if (newNode) {\n if (this._compare(cur.key, newNode.key) === CP.eq) {\n cur.value = newNode.value;\n cur.count += newNode.count;\n this._setCount(this.count + newNode.count);\n traversing = false;\n inserted = cur;\n } else if (this._compare(cur.key, newNode.key) === CP.gt) {\n // Traverse left of the node\n if (cur.left === undefined) {\n //Add to the left of the current node\n cur.left = newNode;\n this._size = this.size + 1;\n this._setCount(this.count + newNode.count);\n\n traversing = false;\n inserted = cur.left;\n } else {\n //Traverse the left of the current node\n if (cur.left) cur = cur.left;\n }\n } else if (this._compare(cur.key, newNode.key) === CP.lt) {\n // Traverse right of the node\n if (cur.right === undefined) {\n //Add to the right of the current node\n cur.right = newNode;\n this._size = this.size + 1;\n this._setCount(this.count + newNode.count);\n\n traversing = false;\n inserted = cur.right;\n } else {\n //Traverse the left of the current node\n if (cur.right) cur = cur.right;\n }\n }\n } else {\n // TODO may need to support undefined inserted\n }\n } else {\n traversing = false;\n }\n }\n }\n if (inserted) this._balancePath(inserted);\n return inserted;\n }\n\n /**\n * The function adds a new node to a binary tree if there is an available slot in the parent node.\n * @param {N | undefined} newNode - The `newNode` parameter represents the node that needs to be added to\n * the tree. It can be either a node object (`N`) or `undefined`.\n * @param {N} parent - The `parent` parameter represents the parent node to which the new node will\n * be added as a child.\n * @returns The method `_addTo` returns either the `parent.left`, `parent.right`, or `undefined`.\n */\n override _addTo(newNode: N | undefined, parent: N): N | undefined {\n if (parent) {\n if (parent.left === undefined) {\n parent.left = newNode;\n if (newNode !== undefined) {\n this._size = this.size + 1;\n this._setCount(this.count + newNode.count);\n }\n\n return parent.left;\n } else if (parent.right === undefined) {\n parent.right = newNode;\n if (newNode !== undefined) {\n this._size = this.size + 1;\n this._setCount(this.count + newNode.count);\n }\n return parent.right;\n } else {\n return;\n }\n } else {\n return;\n }\n }\n\n /**\n * The `addMany` function adds multiple keys or nodes to a TreeMultiset and returns an array of the\n * inserted nodes.\n * @param {(BTNKey | undefined)[] | (N | undefined)[]} keysOrNodes - An array of keys or nodes to be\n * added to the multiset. Each element can be either a BTNKey or a TreeMultisetNode.\n * @param {V[]} [data] - The `data` parameter is an optional array of values that correspond\n * to the keys or nodes being added to the multiset. It is used to associate additional data with\n * each key or node.\n * @returns The function `addMany` returns an array of `N`, `undefined`, or `undefined` values.\n */\n override addMany(keysOrNodes: (BTNKey | undefined)[] | (N | undefined)[], data?: V[]): (N | undefined)[] {\n const inserted: (N | undefined | undefined)[] = [];\n\n for (let i = 0; i < keysOrNodes.length; i++) {\n const keyOrNode = keysOrNodes[i];\n\n if (keyOrNode instanceof TreeMultisetNode) {\n inserted.push(this.add(keyOrNode.key, keyOrNode.value, keyOrNode.count));\n continue;\n }\n\n if (keyOrNode === undefined) {\n inserted.push(this.add(NaN, undefined, 0));\n continue;\n }\n\n inserted.push(this.add(keyOrNode, data?.[i], 1));\n }\n return inserted;\n }\n\n /**\n * The `perfectlyBalance` function in TypeScript takes a sorted array of nodes and builds a balanced\n * binary search tree using either a recursive or iterative approach.\n * @param iterationType - The `iterationType` parameter is an optional parameter that specifies the\n * type of iteration to use when building a balanced binary search tree. It can have two possible\n * values:\n * @returns a boolean value.\n */\n override perfectlyBalance(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 === 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 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 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 * The `delete` function in a binary search tree deletes a node from the tree and returns the deleted\n * node along with the parent node that needs to be balanced.\n * @param {ReturnType<C>} identifier - The `identifier` parameter is either a\n * `BTNKey` or a generic type `N`. It represents the property of the node that we are\n * searching for. It can be a specific key value or any other property of the node.\n * @param callback - The `callback` parameter is a function that takes a node as input and returns a\n * value. This value is compared with the `identifier` parameter to determine if the node should be\n * included in the result. The `callback` parameter has a default value of\n * `this.defaultOneParamCallback`\n * @param [ignoreCount=false] - A boolean flag indicating whether to ignore the count of the node\n * being deleted. If set to true, the count of the node will not be considered and the node will be\n * deleted regardless of its count. If set to false (default), the count of the node will be\n * decremented by 1 and\n * @returns The method `delete` returns an array of `BinaryTreeDeletedResult<N>` objects.\n */\n override delete<C extends BTNCallback<N>>(\n identifier: ReturnType<C>,\n callback: C = this.defaultOneParamCallback as C,\n ignoreCount = false\n ): BinaryTreeDeletedResult<N>[] {\n const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];\n if (!this.root) return bstDeletedResult;\n\n const curr: N | undefined = this.getNode(identifier, callback) ?? undefined;\n if (!curr) return bstDeletedResult;\n\n const parent: N | undefined = curr?.parent ? curr.parent : undefined;\n let needBalanced: N | undefined = undefined,\n orgCurrent = curr;\n\n if (curr.count > 1 && !ignoreCount) {\n curr.count--;\n this._setCount(this.count - 1);\n } else {\n if (!curr.left) {\n if (!parent) {\n if (curr.right !== undefined) this._setRoot(curr.right);\n } else {\n const {familyPosition: fp} = curr;\n if (fp === FamilyPosition.LEFT || fp === FamilyPosition.ROOT_LEFT) {\n parent.left = curr.right;\n } else if (fp === FamilyPosition.RIGHT || fp === FamilyPosition.ROOT_RIGHT) {\n parent.right = curr.right;\n }\n needBalanced = parent;\n }\n } else {\n const leftSubTreeRightMost = curr.left ? this.getRightMost(curr.left) : undefined;\n if (leftSubTreeRightMost) {\n const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;\n orgCurrent = this._swap(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 this._setCount(this.count - orgCurrent.count);\n }\n\n bstDeletedResult.push({deleted: orgCurrent, needBalanced});\n\n if (needBalanced) {\n this._balancePath(needBalanced);\n }\n\n return bstDeletedResult;\n }\n\n /**\n * The clear() function clears the contents of a data structure and sets the count to zero.\n */\n clear() {\n super.clear();\n this._setCount(0);\n }\n\n /**\n * The function swaps the values of two nodes in a binary tree.\n * @param {N} srcNode - The source node that needs to be swapped with the destination node.\n * @param {N} destNode - The `destNode` parameter represents the destination node where the values\n * from `srcNode` will be swapped into.\n * @returns The method is returning the `destNode` after swapping its properties with the `srcNode`.\n */\n protected override _swap(srcNode: N, destNode: N): N {\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 destNode.value = srcNode.value;\n destNode.count = srcNode.count;\n destNode.height = srcNode.height;\n\n srcNode.key = tempNode.key;\n srcNode.value = tempNode.value;\n srcNode.count = tempNode.count;\n srcNode.height = tempNode.height;\n }\n\n return destNode;\n }\n\n /**\n * The function sets the value of the \"_count\" property.\n * @param {number} v - number\n */\n protected _setCount(v: number) {\n this._count = v;\n }\n}\n","export class TreeNode<V = any> {\n key: string;\n value?: V | undefined;\n children?: TreeNode<V>[] | undefined;\n\n constructor(key: string, value?: V, children?: TreeNode<V>[]) {\n this.key = key;\n this.value = value || undefined;\n this.children = children || [];\n }\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 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","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n// todo need to be improved\nexport class MatrixNTI2D<V = any> {\n protected readonly _matrix: Array<Array<V>>;\n\n /**\n * The constructor creates a matrix with the specified number of rows and columns, and initializes all elements to a\n * given initial value or 0 if not provided.\n * @param options - An object containing the following properties:\n */\n constructor(options: {row: number; col: number; initialVal?: V}) {\n const {row, col, initialVal} = options;\n this._matrix = new Array(row).fill(undefined).map(() => new Array(col).fill(initialVal || 0));\n }\n\n /* The `toArray` method returns the matrix as a two-dimensional array. It converts the internal representation of the\n matrix, which is an array of arrays, into a format that is more commonly used in JavaScript. */\n toArray(): Array<Array<V>> {\n return this._matrix;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nexport class Vector2D {\n constructor(\n public x: number = 0,\n public y: number = 0,\n public w: number = 1 // needed for matrix multiplication\n ) {}\n\n /**\n * The function checks if the x and y values of a point are both zero.\n * @returns A boolean value indicating whether both the x and y properties of the object are equal to 0.\n */\n get isZero(): boolean {\n return this.x === 0 && this.y === 0;\n }\n\n /**\n * The above function calculates the length of a vector using the Pythagorean theorem.\n * @returns The length of a vector, calculated using the Pythagorean theorem.\n */\n get length(): number {\n return Math.sqrt(this.x * this.x + this.y * this.y);\n }\n\n /**\n * The function calculates the square of the length of a vector.\n * @returns The method is returning the sum of the squares of the x and y values.\n */\n get lengthSq(): number {\n return this.x * this.x + this.y * this.y;\n }\n\n /**\n * The \"rounded\" function returns a new Vector2D object with the x and y values rounded to the nearest whole number.\n * @returns The method is returning a new instance of the Vector2D class with the x and y values rounded to the nearest\n * whole number.\n */\n get rounded(): Vector2D {\n return new Vector2D(Math.round(this.x), Math.round(this.y));\n }\n\n /**\n * The function \"add\" takes two Vector2D objects as parameters and returns a new Vector2D object with the sum of their\n * x and y components.\n * @param {Vector2D} vector1 - The parameter `vector1` is an instance of the `Vector2D` class. It represents a\n * 2-dimensional vector with an `x` and `y` component.\n * @param {Vector2D} vector2 - The parameter \"vector2\" is of type Vector2D. It represents a 2-dimensional vector with\n * an x and y component.\n * @returns The method is returning a new instance of the Vector2D class with the x and y components of the two input\n * vectors added together.\n */\n static add(vector1: Vector2D, vector2: Vector2D): Vector2D {\n return new Vector2D(vector1.x + vector2.x, vector1.y + vector2.y);\n }\n\n /**\n * The subtract function takes two Vector2D objects as parameters and returns a new Vector2D object with the x and y\n * components subtracted.\n * @param {Vector2D} vector1 - The parameter `vector1` is an instance of the `Vector2D` class, representing a\n * 2-dimensional vector. It has properties `x` and `y` which represent the x and y components of the vector\n * respectively.\n * @param {Vector2D} vector2 - The parameter \"vector2\" is a Vector2D object. It represents the second vector that you\n * want to subtract from the first vector.\n * @returns The method is returning a new Vector2D object with the x and y components subtracted from vector1 and\n * vector2.\n */\n static subtract(vector1: Vector2D, vector2: Vector2D): Vector2D {\n return new Vector2D(vector1.x - vector2.x, vector1.y - vector2.y);\n }\n\n /**\n * The function subtracts a given value from the x and y components of a Vector2D object and returns a new Vector2D\n * object.\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D, which represents a 2-dimensional vector with\n * x and y components.\n * @param {number} value - The \"value\" parameter is a number that will be subtracted from both the x and y components\n * of the \"vector\" parameter.\n * @returns A new Vector2D object with the x and y values subtracted by the given value.\n */\n static subtractValue(vector: Vector2D, value: number): Vector2D {\n return new Vector2D(vector.x - value, vector.y - value);\n }\n\n /**\n * The function multiplies a Vector2D object by a given value.\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D, which represents a 2-dimensional vector with\n * x and y components.\n * @param {number} value - The \"value\" parameter is a number that represents the value by which the x and y components\n * of the vector will be multiplied.\n * @returns A new Vector2D object with the x and y values multiplied by the given value.\n */\n static multiply(vector: Vector2D, value: number): Vector2D {\n return new Vector2D(vector.x * value, vector.y * value);\n }\n\n /**\n * The function divides the x and y components of a Vector2D by a given value and returns a new Vector2D.\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D, which represents a 2-dimensional vector with\n * x and y components.\n * @param {number} value - The value parameter is a number that will be used to divide the x and y components of the\n * vector.\n * @returns A new instance of the Vector2D class with the x and y values divided by the given value.\n */\n static divide(vector: Vector2D, value: number): Vector2D {\n return new Vector2D(vector.x / value, vector.y / value);\n }\n\n /**\n * The function checks if two Vector2D objects are equal by comparing their x and y values.\n * @param {Vector2D} vector1 - The parameter `vector1` is of type `Vector2D`, which represents a 2-dimensional vector.\n * It has two properties: `x` and `y`, which represent the x and y components of the vector, respectively.\n * @param {Vector2D} vector2 - The parameter \"vector2\" is of type Vector2D.\n * @returns a boolean value, which indicates whether the two input vectors are equal or not.\n */\n static equals(vector1: Vector2D, vector2: Vector2D): boolean {\n return vector1.x === vector2.x && vector1.y === vector2.y;\n }\n\n /**\n * The function checks if two Vector2D objects are equal within a specified rounding factor.\n * @param {Vector2D} vector1 - The first vector to compare.\n * @param {Vector2D} vector2 - The parameter \"vector2\" is a Vector2D object, which represents a 2-dimensional vector.\n * It is used as one of the inputs for the \"equalsRounded\" function.\n * @param [roundingFactor=12] - The roundingFactor parameter is used to determine the threshold for considering two\n * vectors as equal. If the absolute difference in the x and y components of the vectors is less than the\n * roundingFactor, the vectors are considered equal.\n * @returns a boolean value.\n */\n static equalsRounded(vector1: Vector2D, vector2: Vector2D, roundingFactor = 12): boolean {\n const vector = Vector2D.abs(Vector2D.subtract(vector1, vector2));\n if (vector.x < roundingFactor && vector.y < roundingFactor) {\n return true;\n }\n\n return false;\n }\n\n /**\n * The normalize function takes a vector as input and returns a normalized version of the vector.Normalizes the vector if it matches a certain condition\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D.\n * @returns the normalized vector if its length is greater than a very small value (epsilon), otherwise it returns the\n * original vector.\n */\n static normalize(vector: Vector2D): Vector2D {\n const length = vector.length;\n if (length > 2.220446049250313e-16) {\n // Epsilon\n return Vector2D.divide(vector, length);\n }\n\n return vector;\n }\n\n /**\n * The function truncates a vector to a maximum length if it exceeds that length.Adjusts x and y so that the length of the vector does not exceed max\n * @param {Vector2D} vector - A 2D vector represented by the Vector2D class.\n * @param {number} max - The `max` parameter is a number that represents the maximum length that the `vector` should\n * have.\n * @returns either the original vector or a truncated version of the vector, depending on whether the length of the\n * vector is greater than the maximum value specified.\n */\n static truncate(vector: Vector2D, max: number): Vector2D {\n if (vector.length > max) {\n return Vector2D.multiply(Vector2D.normalize(vector), max);\n }\n\n return vector;\n }\n\n /**\n * The function returns a new Vector2D object that is perpendicular to the input vector.The vector that is perpendicular to this one\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D.\n * @returns A new Vector2D object is being returned.\n */\n static perp(vector: Vector2D): Vector2D {\n return new Vector2D(-vector.y, vector.x);\n }\n\n /**\n * The reverse function takes a Vector2D object and returns a new Vector2D object with the negated x and y values.\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D, which represents a 2-dimensional vector. It\n * has two properties: \"x\" and \"y\", which represent the x and y components of the vector, respectively.\n * @returns A new Vector2D object with the negated x and y values of the input vector. Returns the vector that is the reverse of this vector\n */\n static reverse(vector: Vector2D): Vector2D {\n return new Vector2D(-vector.x, -vector.y);\n }\n\n /**\n * The function takes a Vector2D object as input and returns a new Vector2D object with the absolute values of its x\n * and y components.\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D, which represents a 2-dimensional vector. It\n * has two properties: \"x\" and \"y\", which represent the x and y components of the vector, respectively.\n * @returns The method is returning a new Vector2D object with the absolute values of the x and y components of the\n * input vector.\n */\n static abs(vector: Vector2D): Vector2D {\n return new Vector2D(Math.abs(vector.x), Math.abs(vector.y));\n }\n\n /**\n * The dot function calculates the dot product of two 2D vectors.The dot product of v1 and v2\n * @param {Vector2D} vector1 - The parameter `vector1` represents a 2D vector with its x and y components.\n * @param {Vector2D} vector2 - The \"vector2\" parameter is a Vector2D object. It represents a two-dimensional vector\n * with an x and y component.\n * @returns The dot product of the two input vectors.\n */\n static dot(vector1: Vector2D, vector2: Vector2D): number {\n return vector1.x * vector2.x + vector1.y * vector2.y;\n }\n\n // /**\n // * Transform vectors based on the current tranformation matrices: translation, rotation and scale\n // * @param vectors The vectors to transform\n // */\n // static transform(vector: Vector2D, transformation: Matrix2D): Vector2D {\n // return Matrix2D.multiplyByVector(transformation, vector)\n // }\n\n // /**\n // * Transform vectors based on the current tranformation matrices: translation, rotation and scale\n // * @param vectors The vectors to transform\n // */\n // static transformList(vectors: Vector2D[], transformation: Matrix2D): Vector2D[] {\n // return vectors.map(vector => Matrix2D.multiplyByVector(transformation, vector))\n // }\n\n /**\n * The function calculates the distance between two points in a two-dimensional space.\n * @param {Vector2D} vector1 - The parameter `vector1` represents the first vector in 2D space, while `vector2`\n * represents the second vector. Each vector has an `x` and `y` component, which represent their respective coordinates\n * in the 2D space.\n * @param {Vector2D} vector2 - The `vector2` parameter represents the second vector in the calculation of distance. It\n * is an instance of the `Vector2D` class, which typically has properties `x` and `y` representing the coordinates of\n * the vector in a 2D space.\n * @returns The distance between vector1 and vector2.\n */\n static distance(vector1: Vector2D, vector2: Vector2D): number {\n const ySeparation = vector2.y - vector1.y;\n const xSeparation = vector2.x - vector1.x;\n return Math.sqrt(ySeparation * ySeparation + xSeparation * xSeparation);\n }\n\n /**\n * The function calculates the squared distance between two 2D vectors.\n * @param {Vector2D} vector1 - The parameter `vector1` represents the first vector, which is an instance of the\n * `Vector2D` class. It contains the x and y coordinates of the vector.\n * @param {Vector2D} vector2 - The `vector2` parameter represents the second vector in a two-dimensional space. It has\n * properties `x` and `y` which represent the coordinates of the vector.\n * @returns the square of the distance between the two input vectors.\n */\n static distanceSq(vector1: Vector2D, vector2: Vector2D): number {\n const ySeparation = vector2.y - vector1.y;\n const xSeparation = vector2.x - vector1.x;\n return ySeparation * ySeparation + xSeparation * xSeparation;\n }\n\n /**\n * The sign function determines the sign of the cross product between two 2D vectors.\n * (assuming the Y axis is pointing down, X axis to right like a Window app)\n * @param {Vector2D} vector1 - The parameter `vector1` is of type `Vector2D`, which represents a 2-dimensional vector.\n * It likely has properties `x` and `y` representing the x and y components of the vector, respectively.\n * @param {Vector2D} vector2 - The above code defines a function called \"sign\" that takes two parameters: vector1 and\n * vector2. Both vector1 and vector2 are of type Vector2D.\n * @returns either -1 or 1. Returns positive if v2 is clockwise of this vector, negative if counterclockwise\n */\n static sign(vector1: Vector2D, vector2: Vector2D): number {\n if (vector1.y * vector2.x > vector1.x * vector2.y) {\n return -1;\n }\n\n return 1;\n }\n\n /**\n * The function calculates the angle between a given vector and the negative y-axis.\n * @param {Vector2D} vector - The \"vector\" parameter is an instance of the Vector2D class, which represents a\n * 2-dimensional vector. It has two properties: \"x\" and \"y\", which represent the x and y components of the vector,\n * respectively.\n * @returns the angle between the given vector and the vector (0, -1) in radians.Returns the angle between origin and the given vector in radians\n */\n static angle(vector: Vector2D): number {\n const origin = new Vector2D(0, -1);\n const radian = Math.acos(Vector2D.dot(vector, origin) / (vector.length * origin.length));\n return Vector2D.sign(vector, origin) === 1 ? Math.PI * 2 - radian : radian;\n }\n\n /**\n * The function \"random\" generates a random Vector2D object with x and y values within the specified range.\n * @param {number} maxX - The maxX parameter represents the maximum value for the x-coordinate of the random vector.\n * @param {number} maxY - The `maxY` parameter represents the maximum value for the y-coordinate of the generated\n * random vector.\n * @returns a new instance of the Vector2D class with random x and y values.\n */\n static random(maxX: number, maxY: number): Vector2D {\n const randX = Math.floor(Math.random() * maxX - maxX / 2);\n const randY = Math.floor(Math.random() * maxY - maxY / 2);\n return new Vector2D(randX, randY);\n }\n\n /**\n * The function sets the values of x and y to zero.\n */\n zero(): void {\n this.x = 0;\n this.y = 0;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport {Vector2D} from './vector2d';\n\nexport class Matrix2D {\n protected readonly _matrix: number[][];\n\n /**\n * The constructor function initializes a Matrix2D object with either a default identity matrix, or a provided matrix\n * or Vector2D object.\n * @param {number[][] | Vector2D} [value] - The `value` parameter can be either a 2D array of numbers (`number[][]`) or\n * an instance of the `Vector2D` class.\n */\n constructor(value?: number[][] | Vector2D) {\n if (typeof value === 'undefined') {\n this._matrix = Matrix2D.identity;\n } else if (value instanceof Vector2D) {\n this._matrix = Matrix2D.identity;\n this._matrix[0][0] = value.x;\n this._matrix[1][0] = value.y;\n this._matrix[2][0] = value.w;\n } else {\n this._matrix = value;\n }\n }\n\n /**\n * The function returns a 2D array with three empty arrays.\n * @returns An empty 2-dimensional array with 3 empty arrays inside.\n */\n static get empty(): number[][] {\n return [[], [], []];\n }\n\n /**\n * The above function returns a 3x3 identity matrix.\n * @returns The method is returning a 2-dimensional array of numbers representing the identity matrix.\n */\n static get identity(): number[][] {\n return [\n [1, 0, 0],\n [0, 1, 0],\n [0, 0, 1]\n ];\n }\n\n /**\n * The function returns a two-dimensional array of numbers.\n * @returns The getter method is returning the value of the private variable `_matrix`, which is a two-dimensional\n * array of numbers.\n */\n get m(): number[][] {\n return this._matrix;\n }\n\n /**\n * The function takes two 2D matrices as input and returns their sum as a new 2D matrix.\n * @param {Matrix2D} matrix1 - Matrix2D - The first matrix to be added.\n * @param {Matrix2D} matrix2 - The parameter `matrix2` is a Matrix2D object.\n * @returns a new instance of the Matrix2D class, which is created using the result array.\n */\n static add(matrix1: Matrix2D, matrix2: Matrix2D): Matrix2D {\n const result = Matrix2D.empty;\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < 3; j++) {\n result[i][j] = matrix1.m[i][j] + matrix2.m[i][j];\n }\n }\n return new Matrix2D(result);\n }\n\n /**\n * The function subtracts two 2D matrices and returns the result as a new Matrix2D object.\n * @param {Matrix2D} matrix1 - Matrix2D - The first matrix to subtract from.\n * @param {Matrix2D} matrix2 - Matrix2D is a class representing a 2D matrix. It has a property `m` which is a 2D array\n * representing the matrix elements.\n * @returns a new instance of the Matrix2D class, which is created using the result array.\n */\n static subtract(matrix1: Matrix2D, matrix2: Matrix2D): Matrix2D {\n const result = Matrix2D.empty;\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < 3; j++) {\n result[i][j] = matrix1.m[i][j] - matrix2.m[i][j];\n }\n }\n return new Matrix2D(result);\n }\n\n /**\n * The function multiplies two 2D matrices and returns the result as a new Matrix2D object.\n * @param {Matrix2D} matrix1 - A 2D matrix represented by the Matrix2D class.\n * @param {Matrix2D} matrix2 - The parameter `matrix2` is a 2D matrix of size 3x3.\n * @returns a new instance of the Matrix2D class, created using the result array.\n */\n static multiply(matrix1: Matrix2D, matrix2: Matrix2D): Matrix2D {\n const result = Matrix2D.empty;\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < 3; j++) {\n result[i][j] = 0;\n for (let k = 0; k < 3; k++) {\n result[i][j] += matrix1.m[i][k] * matrix2.m[k][j];\n }\n }\n }\n return new Matrix2D(result);\n }\n\n /**\n * The function multiplies each element of a 2D matrix by a given value and returns the resulting matrix.\n * @param {Matrix2D} matrix - The `matrix` parameter is an instance of the `Matrix2D` class, which represents a 2D\n * matrix. It contains a property `m` that is a 2D array representing the matrix elements.\n * @param {number} value - The `value` parameter is a number that you want to multiply each element of the `matrix` by.\n * @returns a new instance of the Matrix2D class, which is created using the result array.\n */\n static multiplyByValue(matrix: Matrix2D, value: number): Matrix2D {\n const result = Matrix2D.empty;\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < 3; j++) {\n result[i][j] = matrix.m[i][j] * value;\n }\n }\n return new Matrix2D(result);\n }\n\n /**\n * The function multiplies a 2D matrix by a 2D vector and returns the result as a 2D vector.\n * @param {Matrix2D} matrix - The parameter \"matrix\" is of type Matrix2D. It represents a 2-dimensional matrix.\n * @param {Vector2D} vector - The \"vector\" parameter is a 2D vector, represented by an object of type Vector2D.\n * @returns a Vector2D.\n */\n static multiplyByVector(matrix: Matrix2D, vector: Vector2D): Vector2D {\n const resultMatrix = Matrix2D.multiply(matrix, new Matrix2D(vector));\n return resultMatrix.toVector();\n }\n\n /**\n * The function returns a 2D matrix that scales and flips a vector around the center of a given width and height.\n * @param {number} width - The width parameter represents the width of the view or the canvas. It is a number that\n * specifies the width in pixels or any other unit of measurement.\n * @param {number} height - The height parameter represents the height of the view or the canvas. It is used to\n * calculate the centerY value, which is the vertical center of the view.\n * @returns a Matrix2D object.\n */\n static view(width: number, height: number): Matrix2D {\n const scaleStep = 1; // Scale every vector * scaleStep\n const centerX = width / 2;\n const centerY = height / 2;\n const flipX = Math.cos(Math.PI); // rotate 180deg / 3.14radian around X-axis\n\n return new Matrix2D([\n [scaleStep, 0, centerX],\n [0, flipX * scaleStep, centerY],\n [0, 0, 1]\n ]);\n }\n\n /**\n * The function scales a matrix by a given factor.\n * @param {number} factor - The factor parameter is a number that represents the scaling factor by which the matrix\n * should be scaled.\n * @returns the result of multiplying a new instance of Matrix2D by the given factor.\n */\n static scale(factor: number) {\n return Matrix2D.multiplyByValue(new Matrix2D(), factor);\n }\n\n /**\n * The function \"rotate\" takes an angle in radians and returns a 2D transformation matrix for rotating objects.\n * @param {number} radians - The \"radians\" parameter is the angle in radians by which you want to rotate an object.\n * @returns The code is returning a new instance of a Matrix2D object.\n */\n static rotate(radians: number) {\n const cos = Math.cos(radians);\n const sin = Math.sin(radians);\n\n return new Matrix2D([\n [cos, -sin, 0],\n [sin, cos, 0],\n [0, 0, 1]\n ]);\n }\n\n /**\n * The translate function takes a 2D vector and returns a 2D matrix that represents a translation transformation.\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D. It represents a 2D vector with components x\n * and y, and an optional w component.\n * @returns The method is returning a new instance of the Matrix2D class.\n */\n static translate(vector: Vector2D): Matrix2D {\n return new Matrix2D([\n [1, 0, vector.x],\n [0, 1, vector.y],\n [0, 0, vector.w]\n ]);\n }\n\n /**\n * The function \"toVector\" returns a new Vector2D object with the values from the first and second elements of the\n * _matrix array.\n * @returns A new instance of the Vector2D class is being returned. The values of the returned vector are taken from\n * the first column of the matrix.\n */\n toVector(): Vector2D {\n return new Vector2D(this._matrix[0][0], this._matrix[1][0]);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler 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\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 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 this.onMove && this.onMove(this._cur);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n\n/**\n * TrieNode represents a node in the Trie data structure. It holds a character key, a map of children nodes,\n * and a flag indicating whether it's the end of a word.\n */\nexport class TrieNode {\n key: string;\n children: Map<string, TrieNode>;\n isEnd: boolean;\n\n constructor(key: string) {\n this.key = key;\n this.isEnd = false;\n this.children = new Map<string, TrieNode>();\n }\n}\n\n/**\n * Trie represents a Trie data structure. It provides basic Trie operations and additional methods.\n */\nexport class Trie {\n constructor(words?: string[], caseSensitive = true) {\n this._root = new TrieNode('');\n this._caseSensitive = caseSensitive;\n if (words) {\n for (const i of words) {\n this.add(i);\n }\n }\n }\n\n protected _caseSensitive: boolean;\n\n get caseSensitive(): boolean {\n return this._caseSensitive;\n }\n\n protected _root: TrieNode;\n\n get root() {\n return this._root;\n }\n\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 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 cur.isEnd = true;\n return true;\n }\n\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 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 * 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) {\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 return isDeleted;\n }\n\n getHeight() {\n const beginRoot = this.root;\n let maxDepth = 0;\n if (beginRoot) {\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(beginRoot, 0);\n }\n return maxDepth;\n }\n\n // --- start additional methods ---\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 * 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 * 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 * 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 * 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) startNode = nodeC;\n }\n }\n\n if (isAllWhenEmptyPrefix || startNode !== this.root) dfs(startNode, prefix);\n\n return words;\n }\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 // --- end additional methods ---\n}\n"],"mappings":"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","names":["src_exports","__export","AVLTree","AVLTreeNode","AbstractEdge","AbstractGraph","AbstractVertex","ArrayDeque","BST","BSTNode","BinaryIndexedTree","BinaryTree","BinaryTreeNode","CP","Character","CoordinateMap","CoordinateSet","Deque","DirectedEdge","DirectedGraph","DirectedVertex","DoublyLinkedList","DoublyLinkedListNode","FamilyPosition","FibonacciHeap","FibonacciHeapNode","HashMap","HashTable","HashTableNode","Heap","IterationType","LinkedListQueue","MapEdge","MapGraph","MapVertex","Matrix2D","MatrixNTI2D","MaxHeap","MaxPriorityQueue","MinHeap","MinPriorityQueue","Navigator","ObjectDeque","PriorityQueue","Queue","RBTNColor","RBTreeNode","RedBlackTree","SegmentTree","SegmentTreeNode","SinglyLinkedList","SinglyLinkedListNode","SkipList","SkipListNode","Stack","THUNK_SYMBOL","TopologicalProperty","TreeMap","TreeMultiset","TreeMultisetNode","TreeNode","TreeSet","Trie","TrieNode","UndirectedEdge","UndirectedGraph","UndirectedVertex","Vector2D","arrayRemove","getMSB","isThunk","toThunk","trampoline","trampolineAsync","uuidV4","HashTableNode","key","value","HashTable","_HashTable","capacity","hashFn","index","newNode","currentNode","prevNode","keyString","hash","i","charCode","A","M","char","newCapacity","newBuckets","bucket","newIndex","currentNewNode","CoordinateMap","joint","key","value","CoordinateSet","joint","value","TreeMap","TreeSet","HashMap","initialCapacity","loadFactor","hashFn","key","strKey","hash","i","value","index","k","v","bucket","newCapacity","newTable","newIndex","SinglyLinkedListNode","value","SinglyLinkedList","_SinglyLinkedList","data","singlyLinkedList","item","newNode","current","removedNode","index","i","prevNode","valueOrNode","prev","array","next","callback","existingValueOrNode","newValue","existingValue","existingNode","count","mappedList","filteredList","initialValue","accumulator","DoublyLinkedListNode","value","DoublyLinkedList","_DoublyLinkedList","data","doublyLinkedList","item","newNode","removedNode","index","current","i","prevNode","nextNode","existingValueOrNode","newValue","existingNode","valOrNode","node","array","callback","next","mappedList","filteredList","initialValue","accumulator","SkipListNode","key","value","level","SkipList","maxLevel","probability","newNode","update","current","i","firstNode","nextNode","lastLess","Stack","_Stack","elements","element","LinkedListQueue","SinglyLinkedList","value","Queue","_Queue","elements","element","first","index","item","Deque","DoublyLinkedList","ObjectDeque","capacity","value","mid","index","ArrayDeque","uuidV4","c","r","arrayRemove","array","predicate","i","len","result","value","THUNK_SYMBOL","isThunk","fnOrValue","toThunk","fn","thunk","trampoline","args","trampolineAsync","getMSB","Heap","_Heap","options","element","topValue","nodes","order","result","dfsHelper","index","clonedHeap","visitedNode","cloned","top","parentIndex","parent","leftChildIndex","rightChildIndex","length","targetIndex","temp","i","FibonacciHeapNode","degree","FibonacciHeap","comparator","node","head","flag","z","heapToMerge","thisRoot","otherRoot","thisRootRight","otherRootLeft","a","b","y","x","A","d","t","MaxHeap","Heap","options","a","b","MinHeap","Heap","options","a","b","PriorityQueue","Heap","options","MinPriorityQueue","PriorityQueue","options","a","b","MaxPriorityQueue","PriorityQueue","options","a","b","AbstractVertex","key","value","AbstractEdge","weight","uuidV4","AbstractGraph","vertexKey","vertexOrKey","keyOrVertex","newVertex","vertices","removed","v","v1","v2","srcOrEdge","dest","newEdge","srcOrKey","destOrKey","edge","limit","paths","vertex1","vertex2","stack","vertex","path","neighbors","neighbor","newPath","sum","i","isWeight","allPaths","min","visited","queue","Queue","cost","cur","isDFS","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","PriorityQueue","a","b","curHeapNode","dist","distSrcToNeighbor","scanNegativeCycle","getMin","genPath","hasNegativeCycle","numOfVertices","edges","numOfEdges","j","ends","s","sWeight","dWeight","idAndVertices","n","costs","predecessor","k","needCutVertexes","needBridges","needSCCs","needCycles","dfnMap","lowMap","root","cutVertexes","bridges","dfn","childCount","childLow","curLow","edgeCurToNeighbor","SCCs","getSCCs","low","cycles","SCC","DirectedVertex","AbstractVertex","key","value","DirectedEdge","AbstractEdge","src","dest","weight","DirectedGraph","AbstractGraph","srcOrKey","destOrKey","edges","srcOutEdges","edge","removed","arrayRemove","destInEdges","v1","v2","v1ToV2","v2ToV1","vertexOrKey","target","vertex","destinations","outgoingEdges","outEdge","child","propertyName","statusMap","entry","sorted","hasCycle","dfs","cur","children","childStatus","outEdges","neighbors","neighbor","srcVertex","destVertex","UndirectedVertex","AbstractVertex","key","value","UndirectedEdge","AbstractEdge","v1","v2","weight","UndirectedGraph","AbstractGraph","edges","vertex1","vertex2","e","v1Edges","removed","arrayRemove","v2Edges","edge","vertexOrKey","vertex","edgeSet","neighbors","neighborEdges","neighbor","end","endVertex","MapVertex","DirectedVertex","key","value","lat","long","MapEdge","DirectedEdge","src","dest","weight","MapGraph","DirectedGraph","origin","bottomRight","IterationType","FamilyPosition","RBTNColor","TopologicalProperty","CP","BinaryTreeNode","key","value","v","that","BinaryTree","options","iterationType","keyOrNode","_bfs","root","newNode","queue","Queue","cur","inserted","needInsert","keysOrNodes","values","i","data","identifier","callback","bstDeletedResult","node","curr","parent","needBalanced","orgCurrent","leftSubTreeRightMost","parentOfLeftSubTreeMax","fp","distNode","beginRoot","depth","_getMaxHeight","leftHeight","rightHeight","stack","maxHeight","_getMinHeight","leftMinHeight","rightMinHeight","last","depths","onlyOne","ans","_traverse","isReverse","result","trampoline","dfs","min","max","prev","includeNull","pattern","traverse","level","current","levelSize","levelsNodes","_recursive","head","predecessor","x","y","_reverseEdge","pre","next","_printEdge","tail","srcNode","destNode","tempNode","display","lines","_displayAux","line","width","height","middle","n","p","s","u","first_line","second_line","shifted_lines","left","right","m","q","zipped_lines","a","BSTNode","BinaryTreeNode","key","value","v","BST","BinaryTree","options","comparator","keyOrNode","inserted","newNode","cur","traversing","keysOrNodes","data","isBalanceAdd","iterationType","hasNoNull","arr","n","combinedArr","index","sorted","isNodeOrNullTuple","isBinaryTreeKeyOrNullTuple","sortedKeysOrNodes","sortedData","a","recursive","mid","iterative","stack","popped","l","r","beginRoot","identifier","callback","onlyOne","ans","_traverse","queue","Queue","lesserOrGreater","targetNode","targetKey","node","buildBalanceBST","m","midNode","balanced","_height","leftHeight","rightHeight","last","depths","left","right","b","compared","BinaryIndexedTree","frequency","max","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","SegmentTree","values","mid","left","right","cur","index","root","dfs","indexA","indexB","i","j","leftSum","rightSum","AVLTreeNode","BSTNode","key","value","AVLTree","BST","options","keyOrNode","inserted","identifier","callback","node","deletedResults","needBalanced","srcNode","destNode","height","tempNode","rightHeight","path","i","A","parentOfA","B","C","RBTreeNode","BSTNode","key","value","color","RedBlackTree","BST","options","keyOrNode","node","y","x","identifier","callback","ans","z","yOriginalColor","beginRoot","iterationType","BinaryTreeNode","v","s","u","k","TreeMultisetNode","AVLTreeNode","key","value","count","TreeMultiset","AVLTree","options","keyOrNode","inserted","newNode","cur","traversing","parent","keysOrNodes","data","i","iterationType","sorted","node","n","buildBalanceBST","l","r","m","midNode","stack","popped","identifier","callback","ignoreCount","bstDeletedResult","curr","needBalanced","orgCurrent","leftSubTreeRightMost","parentOfLeftSubTreeMax","fp","srcNode","destNode","height","tempNode","v","TreeNode","_TreeNode","key","value","children","maxDepth","bfs","node","level","i","len","MatrixNTI2D","options","row","col","initialVal","Vector2D","_Vector2D","x","y","w","vector1","vector2","vector","value","roundingFactor","length","max","ySeparation","xSeparation","origin","radian","maxX","maxY","randX","randY","Matrix2D","_Matrix2D","value","Vector2D","matrix1","matrix2","result","i","j","k","matrix","vector","width","height","centerX","centerY","flipX","factor","radians","cos","sin","Character","_Character","direction","turning","Navigator","matrix","onMove","cur","charDir","VISITED","forward","row","j","i","TrieNode","key","Trie","words","caseSensitive","i","word","cur","c","nodeC","isDeleted","dfs","char","child","beginRoot","maxDepth","bfs","node","level","children","input","commonPre","prefix","max","isAllWhenEmptyPrefix","found","charNode","startNode","str"]}
1
+ {"version":3,"sources":["../../src/index.ts","../../src/data-structures/hash/hash-table.ts","../../src/data-structures/hash/coordinate-map.ts","../../src/data-structures/hash/coordinate-set.ts","../../src/data-structures/hash/tree-map.ts","../../src/data-structures/hash/tree-set.ts","../../src/data-structures/hash/hash-map.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/utils/utils.ts","../../src/data-structures/heap/heap.ts","../../src/data-structures/heap/max-heap.ts","../../src/data-structures/heap/min-heap.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/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/types/data-structures/binary-tree/binary-tree.ts","../../src/types/data-structures/binary-tree/rb-tree.ts","../../src/types/data-structures/graph/directed-graph.ts","../../src/types/helpers.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/rb-tree.ts","../../src/data-structures/binary-tree/tree-multimap.ts","../../src/data-structures/tree/tree.ts","../../src/data-structures/matrix/matrix.ts","../../src/data-structures/matrix/vector2d.ts","../../src/data-structures/matrix/matrix2d.ts","../../src/data-structures/matrix/navigator.ts","../../src/data-structures/trie/trie.ts"],"sourcesContent":["export * from './data-structures';\nexport * from './utils';\nexport * from './interfaces';\nexport * from './types';\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n\nexport class HashTableNode<K, V> {\n key: K;\n value: V;\n next: HashTableNode<K, V> | null;\n\n constructor(key: K, value: V) {\n this.key = key;\n this.value = value;\n this.next = null;\n }\n}\n\nimport {HashFunction} from '../../types';\n\nexport class HashTable<K, V> {\n protected static readonly DEFAULT_CAPACITY = 16;\n protected static readonly LOAD_FACTOR = 0.75;\n\n constructor(capacity: number = HashTable.DEFAULT_CAPACITY, hashFn?: HashFunction<K>) {\n this._hashFn = hashFn || this._defaultHashFn;\n this._capacity = Math.max(capacity, HashTable.DEFAULT_CAPACITY);\n this._size = 0;\n this._buckets = new Array<HashTableNode<K, V> | null>(this._capacity).fill(null);\n }\n\n protected _capacity: number;\n\n get capacity(): number {\n return this._capacity;\n }\n\n protected _size: number;\n\n get size(): number {\n return this._size;\n }\n\n protected _buckets: Array<HashTableNode<K, V> | null>;\n\n get buckets(): Array<HashTableNode<K, V> | null> {\n return this._buckets;\n }\n\n protected _hashFn: HashFunction<K>;\n\n get hashFn(): HashFunction<K> {\n return this._hashFn;\n }\n\n /**\n * The set function adds a key-value pair to the hash table, handling collisions and resizing if necessary.\n * @param {K} key - The key parameter represents the key of the key-value pair that you want to insert into the hash\n * table. It is of type K, which is a generic type representing the key's data type.\n * @param {V} value - The parameter `value` represents the value that you want to associate with the given key in the hash\n * table.\n * @returns Nothing is being returned. The return type of the `put` method is `void`, which means it does not return any\n * value.\n */\n set(key: K, value: V): void {\n const index = this._hash(key);\n const newNode = new HashTableNode<K, V>(key, value);\n\n if (!this._buckets[index]) {\n this._buckets[index] = newNode;\n } else {\n // Handle collisions, consider using open addressing, etc.\n let currentNode = this._buckets[index]!;\n while (currentNode) {\n if (currentNode.key === key) {\n // If the key already exists, update the value\n currentNode.value = value;\n return;\n }\n if (!currentNode.next) {\n break;\n }\n currentNode = currentNode.next;\n }\n // Add to the end of the linked list\n currentNode.next = newNode;\n }\n this._size++;\n\n // If the load factor is too high, resize the hash table\n if (this._size / this._capacity >= HashTable.LOAD_FACTOR) {\n this._expand();\n }\n }\n\n /**\n * The `get` function retrieves the value associated with a given key from a hash table.\n * @param {K} key - The `key` parameter represents the key of the element that we want to retrieve from the data\n * structure.\n * @returns The method is returning the value associated with the given key if it exists in the hash table. If the key is\n * not found, it returns `undefined`.\n */\n get(key: K): V | undefined {\n const index = this._hash(key);\n let currentNode = this._buckets[index];\n\n while (currentNode) {\n if (currentNode.key === key) {\n return currentNode.value;\n }\n currentNode = currentNode.next;\n }\n return undefined; // Key not found\n }\n\n /**\n * The delete function removes a key-value pair from a hash table.\n * @param {K} key - The `key` parameter represents the key of the key-value pair that needs to be removed from the hash\n * table.\n * @returns Nothing is being returned. The `delete` method has a return type of `void`, which means it does not return\n * any value.\n */\n delete(key: K): void {\n const index = this._hash(key);\n let currentNode = this._buckets[index];\n let prevNode: HashTableNode<K, V> | null = null;\n\n while (currentNode) {\n if (currentNode.key === key) {\n if (prevNode) {\n prevNode.next = currentNode.next;\n } else {\n this._buckets[index] = currentNode.next;\n }\n this._size--;\n currentNode.next = null; // Release memory\n return;\n }\n prevNode = currentNode;\n currentNode = currentNode.next;\n }\n }\n\n /**\n * The function `_defaultHashFn` calculates the hash value of a given key and returns the remainder when divided by the\n * capacity of the data structure.\n * @param {K} key - The `key` parameter is the input value that needs to be hashed. It can be of any type, but in this\n * code snippet, it is checked whether the key is a string or an object. If it is a string, the `_murmurStringHashFn`\n * function is used to\n * @returns the hash value of the key modulo the capacity of the data structure.\n */\n protected _defaultHashFn(key: K): number {\n // Can be replaced with other hash functions as needed\n const hashValue = typeof key === 'string' ? this._murmurStringHashFn(key) : this._objectHash(key);\n return hashValue % this._capacity;\n }\n\n /**\n * The `_multiplicativeStringHashFn` function calculates a hash value for a given string key using the multiplicative\n * string hash function.\n * @param {K} key - The `key` parameter is the input value for which we want to calculate the hash. It can be of any\n * type, as it is generic (`K`). The function converts the `key` to a string using the `String()` function.\n * @returns a number, which is the result of the multiplicative string hash function applied to the input key.\n */\n protected _multiplicativeStringHashFn<K>(key: K): number {\n const keyString = String(key);\n let hash = 0;\n for (let i = 0; i < keyString.length; i++) {\n const charCode = keyString.charCodeAt(i);\n // Some constants for adjusting the hash function\n const A = 0.618033988749895;\n const M = 1 << 30; // 2^30\n hash = (hash * A + charCode) % M;\n }\n return Math.abs(hash); // Take absolute value to ensure non-negative numbers\n }\n\n /**\n * The function `_murmurStringHashFn` calculates a hash value for a given string key using the MurmurHash algorithm.\n * @param {K} key - The `key` parameter is the input value for which you want to calculate the hash. It can be of any\n * type, but it will be converted to a string using the `String()` function before calculating the hash.\n * @returns a number, which is the hash value calculated for the given key.\n */\n protected _murmurStringHashFn<K>(key: K): number {\n const keyString = String(key);\n const seed = 0;\n let hash = seed;\n\n for (let i = 0; i < keyString.length; i++) {\n const char = keyString.charCodeAt(i);\n hash = (hash ^ char) * 0x5bd1e995;\n hash = (hash ^ (hash >>> 15)) * 0x27d4eb2d;\n hash = hash ^ (hash >>> 15);\n }\n\n return Math.abs(hash);\n }\n\n /**\n * The _hash function takes a key and returns a number.\n * @param {K} key - The parameter \"key\" is of type K, which represents the type of the key that will be hashed.\n * @returns The hash function is returning a number.\n */\n protected _hash(key: K): number {\n return this.hashFn(key);\n }\n\n /**\n * The function calculates a hash value for a given string using the djb2 algorithm.\n * @param {string} key - The `key` parameter in the `stringHash` function is a string value that represents the input for\n * which we want to calculate the hash value.\n * @returns a number, which is the hash value of the input string.\n */\n protected _stringHash(key: string): number {\n let hash = 0;\n for (let i = 0; i < key.length; i++) {\n hash = (hash * 31 + key.charCodeAt(i)) & 0xffffffff;\n }\n return hash;\n }\n\n /**\n * The function `_objectHash` takes a key and returns a hash value, using a custom hash function for objects.\n * @param {K} key - The parameter \"key\" is of type \"K\", which means it can be any type. It could be a string, number,\n * boolean, object, or any other type of value. The purpose of the objectHash function is to generate a hash value for\n * the key, which can be used for\n * @returns a number, which is the hash value of the key.\n */\n protected _objectHash(key: K): number {\n // If the key is an object, you can write a custom hash function\n // For example, convert the object's properties to a string and use string hashing\n // This is just an example; you should write a specific object hash function as needed\n return this._stringHash(JSON.stringify(key));\n }\n\n /**\n * The `expand` function increases the capacity of a hash table by creating a new array of buckets with double the\n * capacity and rehashing all the existing key-value pairs into the new buckets.\n */\n protected _expand(): void {\n const newCapacity = this._capacity * 2;\n const newBuckets = new Array<HashTableNode<K, V> | null>(newCapacity).fill(null);\n\n for (const bucket of this._buckets) {\n let currentNode = bucket;\n while (currentNode) {\n const newIndex = this._hash(currentNode.key);\n const newNode = new HashTableNode<K, V>(currentNode.key, currentNode.value);\n\n if (!newBuckets[newIndex]) {\n newBuckets[newIndex] = newNode;\n } else {\n let currentNewNode = newBuckets[newIndex]!;\n while (currentNewNode.next) {\n currentNewNode = currentNewNode.next;\n }\n currentNewNode.next = newNode;\n }\n currentNode = currentNode.next;\n }\n }\n\n this._buckets = newBuckets;\n this._capacity = newCapacity;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nexport class CoordinateMap<V> extends Map<any, V> {\n constructor(joint?: string) {\n super();\n if (joint !== undefined) this._joint = joint;\n }\n\n protected _joint = '_';\n\n get joint(): string {\n return this._joint;\n }\n\n /**\n * The \"has\" function overrides the base class's \"has\" function and checks if a key exists in the map by joining the\n * key array with a specified delimiter.\n * @param {number[]} key - The parameter \"key\" is an array of numbers.\n * @returns The `has` method is being overridden to return the result of calling the `has` method of the superclass\n * (`super.has`) with the `key` array joined together using the `_joint` property.\n */\n override has(key: number[]) {\n return super.has(key.join(this._joint));\n }\n\n /**\n * The function overrides the set method of a Map object to convert the key from an array to a string using a specified\n * delimiter before calling the original set method.\n * @param {number[]} key - The key parameter is an array of numbers.\n * @param {V} value - The value parameter is the value that you want to associate with the specified key.\n * @returns The `set` method is returning the result of calling the `set` method of the superclass\n * (`super.set(key.join(this._joint), value)`).\n */\n override set(key: number[], value: V) {\n return super.set(key.join(this._joint), value);\n }\n\n /**\n * The function overrides the get method to join the key array with a specified joint and then calls the super get\n * method.\n * @param {number[]} key - An array of numbers\n * @returns The code is returning the value associated with the specified key in the map.\n */\n override get(key: number[]) {\n return super.get(key.join(this._joint));\n }\n\n /**\n * The function overrides the delete method and joins the key array using a specified joint character before calling\n * the super delete method.\n * @param {number[]} key - An array of numbers that represents the key to be deleted.\n * @returns The `delete` method is returning the result of calling the `delete` method on the superclass, with the\n * `key` array joined together using the `_joint` property.\n */\n override delete(key: number[]) {\n return super.delete(key.join(this._joint));\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nexport class CoordinateSet extends Set<any> {\n constructor(joint?: string) {\n super();\n if (joint !== undefined) this._joint = joint;\n }\n\n protected _joint = '_';\n\n get joint(): string {\n return this._joint;\n }\n\n /**\n * The \"has\" function overrides the \"has\" method of the superclass and checks if a value exists in an array after\n * joining its elements with a specified separator.\n * @param {number[]} value - The parameter \"value\" is an array of numbers.\n * @returns The overridden `has` method is returning the result of calling the `has` method of the superclass, passing\n * in the joined value as an argument.\n */\n override has(value: number[]) {\n return super.has(value.join(this._joint));\n }\n\n /**\n * The \"add\" function overrides the parent class's \"add\" function by joining the elements of the input array with a\n * specified delimiter before calling the parent class's \"add\" function.\n * @param {number[]} value - An array of numbers\n * @returns The overridden `add` method is returning the result of calling the `add` method of the superclass\n * (`super.add`) with the joined string representation of the `value` array (`value.join(this._joint)`).\n */\n override add(value: number[]) {\n return super.add(value.join(this._joint));\n }\n\n /**\n * The function overrides the delete method and deletes an element from a Set by joining the elements of the input\n * array with a specified joint and then calling the delete method of the parent class.\n * @param {number[]} value - An array of numbers\n * @returns The `delete` method is returning the result of calling the `delete` method of the superclass, with the\n * `value` array joined together using the `_joint` property.\n */\n override delete(value: number[]) {\n return super.delete(value.join(this._joint));\n }\n}\n","export class TreeMap {}\n","export class TreeSet {}\n","import {HashFunction} from '../../types';\n\n/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nexport class HashMap<K, V> {\n /**\n * The constructor initializes the properties of a hash table, including the initial capacity, load factor, capacity\n * multiplier, size, table array, and hash function.\n * @param [initialCapacity=16] - The initial capacity is the initial size of the hash table. It determines the number of\n * buckets or slots available for storing key-value pairs. The default value is 16.\n * @param [loadFactor=0.75] - The load factor is a measure of how full the hash table can be before it is resized. It is\n * a value between 0 and 1, where 1 means the hash table is completely full and 0 means it is completely empty. When the\n * load factor is reached, the hash table will\n * @param [hashFn] - The `hashFn` parameter is an optional parameter that represents the hash function used to calculate\n * the index of a key in the hash table. If a custom hash function is not provided, a default hash function is used. The\n * default hash function converts the key to a string, calculates the sum of the\n */\n constructor(initialCapacity = 16, loadFactor = 0.75, hashFn?: HashFunction<K>) {\n this._initialCapacity = initialCapacity;\n this._loadFactor = loadFactor;\n this._capacityMultiplier = 2;\n this._size = 0;\n this._table = new Array(initialCapacity);\n this._hashFn =\n hashFn ||\n ((key: K) => {\n const strKey = String(key);\n let hash = 0;\n for (let i = 0; i < strKey.length; i++) {\n hash += strKey.charCodeAt(i);\n }\n return hash % this.table.length;\n });\n }\n\n protected _initialCapacity: number;\n\n get initialCapacity(): number {\n return this._initialCapacity;\n }\n\n protected _loadFactor: number;\n\n get loadFactor(): number {\n return this._loadFactor;\n }\n\n protected _capacityMultiplier: number;\n\n get capacityMultiplier(): number {\n return this._capacityMultiplier;\n }\n\n protected _size: number;\n\n get size(): number {\n return this._size;\n }\n\n protected _table: Array<Array<[K, V]>>;\n\n get table(): Array<Array<[K, V]>> {\n return this._table;\n }\n\n protected _hashFn: HashFunction<K>;\n\n get hashFn(): HashFunction<K> {\n return this._hashFn;\n }\n\n set(key: K, value: V): void {\n const loadFactor = this.size / this.table.length;\n if (loadFactor >= this.loadFactor) {\n this.resizeTable(this.table.length * this.capacityMultiplier);\n }\n\n const index = this._hash(key);\n if (!this.table[index]) {\n this.table[index] = [];\n }\n\n // Check if the key already exists in the bucket\n for (let i = 0; i < this.table[index].length; i++) {\n if (this.table[index][i][0] === key) {\n this.table[index][i][1] = value;\n return;\n }\n }\n\n this.table[index].push([key, value]);\n this._size++;\n }\n\n get(key: K): V | undefined {\n const index = this._hash(key);\n if (!this.table[index]) {\n return undefined;\n }\n\n for (const [k, v] of this.table[index]) {\n if (k === key) {\n return v;\n }\n }\n\n return undefined;\n }\n\n delete(key: K): void {\n const index = this._hash(key);\n if (!this.table[index]) {\n return;\n }\n\n for (let i = 0; i < this.table[index].length; i++) {\n if (this.table[index][i][0] === key) {\n this.table[index].splice(i, 1);\n this._size--;\n\n // Check if the table needs to be resized down\n const loadFactor = this.size / this.table.length;\n if (loadFactor < this.loadFactor / this.capacityMultiplier) {\n this.resizeTable(this.table.length / this.capacityMultiplier);\n }\n return;\n }\n }\n }\n\n *entries(): IterableIterator<[K, V]> {\n for (const bucket of this.table) {\n if (bucket) {\n for (const [key, value] of bucket) {\n yield [key, value];\n }\n }\n }\n }\n\n [Symbol.iterator](): IterableIterator<[K, V]> {\n return this.entries();\n }\n\n clear(): void {\n this._size = 0;\n this._table = new Array(this.initialCapacity);\n }\n\n isEmpty(): boolean {\n return this.size === 0;\n }\n\n protected _hash(key: K): number {\n return this._hashFn(key);\n }\n\n /**\n * The `resizeTable` function resizes the table used in a hash map by creating a new table with a specified capacity and\n * rehashing the key-value pairs from the old table into the new table.\n * @param {number} newCapacity - The newCapacity parameter is the desired capacity for the resized table. It represents\n * the number of buckets that the new table should have.\n */\n protected resizeTable(newCapacity: number): void {\n const newTable = new Array(newCapacity);\n for (const bucket of this._table) {\n // Note that this is this._table\n if (bucket) {\n for (const [key, value] of bucket) {\n const newIndex = this._hash(key) % newCapacity;\n if (!newTable[newIndex]) {\n newTable[newIndex] = [];\n }\n newTable[newIndex].push([key, value]);\n }\n }\n }\n this._table = newTable; // Again, here is this._table\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nexport class SinglyLinkedListNode<E = any> {\n value: E;\n next: SinglyLinkedListNode<E> | null;\n\n /**\n * The constructor function initializes an instance of a class with a given value and sets the next property to null.\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 this.value = value;\n this.next = null;\n }\n}\n\nexport class SinglyLinkedList<E = any> {\n /**\n * The constructor initializes the linked list with an empty head, tail, and length.\n */\n constructor() {\n this._head = null;\n this._tail = null;\n this._length = 0;\n }\n\n protected _head: SinglyLinkedListNode<E> | null;\n\n get head(): SinglyLinkedListNode<E> | null {\n return this._head;\n }\n\n protected _tail: SinglyLinkedListNode<E> | null;\n\n get tail(): SinglyLinkedListNode<E> | null {\n return this._tail;\n }\n\n protected _length: number;\n\n get length(): number {\n return this._length;\n }\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 * The `push` function adds a new node with the given value to the end of a singly linked list.\n * @param {E} value - The \"value\" parameter represents the value that you want to add to the linked list. It can be of\n * any type (E) as specified in the generic type declaration of the class or function.\n */\n push(value: E): void {\n const newNode = new SinglyLinkedListNode(value);\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 }\n\n /**\n * The `push` function adds a new node with the given value to the end of a singly linked list.\n * @param {E} value - The \"value\" parameter represents the value that you want to add to the linked list. It can be of\n * any type (E) as specified in the generic type declaration of the class or function.\n */\n addLast(value: E): void {\n this.push(value);\n }\n\n /**\n * The `pop()` function removes and returns the value of the last element in a linked list, updating the head and tail\n * pointers accordingly.\n * @returns The method `pop()` returns the value of the node that is being removed from the end of the linked list. If\n * the linked list is empty, it returns `null`.\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 = null;\n this._tail = null;\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 = null;\n this._tail = current;\n this._length--;\n return value;\n }\n\n /**\n * The `popLast()` function removes and returns the value of the last element in a linked list, updating the head and tail\n * pointers accordingly.\n * @returns The method `pop()` returns the value of the node that is being removed from the end of the linked list. If\n * the linked list is empty, it returns `null`.\n */\n popLast(): E | undefined {\n return this.pop();\n }\n\n /**\n * The `shift()` function removes and returns the value of the first node in a linked list.\n * @returns The value of the node that is being removed from the beginning of the linked list.\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 * The `popFirst()` function removes and returns the value of the first node in a linked list.\n * @returns The value of the node that is being removed from the beginning of the linked list.\n */\n popFirst(): E | undefined {\n return this.shift();\n }\n\n /**\n * The unshift function adds a new node with the given value to the beginning of a singly linked list.\n * @param {E} value - The parameter \"value\" represents the value of the new node that will be added to the beginning of the\n * linked list.\n */\n unshift(value: E): void {\n const newNode = new SinglyLinkedListNode(value);\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 }\n\n /**\n * The addFirst function adds a new node with the given value to the beginning of a singly linked list.\n * @param {E} value - The parameter \"value\" represents the value of the new node that will be added to the beginning of the\n * linked list.\n */\n addFirst(value: E): void {\n this.unshift(value);\n }\n\n /**\n * The function `getAt` returns the value at a specified index in a linked list, or null 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 `getAt(index: number): E | null` returns the value at the specified index in the linked list, or\n * `null` if the index is out of bounds.\n */\n getAt(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 * 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 `null` if the index is out of bounds.\n */\n getNodeAt(index: number): SinglyLinkedListNode<E> | null {\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 * 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 `null` if the index is out of\n * bounds.\n */\n deleteAt(index: number): E | undefined {\n if (index < 0 || index >= this.length) return undefined;\n if (index === 0) return this.shift();\n if (index === this.length - 1) return this.pop();\n\n const prevNode = this.getNodeAt(index - 1);\n const removedNode = prevNode!.next;\n prevNode!.next = removedNode!.next;\n this._length--;\n return removedNode!.value;\n }\n\n /**\n * The delete function removes a node with a specific value from a singly linked list.\n * @param {E | SinglyLinkedListNode<E>} valueOrNode - The `valueOrNode` 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(valueOrNode: E | SinglyLinkedListNode<E> | null | undefined): boolean {\n if (!valueOrNode) return false;\n let value: E;\n if (valueOrNode instanceof SinglyLinkedListNode) {\n value = valueOrNode.value;\n } else {\n value = valueOrNode;\n }\n let current = this.head,\n prev = null;\n\n while (current) {\n if (current.value === value) {\n if (prev === null) {\n this._head = current.next;\n if (current === this.tail) {\n this._tail = null;\n }\n } else {\n prev.next = current.next;\n if (current === this.tail) {\n this._tail = prev;\n }\n }\n this._length--;\n return true;\n }\n prev = current;\n current = current.next;\n }\n\n return false;\n }\n\n /**\n * The `insertAt` function inserts a value at a specified index in a singly linked list.\n * @param {number} index - The index parameter represents the position at which the new value should be inserted in the\n * linked list. It is of type number.\n * @param {E} value - The `value` parameter represents the value that you want to insert into the linked list at the\n * specified index.\n * @returns The `insert` method returns a boolean value. It returns `true` if the insertion is successful, and `false`\n * if the index is out of bounds.\n */\n insertAt(index: number, value: E): boolean {\n if (index < 0 || index > this.length) return false;\n if (index === 0) {\n this.unshift(value);\n return true;\n }\n if (index === this.length) {\n this.push(value);\n return true;\n }\n\n const newNode = new SinglyLinkedListNode(value);\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 * 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 * The `clear` function resets the linked list by setting the head, tail, and length to null and 0 respectively.\n */\n clear(): void {\n this._head = null;\n this._tail = null;\n this._length = 0;\n }\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 const array: E[] = [];\n let current = this.head;\n while (current) {\n array.push(current.value);\n current = current.next;\n }\n return array;\n }\n\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(): void {\n if (!this.head || this.head === this.tail) return;\n\n let prev: SinglyLinkedListNode<E> | null = null;\n let current: SinglyLinkedListNode<E> | null = this.head;\n let next: SinglyLinkedListNode<E> | null = null;\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 }\n\n /**\n * The `find` function iterates through a linked list and returns the first element that satisfies a given condition.\n * @param callback - A function that takes a value of type E as its parameter and returns a boolean value. This\n * function is used to determine whether a particular value in the linked list satisfies a certain condition.\n * @returns The method `find` returns the first element in the linked list that satisfies the condition specified by\n * the callback function. If no element satisfies the condition, it returns `null`.\n */\n find(callback: (value: E) => boolean): E | null {\n let current = this.head;\n while (current) {\n if (callback(current.value)) {\n return current.value;\n }\n current = current.next;\n }\n return null;\n }\n\n /**\n * The `indexOf` function returns the index of the first occurrence of a given value in a linked list.\n * @param {E} value - The value parameter is the value that you want to find the index of in the linked list.\n * @returns The method is returning the index of the first occurrence of the specified value in the linked list. If the\n * value is not found, it returns -1.\n */\n indexOf(value: E): number {\n let index = 0;\n let current = this.head;\n\n while (current) {\n if (current.value === value) {\n return index;\n }\n index++;\n current = current.next;\n }\n\n return -1;\n }\n\n /**\n * The function finds a node in a singly linked list by its value and returns the node if found, otherwise returns\n * null.\n * @param {E} value - The value parameter is the value that we want to search for in the linked list.\n * @returns a `SinglyLinkedListNode<E>` if a node with the specified value is found in the linked list. If no node with\n * the specified value is found, the function returns `null`.\n */\n getNode(value: E): SinglyLinkedListNode<E> | null {\n let current = this.head;\n\n while (current) {\n if (current.value === value) {\n return current;\n }\n current = current.next;\n }\n\n return null;\n }\n\n /**\n * The `insertBefore` function inserts a new value before an existing value in a singly linked list.\n * @param {E | SinglyLinkedListNode<E>} existingValueOrNode - The existing value or node that you want to insert the\n * new value before. It can be either the value itself or a node containing the value in the linked list.\n * @param {E} newValue - The `newValue` parameter represents the value that you want to insert into the linked list.\n * @returns The method `insertBefore` returns a boolean value. It returns `true` if the new value was successfully\n * inserted before the existing value, and `false` otherwise.\n */\n insertBefore(existingValueOrNode: E | SinglyLinkedListNode<E>, newValue: E): boolean {\n if (!this.head) return false;\n\n let existingValue: E;\n if (existingValueOrNode instanceof SinglyLinkedListNode) {\n existingValue = existingValueOrNode.value;\n } else {\n existingValue = existingValueOrNode;\n }\n if (this.head.value === existingValue) {\n this.unshift(newValue);\n return true;\n }\n\n let current = this.head;\n while (current.next) {\n if (current.next.value === existingValue) {\n const newNode = new SinglyLinkedListNode(newValue);\n newNode.next = current.next;\n current.next = newNode;\n this._length++;\n return true;\n }\n current = current.next;\n }\n\n return false;\n }\n\n /**\n * The `insertAfter` function inserts a new node with a given value after an existing node in a singly linked list.\n * @param {E | SinglyLinkedListNode<E>} existingValueOrNode - The existing value or node in the linked list after which\n * the new value will be inserted. It can be either the value of the existing node or the existing node itself.\n * @param {E} newValue - The value that you want to insert into the linked list after the existing value or node.\n * @returns The method returns a boolean value. It returns true if the new value was successfully inserted after the\n * existing value or node, and false if the existing value or node was not found in the linked list.\n */\n insertAfter(existingValueOrNode: E | SinglyLinkedListNode<E>, newValue: E): boolean {\n let existingNode: E | SinglyLinkedListNode<E> | null;\n\n if (existingValueOrNode instanceof SinglyLinkedListNode) {\n existingNode = existingValueOrNode;\n } else {\n existingNode = this.getNode(existingValueOrNode);\n }\n\n if (existingNode) {\n const newNode = new SinglyLinkedListNode(newValue);\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 * The function counts the number of occurrences of a given value in a linked list.\n * @param {E} value - The value parameter is the value that you want to count the occurrences of in the linked list.\n * @returns The count of occurrences of the given value in the linked list.\n */\n countOccurrences(value: E): number {\n let count = 0;\n let current = this.head;\n\n while (current) {\n if (current.value === value) {\n count++;\n }\n current = current.next;\n }\n\n return count;\n }\n\n /**\n * The `forEach` function iterates over each element in a linked list and applies a callback function to each element.\n * @param callback - The callback parameter is a function that takes two arguments: value and index. The value argument\n * represents the value of the current node in the linked list, and the index argument represents the index of the\n * current node in the linked list.\n */\n forEach(callback: (value: E, index: number) => void): void {\n let current = this.head;\n let index = 0;\n while (current) {\n callback(current.value, index);\n current = current.next;\n index++;\n }\n }\n\n /**\n * The `map` function takes a callback function and applies it to each element in the SinglyLinkedList, returning a new\n * SinglyLinkedList with the transformed values.\n * @param callback - The callback parameter is a function that takes a value of type E (the type of values stored in\n * the original SinglyLinkedList) and returns a value of type U (the type of values that will be stored in the mapped\n * SinglyLinkedList).\n * @returns The `map` function is returning a new instance of `SinglyLinkedList<U>` that contains the mapped values.\n */\n map<U>(callback: (value: E) => U): SinglyLinkedList<U> {\n const mappedList = new SinglyLinkedList<U>();\n let current = this.head;\n while (current) {\n mappedList.push(callback(current.value));\n current = current.next;\n }\n return mappedList;\n }\n\n /**\n * The `filter` function iterates through a SinglyLinkedList and returns a new SinglyLinkedList containing only the\n * elements that satisfy the given callback function.\n * @param callback - The `callback` parameter is a function that takes a value of type `E` and returns a boolean value.\n * It is used to determine whether a value should be included in the filtered list or not.\n * @returns The filtered list, which is an instance of the SinglyLinkedList class.\n */\n filter(callback: (value: E) => boolean): SinglyLinkedList<E> {\n const filteredList = new SinglyLinkedList<E>();\n let current = this.head;\n while (current) {\n if (callback(current.value)) {\n filteredList.push(current.value);\n }\n current = current.next;\n }\n return filteredList;\n }\n\n /**\n * The `reduce` function iterates over a linked list and applies a callback function to each element, accumulating a\n * single value.\n * @param callback - The `callback` parameter is a function that takes two arguments: `accumulator` and `value`. It is\n * used to perform a specific operation on each element of the linked list.\n * @param {U} initialValue - The `initialValue` parameter is the initial value of the accumulator. It is the starting\n * point for the reduction operation.\n * @returns The `reduce` method is returning the final value of the accumulator after iterating through all the\n * elements in the linked list.\n */\n reduce<U>(callback: (accumulator: U, value: E) => U, initialValue: U): U {\n let accumulator = initialValue;\n let current = this.head;\n while (current) {\n accumulator = callback(accumulator, current.value);\n current = current.next;\n }\n return accumulator;\n }\n\n /**\n * The function returns an iterator that iterates over the values of a linked list.\n */\n *[Symbol.iterator]() {\n let current = this.head;\n\n while (current) {\n yield current.value;\n current = current.next;\n }\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nexport class DoublyLinkedListNode<E = any> {\n value: E;\n next: DoublyLinkedListNode<E> | null;\n prev: DoublyLinkedListNode<E> | null;\n\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 this.value = value;\n this.next = null;\n this.prev = null;\n }\n}\n\nexport class DoublyLinkedList<E = any> {\n /**\n * The constructor initializes the linked list with an empty head, tail, and length.\n */\n constructor() {\n this._head = null;\n this._tail = null;\n this._length = 0;\n }\n\n protected _head: DoublyLinkedListNode<E> | null;\n\n get head(): DoublyLinkedListNode<E> | null {\n return this._head;\n }\n\n protected _tail: DoublyLinkedListNode<E> | null;\n\n get tail(): DoublyLinkedListNode<E> | null {\n return this._tail;\n }\n\n protected _length: number;\n\n get length(): number {\n return this._length;\n }\n\n get size(): number {\n return this.length;\n }\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 const doublyLinkedList = new DoublyLinkedList<E>();\n for (const item of data) {\n doublyLinkedList.push(item);\n }\n return doublyLinkedList;\n }\n\n /**\n * The push function adds a new node with the given value to the end of the doubly linked list.\n * @param {E} value - The value to be added to the linked list.\n */\n push(value: E): void {\n const newNode = new DoublyLinkedListNode(value);\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 }\n\n /**\n * The addLast function adds a new node with the given value to the end of the doubly linked list.\n * @param {E} value - The value to be added to the linked list.\n */\n addLast(value: E): void {\n this.push(value);\n }\n\n /**\n * The `pop()` function removes and returns the value of the last node in a doubly linked list.\n * @returns The method is returning the value of the removed node (removedNode.value) if the list is not empty. If the\n * list is empty, it returns null.\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 = null;\n this._tail = null;\n } else {\n this._tail = removedNode.prev;\n this.tail!.next = null;\n }\n this._length--;\n return removedNode.value;\n }\n\n /**\n * The `popLast()` function removes and returns the value of the last node in a doubly linked list.\n * @returns The method is returning the value of the removed node (removedNode.value) if the list is not empty. If the\n * list is empty, it returns null.\n */\n popLast(): E | undefined {\n return this.pop();\n }\n\n /**\n * The `shift()` function removes and returns the value of the first node in a doubly linked list.\n * @returns The method `shift()` returns the value of the node that is removed from the beginning of the doubly linked\n * list.\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 = null;\n this._tail = null;\n } else {\n this._head = removedNode.next;\n this.head!.prev = null;\n }\n this._length--;\n return removedNode.value;\n }\n\n /**\n * The `popFirst()` function removes and returns the value of the first node in a doubly linked list.\n * @returns The method `shift()` returns the value of the node that is removed from the beginning of the doubly linked\n * list.\n */\n popFirst(): E | undefined {\n return this.shift();\n }\n\n /**\n * The unshift function adds a new node with the given value to the beginning of a doubly linked list.\n * @param {E} value - The `value` parameter represents the value of the new node that will be added to the beginning of the\n * doubly linked list.\n */\n unshift(value: E): void {\n const newNode = new DoublyLinkedListNode(value);\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 }\n\n /**\n * The addFirst function adds a new node with the given value to the beginning of a doubly linked list.\n * @param {E} value - The `value` parameter represents the value of the new node that will be added to the beginning of the\n * doubly linked list.\n */\n addFirst(value: E): void {\n this.unshift(value);\n }\n\n /**\n * The `getFirst` function returns the first node in a doubly linked list, or null if the list is empty.\n * @returns The method `getFirst()` returns the first node of the doubly linked list, or `null` if the list is empty.\n */\n getFirst(): E | undefined {\n return this.head?.value;\n }\n\n /**\n * The `getLast` function returns the last node in a doubly linked list, or null if the list is empty.\n * @returns The method `getLast()` returns the last node of the doubly linked list, or `null` if the list is empty.\n */\n getLast(): E | undefined {\n return this.tail?.value;\n }\n\n /**\n * The `getAt` function returns the value at a specified index in a linked list, or null 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 null.\n */\n getAt(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 * The function `getNodeAt` returns the node at a given index in a doubly linked list, or null 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 `null`.\n */\n getNodeAt(index: number): DoublyLinkedListNode<E> | null {\n if (index < 0 || index >= this.length) return null;\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 * The function `findNodeByValue` searches for a node with a specific value in a doubly linked list and returns the\n * node if found, otherwise it returns null.\n * @param {E} value - The `value` parameter is the value that we want to search for in the doubly linked list.\n * @returns The function `findNodeByValue` returns a `DoublyLinkedListNode<E>` if a node with the specified value `value`\n * is found in the linked list. If no such node is found, it returns `null`.\n */\n getNode(value: E | null): DoublyLinkedListNode<E> | null {\n let current = this.head;\n\n while (current) {\n if (current.value === value) {\n return current;\n }\n current = current.next;\n }\n\n return null;\n }\n\n /**\n * The `insert` function inserts a value at a specified index in a doubly linked list.\n * @param {number} index - The index parameter represents the position at which the new value should be inserted in the\n * DoublyLinkedList. It is of type number.\n * @param {E} value - The `value` parameter represents the value that you want to insert into the Doubly Linked List at the\n * specified index.\n * @returns The `insert` method returns a boolean value. It returns `true` if the insertion is successful, and `false`\n * if the index is out of bounds.\n */\n insertAt(index: number, value: E): boolean {\n if (index < 0 || index > this.length) return false;\n if (index === 0) {\n this.unshift(value);\n return true;\n }\n if (index === this.length) {\n this.push(value);\n return true;\n }\n\n const newNode = new DoublyLinkedListNode(value);\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 * The `insertBefore` function inserts a new value before an existing value or node in a doubly linked list.\n * @param {E | DoublyLinkedListNode<E>} existingValueOrNode - The existing value or node in the doubly linked list\n * before which the new value will be inserted. It can be either the value of the existing node or the existing node\n * itself.\n * @param {E} newValue - The `newValue` parameter represents the value that you want to insert into the doubly linked\n * list.\n * @returns The method returns a boolean value. It returns `true` if the insertion is successful, and `false` if the\n * insertion fails.\n */\n insertBefore(existingValueOrNode: E | DoublyLinkedListNode<E>, newValue: E): boolean {\n let existingNode;\n\n if (existingValueOrNode instanceof DoublyLinkedListNode) {\n existingNode = existingValueOrNode;\n } else {\n existingNode = this.getNode(existingValueOrNode);\n }\n\n if (existingNode) {\n const newNode = new DoublyLinkedListNode(newValue);\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 * 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 `null` if the index is out of\n * bounds.\n */\n deleteAt(index: number): E | undefined {\n if (index < 0 || index >= this.length) return undefined;\n if (index === 0) return this.shift();\n if (index === this.length - 1) return this.pop();\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 * The `delete` function removes a node from a doubly linked list based on either the node itself or its value.\n * @param {E | DoublyLinkedListNode<E>} valOrNode - The `valOrNode` parameter can accept either a value of type `E` or\n * a `DoublyLinkedListNode<E>` object.\n * @returns The `delete` method returns a boolean value. It returns `true` if the value or node was successfully\n * deleted from the doubly linked list, and `false` if the value or node was not found in the list.\n */\n delete(valOrNode: E | DoublyLinkedListNode<E> | null): boolean {\n let node: DoublyLinkedListNode<E> | null;\n\n if (valOrNode instanceof DoublyLinkedListNode) {\n node = valOrNode;\n } else {\n node = this.getNode(valOrNode);\n }\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 prevNode!.next = nextNode;\n nextNode!.prev = prevNode;\n this._length--;\n }\n return true;\n }\n return false;\n }\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 const array: E[] = [];\n let current = this.head;\n while (current) {\n array.push(current.value);\n current = current.next;\n }\n return array;\n }\n\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 * The `clear` function resets the linked list by setting the head, tail, and length to null and 0 respectively.\n */\n clear(): void {\n this._head = null;\n this._tail = null;\n this._length = 0;\n }\n\n /**\n * The `find` function iterates through a linked list and returns the first element that satisfies a given condition.\n * @param callback - A function that takes a value of type E as its parameter and returns a boolean value. This\n * function is used to determine whether a particular value in the linked list satisfies a certain condition.\n * @returns The method `find` returns the first element in the linked list that satisfies the condition specified by\n * the callback function. If no element satisfies the condition, it returns `null`.\n */\n find(callback: (value: E) => boolean): E | null {\n let current = this.head;\n while (current) {\n if (callback(current.value)) {\n return current.value;\n }\n current = current.next;\n }\n return null;\n }\n\n /**\n * The function returns the index of the first occurrence of a given value in a linked list.\n * @param {E} value - The parameter `value` is of type `E`, which means it can be any data type. It represents the value\n * that we are searching for in the linked list.\n * @returns The method `indexOf` returns the index of the first occurrence of the specified value `value` in the linked\n * list. If the value is not found, it returns -1.\n */\n indexOf(value: E): number {\n let index = 0;\n let current = this.head;\n while (current) {\n if (current.value === value) {\n return index;\n }\n index++;\n current = current.next;\n }\n return -1;\n }\n\n /**\n * The `findBackward` function iterates through a linked list from the last node to the first node and returns the last\n * value that satisfies the given callback function, or null if no value satisfies the callback.\n * @param callback - A function that takes a value of type E as its parameter and returns a boolean value. This\n * function is used to determine whether a given value satisfies a certain condition.\n * @returns The method `findBackward` returns the last value in the linked list that satisfies the condition specified by\n * the callback function. If no value satisfies the condition, it returns `null`.\n */\n findBackward(callback: (value: E) => boolean): E | null {\n let current = this.tail;\n while (current) {\n if (callback(current.value)) {\n return current.value;\n }\n current = current.prev;\n }\n return null;\n }\n\n /**\n * The `toArrayBackward` function converts a doubly linked list into an array in reverse order.\n * @returns The `toArrayBackward()` function returns an array of type `E[]`.\n */\n toArrayBackward(): E[] {\n const array: E[] = [];\n let current = this.tail;\n while (current) {\n array.push(current.value);\n current = current.prev;\n }\n return array;\n }\n\n /**\n * The `reverse` function reverses the order of the elements in a doubly linked list.\n */\n reverse(): void {\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 }\n\n /**\n * The `forEach` function iterates over each element in a linked list and applies a callback function to each element.\n * @param callback - The callback parameter is a function that takes two arguments: value and index. The value argument\n * represents the value of the current node in the linked list, and the index argument represents the index of the\n * current node in the linked list.\n */\n forEach(callback: (value: E, index: number) => void): void {\n let current = this.head;\n let index = 0;\n while (current) {\n callback(current.value, index);\n current = current.next;\n index++;\n }\n }\n\n /**\n * The `map` function takes a callback function and applies it to each element in the DoublyLinkedList, returning a new\n * DoublyLinkedList with the transformed values.\n * @param callback - The callback parameter is a function that takes a value of type E (the type of values stored in\n * the original DoublyLinkedList) and returns a value of type U (the type of values that will be stored in the mapped\n * DoublyLinkedList).\n * @returns The `map` function is returning a new instance of `DoublyLinkedList<U>` that contains the mapped values.\n */\n map<U>(callback: (value: E) => U): DoublyLinkedList<U> {\n const mappedList = new DoublyLinkedList<U>();\n let current = this.head;\n while (current) {\n mappedList.push(callback(current.value));\n current = current.next;\n }\n return mappedList;\n }\n\n /**\n * The `filter` function iterates through a DoublyLinkedList and returns a new DoublyLinkedList containing only the\n * elements that satisfy the given callback function.\n * @param callback - The `callback` parameter is a function that takes a value of type `E` and returns a boolean value.\n * It is used to determine whether a value should be included in the filtered list or not.\n * @returns The filtered list, which is an instance of the DoublyLinkedList class.\n */\n filter(callback: (value: E) => boolean): DoublyLinkedList<E> {\n const filteredList = new DoublyLinkedList<E>();\n let current = this.head;\n while (current) {\n if (callback(current.value)) {\n filteredList.push(current.value);\n }\n current = current.next;\n }\n return filteredList;\n }\n\n /**\n * The `reduce` function iterates over a linked list and applies a callback function to each element, accumulating a\n * single value.\n * @param callback - The `callback` parameter is a function that takes two arguments: `accumulator` and `value`. It is\n * used to perform a specific operation on each element of the linked list.\n * @param {U} initialValue - The `initialValue` parameter is the initial value of the accumulator. It is the starting\n * point for the reduction operation.\n * @returns The `reduce` method is returning the final value of the accumulator after iterating through all the\n * elements in the linked list.\n */\n reduce<U>(callback: (accumulator: U, value: E) => U, initialValue: U): U {\n let accumulator = initialValue;\n let current = this.head;\n while (current) {\n accumulator = callback(accumulator, current.value);\n current = current.next;\n }\n return accumulator;\n }\n\n /**\n * The `insertAfter` function inserts a new node with a given value after an existing node in a doubly linked list.\n * @param {E | DoublyLinkedListNode<E>} existingValueOrNode - The existing value or node in the doubly linked list\n * after which the new value will be inserted. It can be either the value of the existing node or the existing node\n * itself.\n * @param {E} newValue - The value that you want to insert into the doubly linked list.\n * @returns The method returns a boolean value. It returns true if the insertion is successful, and false if the\n * existing value or node is not found in the doubly linked list.\n */\n insertAfter(existingValueOrNode: E | DoublyLinkedListNode<E>, newValue: E): boolean {\n let existingNode;\n\n if (existingValueOrNode instanceof DoublyLinkedListNode) {\n existingNode = existingValueOrNode;\n } else {\n existingNode = this.getNode(existingValueOrNode);\n }\n\n if (existingNode) {\n const newNode = new DoublyLinkedListNode(newValue);\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 * The function returns an iterator that iterates over the values of a linked list.\n */\n *[Symbol.iterator]() {\n let current = this.head;\n\n while (current) {\n yield current.value;\n current = current.next;\n }\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\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\nexport class SkipList<K, V> {\n /**\n * The constructor initializes a SkipList with a specified maximum level and probability.\n * @param [maxLevel=16] - The `maxLevel` parameter represents the maximum level that a skip list can have. It determines\n * the maximum number of levels that can be created in the skip list.\n * @param [probability=0.5] - The probability parameter represents the probability of a node being promoted to a higher\n * level in the skip list. It is used to determine the height of each node in the skip list.\n */\n constructor(maxLevel = 16, probability = 0.5) {\n this._head = new SkipListNode<K, V>(null as any, null as any, maxLevel);\n this._level = 0;\n this._maxLevel = maxLevel;\n this._probability = probability;\n }\n\n protected _head: SkipListNode<K, V>;\n\n get head(): SkipListNode<K, V> {\n return this._head;\n }\n\n protected _level: number;\n\n get level(): number {\n return this._level;\n }\n\n protected _maxLevel: number;\n\n get maxLevel(): number {\n return this._maxLevel;\n }\n\n protected _probability: number;\n\n get probability(): number {\n return this._probability;\n }\n\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] !== null) {\n this._level = Math.max(this.level, newNode.forward.length);\n }\n }\n\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 has(key: K): boolean {\n return this.get(key) !== undefined;\n }\n\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] === null) {\n this._level--;\n }\n return true;\n }\n\n return false;\n }\n\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 getFirst(): V | undefined {\n const firstNode = this.head.forward[0];\n return firstNode ? firstNode.value : undefined;\n }\n\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 getLast(): 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 * 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 * 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 = null;\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 * 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 * @license MIT\n * @copyright Tyler Zeng <zrwusa@gmail.com>\n * @class\n */\nexport class Stack<E = any> {\n /**\n * The constructor initializes an array of elements, which can be provided as an optional parameter.\n * @param {E[]} [elements] - The `elements` parameter is an optional parameter of type `E[]`, which represents an array\n * of elements of type `E`. It is used to initialize the `_elements` property of the class. If the `elements` parameter\n * is provided and is an array, it is assigned to the `_elements\n */\n constructor(elements?: E[]) {\n this._elements = Array.isArray(elements) ? elements : [];\n }\n\n protected _elements: E[];\n\n get elements(): E[] {\n return this._elements;\n }\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 * 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 * The size() function returns the number of elements in an array.\n * @returns The size of the elements array.\n */\n size(): number {\n return this.elements.length;\n }\n\n /**\n * The `peek` function returns the last element of an array, or null if the array is empty.\n * @returns The `peek()` function returns the last element of the `_elements` array, or `null` if the array is empty.\n */\n peek(): E | null {\n if (this.isEmpty()) return null;\n\n return this.elements[this.elements.length - 1];\n }\n\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): Stack<E> {\n this.elements.push(element);\n return this;\n }\n\n /**\n * The `pop` function removes and returns the last element from an array, or returns null 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 `null`.\n */\n pop(): E | null {\n if (this.isEmpty()) return null;\n\n return this.elements.pop() || null;\n }\n\n /**\n * The toArray function returns a copy of the elements in an array.\n * @returns An array of type E.\n */\n toArray(): E[] {\n return this.elements.slice();\n }\n\n /**\n * The clear function clears the elements array.\n */\n clear(): void {\n this._elements = [];\n }\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> {\n return new Stack(this.elements.slice());\n }\n}\n","/**\n * @license MIT\n * @copyright Tyler Zeng <zrwusa@gmail.com>\n * @class\n */\nimport {SinglyLinkedList} from '../linked-list';\n\nexport class LinkedListQueue<E = any> extends SinglyLinkedList<E> {\n /**\n * The enqueue function adds a value to the end of an array.\n * @param {E} value - The value parameter represents the value that you want to add to the queue.\n */\n enqueue(value: E) {\n this.push(value);\n }\n\n /**\n * The `dequeue` function removes and returns the first element from a queue, or returns null if the queue is empty.\n * @returns The method is returning the element at the front of the queue, or null if the queue is empty.\n */\n dequeue(): E | undefined {\n return this.shift();\n }\n\n /**\n * The `getFirst` function returns the value of the head node in a linked list, or `undefined` if the list is empty.\n * @returns The `getFirst()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`.\n */\n getFirst(): E | undefined {\n return this.head?.value;\n }\n\n /**\n * The `peek` function returns the value of the head node in a linked list, or `undefined` if the list is empty.\n * @returns The `peek()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`.\n */\n peek(): E | undefined {\n return this.getFirst();\n }\n}\n\nexport class Queue<E = any> {\n /**\n * The constructor initializes an instance of a class with an optional array of elements and sets the offset to 0.\n * @param {E[]} [elements] - The `elements` parameter is an optional array of elements of type `E`. If provided, it\n * will be used to initialize the `_nodes` property of the class. If not provided, the `_nodes` property will be\n * initialized as an empty array.\n */\n constructor(elements?: E[]) {\n this._nodes = elements || [];\n this._offset = 0;\n }\n\n protected _nodes: E[];\n\n get nodes(): E[] {\n return this._nodes;\n }\n\n protected _offset: number;\n\n get offset(): number {\n return this._offset;\n }\n\n /**\n * The size function returns the number of elements in an array.\n * @returns {number} The size of the array, which is the difference between the length of the array and the offset.\n */\n get size(): number {\n return this.nodes.length - this.offset;\n }\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 * @static\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 * The push function adds an element to the end of the queue and returns the updated queue.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 The `add` method is returning a `Queue<E>` object.\n */\n push(element: E): Queue<E> {\n this.nodes.push(element);\n return this;\n }\n\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 `null` if the queue is empty.\n */\n shift(): E | undefined {\n if (this.size === 0) return undefined;\n\n const first = this.getFirst();\n this._offset += 1;\n\n if (this.offset * 2 < this.nodes.length) return first;\n\n // only delete dequeued elements when reaching half size\n // to decrease latency of shifting elements.\n this._nodes = this.nodes.slice(this.offset);\n this._offset = 0;\n return first;\n }\n\n /**\n * The `getFirst` function returns the first element of the array `_nodes` if it exists, otherwise it returns `null`.\n * @returns The `getFirst()` method returns the first element of the data structure, represented by the `_nodes` array at\n * the `_offset` index. If the data structure is empty (size is 0), it returns `null`.\n */\n getFirst(): E | undefined {\n return this.size > 0 ? this.nodes[this.offset] : undefined;\n }\n\n /**\n * The `peek` function returns the first element of the array `_nodes` if it exists, otherwise it returns `null`.\n * @returns The `peek()` method returns the first element of the data structure, represented by the `_nodes` array at\n * the `_offset` index. If the data structure is empty (size is 0), it returns `null`.\n */\n peek(): E | undefined {\n return this.getFirst();\n }\n\n /**\n * The `getLast` function returns the last element in an array-like data structure, or null if the structure is empty.\n * @returns The method `getLast()` returns the last element of the `_nodes` array if the array is not empty. If the\n * array is empty, it returns `null`.\n */\n getLast(): E | undefined {\n return this.size > 0 ? this.nodes[this.nodes.length - 1] : undefined;\n }\n\n /**\n * The `peekLast` function returns the last element in an array-like data structure, or null if the structure is empty.\n * @returns The method `peekLast()` returns the last element of the `_nodes` array if the array is not empty. If the\n * array is empty, it returns `null`.\n */\n peekLast(): E | undefined {\n return this.getLast();\n }\n\n /**\n * The enqueue function adds a value to the end of a queue.\n * @param {E} value - The value parameter represents the value that you want to add to the queue.\n */\n enqueue(value: E) {\n this.push(value);\n }\n\n /**\n * The `dequeue` function removes and returns the first element from a queue, or returns null if the queue is empty.\n * @returns The method is returning a value of type E or null.\n */\n dequeue(): E | undefined {\n return this.shift();\n }\n\n getAt(index: number): E | undefined {\n return this.nodes[index];\n }\n\n /**\n * The function checks if a data structure is empty by comparing its size to zero.\n * @returns {boolean} 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 * The toArray() function returns an array of elements from the current offset to the end of the _nodes array.\n * @returns An array of type E is being returned.\n */\n toArray(): E[] {\n return this.nodes.slice(this.offset);\n }\n\n /**\n * The clear function resets the nodes array and offset to their initial values.\n */\n clear(): void {\n this._nodes = [];\n this._offset = 0;\n }\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(): Queue<E> {\n return new Queue(this.nodes.slice(this.offset));\n }\n\n *[Symbol.iterator]() {\n for (const item of this.nodes) {\n yield item;\n }\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport {DoublyLinkedList} from '../linked-list';\n\n// O(n) time complexity of obtaining the value\n// O(1) time complexity of adding at the beginning and the end\nexport class Deque<E = any> extends DoublyLinkedList<E> {}\n\n// O(1) time complexity of obtaining the value\n// O(n) time complexity of adding at the beginning and the end\n// todo tested slowest one\nexport class ObjectDeque<E = number> {\n constructor(capacity?: number) {\n if (capacity !== undefined) this._capacity = capacity;\n }\n\n protected _nodes: {[key: number]: E} = {};\n\n get nodes(): {[p: number]: E} {\n return this._nodes;\n }\n\n protected _capacity = Number.MAX_SAFE_INTEGER;\n\n get capacity(): number {\n return this._capacity;\n }\n\n protected _first = -1;\n\n get first(): number {\n return this._first;\n }\n\n protected _last = -1;\n\n get last(): number {\n return this._last;\n }\n\n protected _size = 0;\n\n get size(): number {\n return this._size;\n }\n\n /**\n * The \"addFirst\" function adds a value to the beginning of an array-like data structure.\n * @param {E} value - The `value` parameter represents the value that you want to add to the beginning of the data\n * structure.\n */\n addFirst(value: E) {\n if (this.size === 0) {\n const mid = Math.floor(this.capacity / 2);\n this._first = mid;\n this._last = mid;\n } else {\n this._first--;\n }\n this.nodes[this.first] = value;\n this._size++;\n }\n\n /**\n * The addLast function adds a value to the end of an array-like data structure.\n * @param {E} value - The `value` parameter represents the value that you want to add to the end of the data structure.\n */\n addLast(value: E) {\n if (this.size === 0) {\n const mid = Math.floor(this.capacity / 2);\n this._first = mid;\n this._last = mid;\n } else {\n this._last++;\n }\n this.nodes[this.last] = value;\n this._size++;\n }\n\n /**\n * The function `popFirst()` removes and returns the first element in a data structure.\n * @returns The value of the first element in the data structure.\n */\n popFirst() {\n if (!this.size) return;\n const value = this.getFirst();\n delete this.nodes[this.first];\n this._first++;\n this._size--;\n return value;\n }\n\n /**\n * The `getFirst` function returns the first element in an array-like data structure if it exists.\n * @returns The element at the first position of the `_nodes` array.\n */\n getFirst() {\n if (this.size) return this.nodes[this.first];\n }\n\n /**\n * The `popLast()` function removes and returns the last element in a data structure.\n * @returns The value that was removed from the data structure.\n */\n popLast() {\n if (!this.size) return;\n const value = this.getLast();\n delete this.nodes[this.last];\n this._last--;\n this._size--;\n\n return value;\n }\n\n /**\n * The `getLast()` function returns the last element in an array-like data structure.\n * @returns The last element in the array \"_nodes\" is being returned.\n */\n getLast() {\n if (this.size) return this.nodes[this.last];\n }\n\n /**\n * The get function returns the element at the specified index in an array-like data structure.\n * @param {number} index - The index parameter is a number that represents the position of the element you want to\n * retrieve from the array.\n * @returns The element at the specified index in the `_nodes` array is being returned. If there is no element at that\n * index, `null` is returned.\n */\n get(index: number) {\n return this.nodes[this.first + index] || null;\n }\n\n /**\n * The function checks if the size of a data structure is less than or equal to zero.\n * @returns The method is returning a boolean value indicating whether the size of the object is less than or equal to 0.\n */\n isEmpty() {\n return this.size <= 0;\n }\n}\n\n// O(1) time complexity of obtaining the value\n// O(n) time complexity of adding at the beginning and the end\nexport class ArrayDeque<E> {\n protected _nodes: E[] = [];\n\n get nodes(): E[] {\n return this._nodes;\n }\n\n get size() {\n return this.nodes.length;\n }\n\n /**\n * O(n) time complexity of adding at the beginning and the end\n */\n\n /**\n * The function \"addLast\" adds a value to the end of an array.\n * @param {E} value - The value parameter represents the value that you want to add to the end of the array.\n * @returns The return value is the new length of the array after the value has been added.\n */\n addLast(value: E) {\n return this.nodes.push(value);\n }\n\n /**\n * The function \"popLast\" returns and removes the last element from an array, or returns null if the array is empty.\n * @returns The method `popLast()` returns the last element of the `_nodes` array, or `null` if the array is empty.\n */\n popLast(): E | null {\n return this.nodes.pop() ?? null;\n }\n\n /**\n * The `popFirst` function removes and returns the first element from an array, or returns null if the array is empty.\n * @returns The `popFirst()` function returns the first element of the `_nodes` array, or `null` if the array is\n * empty.\n */\n popFirst(): E | null {\n return this.nodes.shift() ?? null;\n }\n\n /**\n * O(n) time complexity of adding at the beginning and the end\n */\n\n /**\n * The function \"addFirst\" adds a value to the beginning of an array.\n * @param {E} value - The value parameter represents the value that you want to add to the beginning of the array.\n * @returns The return value of the `addFirst` function is the new length of the array `_nodes` after adding the\n * `value` at the beginning.\n */\n addFirst(value: E) {\n return this.nodes.unshift(value);\n }\n\n /**\n * The `getFirst` function returns the first element of an array or null if the array is empty.\n * @returns The function `getFirst()` is returning the first element (`E`) of the `_nodes` array. If the array is\n * empty, it will return `null`.\n */\n getFirst(): E | null {\n return this.nodes[0] ?? null;\n }\n\n /**\n * The `getLast` function returns the last element of an array or null if the array is empty.\n * @returns The method `getLast()` returns the last element of the `_nodes` array, or `null` if the array is empty.\n */\n getLast(): E | null {\n return this.nodes[this.nodes.length - 1] ?? null;\n }\n\n /**\n * O(1) time complexity of obtaining the value\n */\n\n /**\n * The get function returns the element at the specified index in an array, or null if the index is out of bounds.\n * @param {number} index - The index parameter is a number that represents the position of the element you want to\n * retrieve from the array.\n * @returns The method is returning the element at the specified index in the `_nodes` array. If the element exists, it\n * will be returned. If the element does not exist (i.e., the index is out of bounds), `null` will be returned.\n */\n get(index: number): E | null {\n return this.nodes[index] ?? null;\n }\n\n /**\n * The set function assigns a value to a specific index in an array.\n * @param {number} index - The index parameter is a number that represents the position of the element in the array\n * that you want to set a new value for.\n * @param {E} value - The value parameter represents the new value that you want to set at the specified index in the\n * _nodes array.\n * @returns The value that is being set at the specified index in the `_nodes` array.\n */\n set(index: number, value: E) {\n return (this.nodes[index] = value);\n }\n\n /**\n * The insert function adds a value at a specified index in an array.\n * @param {number} index - The index parameter specifies the position at which the value should be inserted in the\n * array. It is a number that represents the index of the array where the value should be inserted. The index starts\n * from 0, so the first element of the array has an index of 0, the second element has\n * @param {E} value - The value parameter represents the value that you want to insert into the array at the specified\n * index.\n * @returns The splice method returns an array containing the removed elements, if any. In this case, since no elements\n * are being removed, an empty array will be returned.\n */\n insert(index: number, value: E) {\n return this.nodes.splice(index, 0, value);\n }\n\n /**\n * The delete function removes an element from an array at a specified index.\n * @param {number} index - The index parameter specifies the position of the element to be removed from the array. It\n * is a number that represents the index of the element to be removed.\n * @returns The method is returning an array containing the removed element.\n */\n delete(index: number) {\n return this.nodes.splice(index, 1);\n }\n\n /**\n * The function checks if an array called \"_nodes\" is empty.\n * @returns The method `isEmpty()` is returning a boolean value. It returns `true` if the length of the `_nodes` array\n * is 0, indicating that the array is empty. Otherwise, it returns `false`.\n */\n isEmpty() {\n return this.nodes.length === 0;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type {Thunk, ToThunkFn, TrlAsyncFn, TrlFn} from '../types';\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\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\nexport const isThunk = (fnOrValue: any) => {\n return typeof fnOrValue === 'function' && fnOrValue.__THUNK__ === THUNK_SYMBOL;\n};\n\nexport const toThunk = (fn: ToThunkFn): Thunk => {\n const thunk = () => fn();\n thunk.__THUNK__ = THUNK_SYMBOL;\n return thunk;\n};\n\nexport const trampoline = (fn: TrlFn) => {\n const cont = (...args: [...Parameters<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\nexport const trampolineAsync = (fn: TrlAsyncFn) => {\n const cont = (...args: [...Parameters<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\nexport const getMSB = (value: number): number => {\n if (value <= 0) {\n return 0;\n }\n return 1 << (31 - Math.clz32(value));\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} from '../../types';\n\nexport class Heap<E = any> {\n constructor(options: {comparator: Comparator<E>; nodes?: E[]}) {\n this._comparator = options.comparator;\n if (options.nodes && options.nodes.length > 0) {\n this._nodes = options.nodes;\n this.fix();\n }\n }\n\n protected _nodes: E[] = [];\n\n get nodes(): E[] {\n return this._nodes;\n }\n\n protected _comparator: Comparator<E>;\n\n get comparator(): Comparator<E> {\n return this._comparator;\n }\n\n /**\n * Get the size (number of elements) of the heap.\n */\n get size(): number {\n return this.nodes.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.nodes[this.size - 1] ?? undefined;\n }\n\n /**\n * Static method that creates a binary heap from an array of nodes and a comparison function.\n * @returns A new Heap instance.\n * @param options\n */\n static heapify<E>(options: {nodes: E[]; comparator: Comparator<E>}): Heap<E> {\n return new Heap<E>(options);\n }\n\n /**\n * Insert an element into the heap and maintain the heap properties.\n * @param element - The element to be inserted.\n */\n add(element: E): Heap<E> {\n return this.push(element);\n }\n\n /**\n * Insert an element into the heap and maintain the heap properties.\n * @param element - The element to be inserted.\n */\n push(element: E): Heap<E> {\n this.nodes.push(element);\n this.bubbleUp(this.nodes.length - 1);\n return this;\n }\n\n /**\n * Remove and return the top element (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.nodes.length === 0) {\n return undefined;\n }\n if (this.nodes.length === 1) {\n return this.nodes.pop() as E;\n }\n\n const topValue = this.nodes[0];\n this.nodes[0] = this.nodes.pop() as E;\n this.sinkDown(0);\n return topValue;\n }\n\n /**\n * Remove and return the top element (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 return this.poll();\n }\n\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 if (this.nodes.length === 0) {\n return undefined;\n }\n return this.nodes[0];\n }\n\n /**\n * Check if the heap is empty.\n * @returns True if the heap is empty, otherwise false.\n */\n isEmpty() {\n return this.size === 0;\n }\n\n /**\n * Reset the nodes of the heap. Make the nodes empty.\n */\n clear() {\n this._nodes = [];\n }\n\n /**\n * Clear and add nodes of the heap\n * @param nodes\n */\n refill(nodes: E[]) {\n this._nodes = nodes;\n this.fix();\n }\n\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 has(element: E): boolean {\n return this.nodes.includes(element);\n }\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): E[] {\n const result: E[] = [];\n\n // Auxiliary recursive function, traverses the binary heap according to the traversal order\n const dfsHelper = (index: number) => {\n if (index < this.size) {\n if (order === 'in') {\n dfsHelper(2 * index + 1);\n result.push(this.nodes[index]);\n dfsHelper(2 * index + 2);\n } else if (order === 'pre') {\n result.push(this.nodes[index]);\n dfsHelper(2 * index + 1);\n dfsHelper(2 * index + 2);\n } else if (order === 'post') {\n dfsHelper(2 * index + 1);\n dfsHelper(2 * index + 2);\n result.push(this.nodes[index]);\n }\n }\n };\n\n dfsHelper(0); // Traverse starting from the root node\n\n return result;\n }\n\n /**\n * Convert the heap to an array.\n * @returns An array containing the elements of the heap.\n */\n toArray(): E[] {\n return [...this.nodes];\n }\n\n getNodes(): E[] {\n return this.nodes;\n }\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> {\n const clonedHeap = new Heap<E>({comparator: this.comparator});\n clonedHeap._nodes = [...this.nodes];\n return clonedHeap;\n }\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 = this.clone();\n while (cloned.size !== 0) {\n const top = cloned.poll();\n if (top) visitedNode.push(top);\n }\n return visitedNode;\n }\n\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): void {\n const element = this.nodes[index];\n while (index > 0) {\n const parentIndex = Math.floor((index - 1) / 2);\n const parent = this.nodes[parentIndex];\n if (this.comparator(element, parent) < 0) {\n this.nodes[index] = parent;\n this.nodes[parentIndex] = element;\n index = parentIndex;\n } else {\n break;\n }\n }\n }\n\n /**\n * Sinking operation to maintain heap properties after removing the top element.\n * @param index - The index from which to start sinking.\n */\n protected sinkDown(index: number): void {\n const leftChildIndex = 2 * index + 1;\n const rightChildIndex = 2 * index + 2;\n const length = this.nodes.length;\n let targetIndex = index;\n\n if (leftChildIndex < length && this.comparator(this.nodes[leftChildIndex], this.nodes[targetIndex]) < 0) {\n targetIndex = leftChildIndex;\n }\n if (rightChildIndex < length && this.comparator(this.nodes[rightChildIndex], this.nodes[targetIndex]) < 0) {\n targetIndex = rightChildIndex;\n }\n\n if (targetIndex !== index) {\n const temp = this.nodes[index];\n this.nodes[index] = this.nodes[targetIndex];\n this.nodes[targetIndex] = temp;\n this.sinkDown(targetIndex);\n }\n }\n\n /**\n * Fix the entire heap to maintain heap properties.\n */\n protected fix() {\n for (let i = Math.floor(this.size / 2); i >= 0; i--) this.sinkDown(i);\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 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 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 get root(): FibonacciHeapNode<E> | undefined {\n return this._root;\n }\n\n protected _size = 0;\n\n get size(): number {\n return this._size;\n }\n\n protected _min?: FibonacciHeapNode<E>;\n\n get min(): FibonacciHeapNode<E> | undefined {\n return this._min;\n }\n\n protected _comparator: Comparator<E>;\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 * O(1) time operation.\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 * O(1) time operation.\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 * O(1) time operation.\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 * O(1) time operation.\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 nodes of the linked list.\n */\n consumeLinkedList(head?: FibonacciHeapNode<E>): FibonacciHeapNode<E>[] {\n const nodes: FibonacciHeapNode<E>[] = [];\n if (!head) return nodes;\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 nodes.push(node);\n node = node.right;\n }\n }\n\n return nodes;\n }\n\n /**\n * O(log n) time operation.\n * Remove and return the top element (smallest or largest element) from the heap.\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 * O(log n) time operation.\n * Remove and return the top element (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 * O(log n) time operation.\n * Remove and return the top element (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 nodes = this.consumeLinkedList(z.child);\n for (const node of nodes) {\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 * O(log n) time operation.\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 * 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 * Create a new node.\n * @param element\n * @protected\n */\n protected createNode(element: E): FibonacciHeapNode<E> {\n return new FibonacciHeapNode<E>(element);\n }\n\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 * O(log n) time operation.\n * Remove and return the top element (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 * O(log n) time operation.\n * Remove and return the top element (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 * O(log n) time operation.\n * Remove and return the top element (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 nodes = 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 nodes) {\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 */\n\nimport {Heap} from './heap';\nimport type {Comparator} from '../../types';\n\nexport class MaxHeap<E = any> extends Heap<E> {\n constructor(\n options: {comparator: Comparator<E>; nodes?: E[]} = {\n comparator: (a: E, b: E) => {\n if (!(typeof a === 'number' && typeof b === 'number')) {\n throw new Error('The a, b params of compare function must be number');\n } else {\n return b - a;\n }\n }\n }\n ) {\n super(options);\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 */\n\nimport {Heap} from './heap';\nimport type {Comparator} from '../../types';\n\nexport class MinHeap<E = any> extends Heap<E> {\n constructor(\n options: {comparator: Comparator<E>; nodes?: E[]} = {\n comparator: (a: E, b: E) => {\n if (!(typeof a === 'number' && typeof b === 'number')) {\n throw new Error('The a, b params of compare function must be number');\n } else {\n return a - b;\n }\n }\n }\n ) {\n super(options);\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 */\n\nimport {Heap} from '../heap';\nimport {Comparator} from '../../types';\n\nexport class PriorityQueue<E = any> extends Heap<E> {\n constructor(options: {comparator: Comparator<E>; nodes?: E[]}) {\n super(options);\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 {PriorityQueue} from './priority-queue';\nimport type {Comparator} from '../../types';\n\nexport class MinPriorityQueue<E = any> extends PriorityQueue<E> {\n constructor(\n options: {comparator: Comparator<E>; nodes?: E[]} = {\n comparator: (a: E, b: E) => {\n if (!(typeof a === 'number' && typeof b === 'number')) {\n throw new Error('The a, b params of compare function must be number');\n } else {\n return a - b;\n }\n }\n }\n ) {\n super(options);\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 {PriorityQueue} from './priority-queue';\nimport type {Comparator} from '../../types';\n\nexport class MaxPriorityQueue<E = any> extends PriorityQueue<E> {\n constructor(\n options: {comparator: Comparator<E>; nodes?: E[]} = {\n comparator: (a: E, b: E) => {\n if (!(typeof a === 'number' && typeof b === 'number')) {\n throw new Error('The a, b params of compare function must be number');\n } else {\n return b - a;\n }\n }\n }\n ) {\n super(options);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport {uuidV4} from '../../utils';\nimport {PriorityQueue} from '../priority-queue';\nimport type {DijkstraResult, VertexKey} from '../../types';\nimport {IGraph} from '../../interfaces';\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> implements IGraph<V, E, VO, EO>\n{\n protected _vertices: Map<VertexKey, VO> = new Map<VertexKey, VO>();\n\n get vertices(): Map<VertexKey, VO> {\n return this._vertices;\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 | null;\n\n abstract getEdge(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | null;\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] | null;\n\n /**\n * The function \"getVertex\" returns the vertex with the specified ID or null 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 `_vertices` map.\n * @returns The method `getVertex` returns the vertex with the specified `vertexKey` if it exists in the `_vertices`\n * map. If the vertex does not exist, it returns `null`.\n */\n getVertex(vertexKey: VertexKey): VO | null {\n return this._vertices.get(vertexKey) || null;\n }\n\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._vertices.has(this._getVertexKey(vertexOrKey));\n }\n\n addVertex(vertex: VO): boolean;\n\n addVertex(key: VertexKey, value?: V): boolean;\n\n addVertex(keyOrVertex: VertexKey | VO, value?: V): boolean {\n if (keyOrVertex instanceof AbstractVertex) {\n return this._addVertexOnly(keyOrVertex);\n } else {\n const newVertex = this.createVertex(keyOrVertex, value);\n return this._addVertexOnly(newVertex);\n }\n }\n\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 const vertexKey = this._getVertexKey(vertexOrKey);\n return this._vertices.delete(vertexKey);\n }\n\n /**\n * The function removes all vertices from a graph and returns a boolean indicating if any vertices were removed.\n * @param {VO[] | VertexKey[]} vertices - The `vertices` parameter can be either an array of vertices (`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 vertices\n * were removed.\n */\n removeManyVertices(vertices: VO[] | VertexKey[]): boolean {\n const removed: boolean[] = [];\n for (const v of vertices) {\n removed.push(this.deleteVertex(v));\n }\n return removed.length > 0;\n }\n\n /**\n * The function checks if there is an edge between two vertices 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 addEdge(srcOrEdge: VO | VertexKey | EO, dest?: VO | VertexKey, weight?: number, value?: E): boolean {\n if (srcOrEdge instanceof AbstractEdge) {\n return this._addEdgeOnly(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._addEdgeOnly(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 * The function sets the weight of an edge between two vertices 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 vertices, 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 * The function `getAllPathsBetween` finds all paths between two vertices 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 vertices (`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 * The function calculates the sum of weights along a given path.\n * @param {VO[]} path - An array of vertices (VO) representing a path in a graph.\n * @returns The function `getPathSumWeight` returns the sum of the weights of the edges 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 * The function `getMinCostBetween` calculates the minimum cost between two vertices 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 edges 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 edges. 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 vertices (`v1`\n * and `v2`). If the `isWeight` parameter is `true`, it calculates the minimum weight among all paths between the\n * vertices. 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 | null {\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 null;\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.size > 0) {\n for (let i = 0; i < queue.size; 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 null;\n }\n }\n\n /**\n * The function `getMinPathBetween` returns the minimum path between two vertices 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 edges 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 vertices (`VO[]`) representing the minimum path between\n * two vertices (`v1` and `v2`). If there is no path between the vertices, it returns `null`.\n */\n getMinPathBetween(v1: VO | VertexKey, v2: VO | VertexKey, isWeight?: boolean, isDFS = false): VO[] | null {\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] || null;\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 * Dijkstra algorithm time: O(VE) space: O(VO + EO)\n * /\n\n /**\n * Dijkstra algorithm time: O(VE) space: O(VO + EO)\n * The function `dijkstraWithoutHeap` implements Dijkstra's algorithm to find the shortest path between two vertices 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 | null} [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 `null`.\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 vertices 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 | null,\n getMinDist?: boolean,\n genPaths?: boolean\n ): DijkstraResult<VO> {\n if (getMinDist === undefined) getMinDist = false;\n if (genPaths === undefined) genPaths = false;\n\n if (dest === undefined) dest = null;\n let minDist = Infinity;\n let minDest: VO | null = null;\n let minPath: VO[] = [];\n const paths: VO[][] = [];\n\n const vertices = this._vertices;\n const distMap: Map<VO, number> = new Map();\n const seen: Set<VO> = new Set();\n const preMap: Map<VO, VO | null> = new Map(); // predecessor\n const srcVertex = this._getVertex(src);\n\n const destVertex = dest ? this._getVertex(dest) : null;\n\n if (!srcVertex) {\n return null;\n }\n\n for (const vertex of vertices) {\n const vertexOrKey = vertex[1];\n if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Infinity);\n }\n distMap.set(srcVertex, 0);\n preMap.set(srcVertex, null);\n\n const getMinOfNoSeen = () => {\n let min = Infinity;\n let minV: VO | null = null;\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 | null) => {\n for (const vertex of vertices) {\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 < vertices.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-null-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 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 genPaths && getPaths(minDest);\n\n return {distMap, preMap, seen, paths, minDist, minPath};\n }\n\n /**\n * Dijkstra algorithm time: O(logVE) space: O(VO + EO)\n *\n * Dijkstra's algorithm only solves the single-source shortest path problem, while the Bellman-Ford algorithm and Floyd-Warshall algorithm can address shortest paths between all pairs of nodes.\n * Dijkstra's algorithm is suitable for graphs with non-negative edge weights, whereas the Bellman-Ford algorithm and Floyd-Warshall algorithm can handle negative-weight edges.\n * The time complexity of Dijkstra's algorithm and the Bellman-Ford algorithm depends on the size of the graph, while the time complexity of the Floyd-Warshall algorithm is O(VO^3), where VO is the number of nodes. For dense graphs, Floyd-Warshall might become slower.\n *\n * /\n\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 | null} [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 vertices 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 vertices 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 | null,\n getMinDist?: boolean,\n genPaths?: boolean\n ): DijkstraResult<VO> {\n if (getMinDist === undefined) getMinDist = false;\n if (genPaths === undefined) genPaths = false;\n\n if (dest === undefined) dest = null;\n let minDist = Infinity;\n let minDest: VO | null = null;\n let minPath: VO[] = [];\n const paths: VO[][] = [];\n const vertices = this._vertices;\n const distMap: Map<VO, number> = new Map();\n const seen: Set<VO> = new Set();\n const preMap: Map<VO, VO | null> = new Map(); // predecessor\n\n const srcVertex = this._getVertex(src);\n const destVertex = dest ? this._getVertex(dest) : null;\n\n if (!srcVertex) return null;\n\n for (const vertex of vertices) {\n const vertexOrKey = vertex[1];\n if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Infinity);\n }\n\n const heap = new PriorityQueue<{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, null);\n\n /**\n * The function `getPaths` retrieves all paths from vertices to a specified minimum vertex.\n * @param {VO | null} minV - The parameter `minV` is of type `VO | null`. It represents the minimum vertex value or\n * null.\n */\n const getPaths = (minV: VO | null) => {\n for (const vertex of vertices) {\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 * BellmanFord time:O(VE) space:O(VO)\n * one to rest pairs\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 edges for several rounds to gradually approximate the shortest paths. Due to its ability to handle negative-weight edges, 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 vertices 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 vertices 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 vertices 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 vertices = this._vertices;\n const numOfVertices = vertices.size;\n const edges = this.edgeSet();\n const numOfEdges = edges.length;\n\n this._vertices.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(edges[j]);\n if (ends) {\n const [s, d] = ends;\n const weight = edges[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 genPath && preMap.set(d, s);\n }\n }\n }\n }\n }\n\n let minDest: VO | null = null;\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 vertices) {\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(edges[j]);\n if (ends) {\n const [s] = ends;\n const weight = edges[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 edges for several rounds to gradually approximate the shortest paths. Due to its ability to handle negative-weight edges, 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 * Floyd algorithm time: O(VO^3) space: O(VO^2), 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 edges, and it can simultaneously compute shortest paths between any two nodes.\n * /\n\n /**\n * Floyd algorithm time: O(VO^3) space: O(VO^2), 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 edges, 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 vertices 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 vertices in a graph. The\n * `predecessor` property is a 2D array of vertices (or `null`) representing the predecessor vertices in the shortest\n * path between vertices in the\n */\n floydWarshall(): {costs: number[][]; predecessor: (VO | null)[][]} {\n const idAndVertices = [...this._vertices];\n const n = idAndVertices.length;\n\n const costs: number[][] = [];\n const predecessor: (VO | null)[][] = [];\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] = null;\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 * Tarjan is an algorithm based on dfs,which is used to solve the connectivity problem of graphs.\n * Tarjan can find cycles in directed or undirected graph\n * Tarjan can find the articulation points and bridges(critical edges) of undirected graphs in linear time,\n * Tarjan solve the bi-connected components of undirected graphs;\n * Tarjan can find the SSC(strongly connected components), articulation points, and bridges of directed graphs.\n * /\n\n /**\n * Tarjan is an algorithm based on dfs,which is used to solve the connectivity problem of graphs.\n * Tarjan can find cycles in directed or undirected graph\n * Tarjan can find the articulation points and bridges(critical edges) of undirected graphs in linear time,\n * Tarjan solve the bi-connected components of undirected graphs;\n * Tarjan can find the SSC(strongly connected components), articulation points, and bridges of directed graphs.\n * The `tarjan` function is used to perform various graph analysis tasks such as finding articulation points, bridges,\n * strongly connected components (SCCs), and cycles in a graph.\n * @param {boolean} [needCutVertexes] - A boolean value indicating whether or not to calculate and return the\n * articulation points in the graph. Articulation points are the vertices in a graph whose removal would increase the\n * number of connected components in the graph.\n * @param {boolean} [needBridges] - A boolean flag indicating whether the algorithm should find and return the bridges\n * (edges whose removal would increase the number of connected components in the graph).\n * @param {boolean} [needSCCs] - A boolean value indicating whether the Strongly Connected Components (SCCs) of the\n * graph are needed. If set to true, the function will calculate and return the SCCs of the graph. If set to false, the\n * SCCs will not be calculated or returned.\n * @param {boolean} [needCycles] - A boolean flag indicating whether the algorithm should find cycles in the graph. If\n * set to true, the algorithm will return a map of cycles, where the keys are the low values of the SCCs and the values\n * are arrays of vertices that form cycles within the SCCs.\n * @returns The function `tarjan` returns an object with the following properties:\n */\n tarjan(\n needCutVertexes: boolean = false,\n needBridges: boolean = false,\n needSCCs: boolean = true,\n needCycles: boolean = false\n ) {\n // !! in undirected graph we will not let child visit parent when dfs\n // !! articulation point(in dfs search tree not in graph): (cur !== root && cur.has(child)) && (low(child) >= dfn(cur)) || (cur === root && cur.children() >= 2)\n // !! bridge: low(child) > dfn(cur)\n\n const defaultConfig = false;\n if (needCutVertexes === undefined) needCutVertexes = defaultConfig;\n if (needBridges === undefined) needBridges = defaultConfig;\n if (needSCCs === undefined) needSCCs = defaultConfig;\n if (needCycles === undefined) needCycles = defaultConfig;\n\n const dfnMap: Map<VO, number> = new Map();\n const lowMap: Map<VO, number> = new Map();\n const vertices = this._vertices;\n vertices.forEach(v => {\n dfnMap.set(v, -1);\n lowMap.set(v, Infinity);\n });\n\n const [root] = vertices.values();\n\n const cutVertexes: VO[] = [];\n const bridges: EO[] = [];\n let dfn = 0;\n const dfs = (cur: VO, parent: VO | null) => {\n dfn++;\n dfnMap.set(cur, dfn);\n lowMap.set(cur, dfn);\n\n const neighbors = this.getNeighbors(cur);\n let childCount = 0; // child in dfs tree not child in graph\n for (const neighbor of neighbors) {\n if (neighbor !== parent) {\n if (dfnMap.get(neighbor) === -1) {\n childCount++;\n dfs(neighbor, cur);\n }\n const childLow = lowMap.get(neighbor);\n const curLow = lowMap.get(cur);\n // TODO after no-non-null-assertion not ensure the logic\n if (curLow !== undefined && childLow !== undefined) {\n lowMap.set(cur, Math.min(curLow, childLow));\n }\n const curFromMap = dfnMap.get(cur);\n if (childLow !== undefined && curFromMap !== undefined) {\n if (needCutVertexes) {\n if ((cur === root && childCount >= 2) || (cur !== root && childLow >= curFromMap)) {\n // todo not ensure the logic if (cur === root && childCount >= 2 || ((cur !== root) && (childLow >= curFromMap))) {\n cutVertexes.push(cur);\n }\n }\n\n if (needBridges) {\n if (childLow > curFromMap) {\n const edgeCurToNeighbor = this.getEdge(cur, neighbor);\n if (edgeCurToNeighbor) {\n bridges.push(edgeCurToNeighbor);\n }\n }\n }\n }\n }\n }\n };\n\n dfs(root, null);\n\n let SCCs: Map<number, VO[]> = new Map();\n\n const getSCCs = () => {\n const SCCs: Map<number, VO[]> = new Map();\n lowMap.forEach((low, vertex) => {\n if (!SCCs.has(low)) {\n SCCs.set(low, [vertex]);\n } else {\n SCCs.get(low)?.push(vertex);\n }\n });\n return SCCs;\n };\n\n if (needSCCs) {\n SCCs = getSCCs();\n }\n\n const cycles: Map<number, VO[]> = new Map();\n if (needCycles) {\n let SCCs: Map<number, VO[]> = new Map();\n if (SCCs.size < 1) {\n SCCs = getSCCs();\n }\n\n SCCs.forEach((SCC, low) => {\n if (SCC.length > 1) {\n cycles.set(low, SCC);\n }\n });\n }\n\n return {dfnMap, lowMap, bridges, cutVertexes, SCCs, cycles};\n }\n\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(false, false, false, false).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(false, false, false, false).lowMap;\n }\n\n /**\n * The function `getCycles` returns a map of cycles found using the Tarjan algorithm.\n * @returns The function `getCycles()` is returning a `Map<number, VO[]>`.\n */\n getCycles(): Map<number, VO[]> {\n return this.tarjan(false, false, false, true).cycles;\n }\n\n /**\n * The function \"getCutVertexes\" returns an array of cut vertexes using the Tarjan algorithm.\n * @returns an array of VO objects, specifically the cut vertexes.\n */\n getCutVertexes(): VO[] {\n return this.tarjan(true, false, false, false).cutVertexes;\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(false, false, true, false).SCCs;\n }\n\n /**\n * The function \"getBridges\" returns an array of bridges using the Tarjan algorithm.\n * @returns the bridges found using the Tarjan algorithm.\n */\n getBridges() {\n return this.tarjan(false, true, false, false).bridges;\n }\n\n protected abstract _addEdgeOnly(edge: EO): boolean;\n\n protected _addVertexOnly(newVertex: VO): boolean {\n if (this.hasVertex(newVertex)) {\n return false;\n // throw (new Error('Duplicated vertex key is not allowed'));\n }\n this._vertices.set(newVertex.key, newVertex);\n return true;\n }\n\n protected _getVertex(vertexOrKey: VertexKey | VO): VO | null {\n const vertexKey = this._getVertexKey(vertexOrKey);\n return this._vertices.get(vertexKey) || null;\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 Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport {arrayRemove} from '../../utils';\nimport {AbstractEdge, AbstractGraph, AbstractVertex} from './abstract-graph';\nimport type {TopologicalStatus, VertexKey} from '../../types';\nimport {IGraph} from '../../interfaces';\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 vertices 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\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 protected _inEdgeMap: Map<VO, EO[]> = new Map<VO, EO[]>();\n\n get inEdgeMap(): Map<VO, EO[]> {\n return this._inEdgeMap;\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 /**\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 vertices.\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 ?? key) as VO;\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 /**\n * The function creates a directed edge between two vertices 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 * The `getEdge` function retrieves an edge between two vertices based on their source and destination IDs.\n * @param {VO | VertexKey | null} srcOrKey - The source vertex or its ID. It can be either a vertex object or a vertex ID.\n * @param {VO | VertexKey | null} 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 `null` if the\n * destination is not specified.\n * @returns the first edge found between the source and destination vertices, or null if no such edge is found.\n */\n getEdge(srcOrKey: VO | VertexKey | null, destOrKey: VO | VertexKey | null): EO | null {\n let edges: EO[] = [];\n\n if (srcOrKey !== null && destOrKey !== null) {\n const src: VO | null = this._getVertex(srcOrKey);\n const dest: VO | null = this._getVertex(destOrKey);\n\n if (src && dest) {\n const srcOutEdges = this._outEdgeMap.get(src);\n if (srcOutEdges) {\n edges = srcOutEdges.filter(edge => edge.dest === dest.key);\n }\n }\n }\n\n return edges[0] || null;\n }\n\n /**\n * The function removes an edge between two vertices 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 null if either the source or destination vertex does not exist.\n */\n deleteEdgeSrcToDest(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | null {\n const src: VO | null = this._getVertex(srcOrKey);\n const dest: VO | null = this._getVertex(destOrKey);\n let removed: EO | null = null;\n if (!src || !dest) {\n return null;\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] || null;\n }\n return removed;\n }\n\n /**\n * The function removes an edge from a graph and returns the removed edge, or null if the edge was not found.\n * @param {EO} edge - The `edge` parameter is an object that represents an edge in a graph. It has two properties: `src`\n * and `dest`, which represent the source and destination vertices of the edge, respectively.\n * @returns The method `deleteEdge` returns the removed edge (`EO`) if it exists, or `null` if the edge does not exist.\n */\n deleteEdge(edge: EO): EO | null {\n let removed: EO | null = null;\n const src = this._getVertex(edge.src);\n const dest = this._getVertex(edge.dest);\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);\n }\n\n const destInEdges = this._inEdgeMap.get(dest);\n if (destInEdges && destInEdges.length > 0) {\n removed = arrayRemove(destInEdges, (edge: EO) => edge.dest === dest.key)[0];\n }\n }\n\n return removed;\n }\n\n /**\n * The function removes edges between two vertices and returns the removed edges.\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 edges (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 v1ToV2 && removed.push(v1ToV2);\n v2ToV1 && removed.push(v2ToV1);\n }\n\n return removed;\n }\n\n /**\n * The function `incomingEdgesOf` returns an array of incoming edges 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 edges (`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 * The function `outgoingEdgesOf` returns an array of outgoing edges 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 edges (`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 * 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 * The function \"inDegreeOf\" returns the number of incoming edges 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 edges of the specified vertex or vertex ID.\n */\n inDegreeOf(vertexOrKey: VertexKey | VO): number {\n return this.incomingEdgesOf(vertexOrKey).length;\n }\n\n /**\n * The function `outDegreeOf` returns the number of outgoing edges 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 edges from the specified vertex or vertex ID.\n */\n outDegreeOf(vertexOrKey: VertexKey | VO): number {\n return this.outgoingEdgesOf(vertexOrKey).length;\n }\n\n /**\n * The function \"edgesOf\" returns an array of both outgoing and incoming edges 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 edges.\n */\n edgesOf(vertexOrKey: VertexKey | VO): EO[] {\n return [...this.outgoingEdgesOf(vertexOrKey), ...this.incomingEdgesOf(vertexOrKey)];\n }\n\n /**\n * The function \"getEdgeSrc\" returns the source vertex of an edge, or null 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 null.\n */\n getEdgeSrc(e: EO): VO | null {\n return this._getVertex(e.src);\n }\n\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 null.\n */\n getEdgeDest(e: EO): VO | null {\n return this._getVertex(e.dest);\n }\n\n /**\n * The function `getDestinations` returns an array of destination vertices connected to a given vertex.\n * @param {VO | VertexKey | null} 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 `null`.\n * @returns an array of vertices (VO[]).\n */\n getDestinations(vertex: VO | VertexKey | null): VO[] {\n if (vertex === null) {\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 * The `topologicalSort` function performs a topological sort on a graph and returns an array of vertices or vertex IDs\n * in the sorted order, or null 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 vertices. It can have two possible values: 'vertex' or 'key'. If 'vertex' is\n * specified, the vertices themselves will be used for sorting. If 'key' is specified, the ids of\n * @returns an array of vertices or vertex IDs in topological order. If there is a cycle in the graph, it returns null.\n */\n topologicalSort(propertyName?: 'vertex' | 'key'): Array<VO | VertexKey> | null {\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.vertices) {\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.vertices) {\n if (statusMap.get(entry[1]) === 0) {\n dfs(entry[1]);\n }\n }\n\n if (hasCycle) return null;\n\n if (propertyName === 'key') sorted = sorted.map(vertex => (vertex instanceof DirectedVertex ? vertex.key : vertex));\n return sorted.reverse();\n }\n\n /**\n * The `edgeSet` function returns an array of all the edges in the graph.\n * @returns The `edgeSet()` method returns an array of edges (`EO[]`).\n */\n edgeSet(): EO[] {\n let edges: EO[] = [];\n this._outEdgeMap.forEach(outEdges => {\n edges = [...edges, ...outEdges];\n });\n return edges;\n }\n\n /**\n * The function `getNeighbors` returns an array of neighboring vertices 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 vertices (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-null-assertion not ensure the logic\n if (neighbor) {\n neighbors.push(neighbor);\n }\n }\n }\n return neighbors;\n }\n\n /**\n * The function \"getEndsOfEdge\" returns the source and destination vertices of an edge if it exists in the graph,\n * otherwise it returns null.\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 vertices `[VO, VO]` if the edge exists in the\n * graph. If the edge does not exist, it returns `null`.\n */\n getEndsOfEdge(edge: EO): [VO, VO] | null {\n if (!this.hasEdge(edge.src, edge.dest)) {\n return null;\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 null;\n }\n }\n\n /**\n * The function `_addEdgeOnly` adds an edge to a graph if the source and destination vertices 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 _addEdgeOnly(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-null-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 Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport {arrayRemove} from '../../utils';\nimport {AbstractEdge, AbstractGraph, AbstractVertex} from './abstract-graph';\nimport type {VertexKey} from '../../types';\nimport {IGraph} from '../../interfaces';\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 vertices: [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.vertices = [v1, v2];\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 edges.\n */\n constructor() {\n super();\n this._edges = new Map<VO, EO[]>();\n }\n\n protected _edges: Map<VO, EO[]>;\n\n get edges(): Map<VO, EO[]> {\n return this._edges;\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 vertices 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 * The function `getEdge` returns the first edge that connects two vertices, or null if no such edge exists.\n * @param {VO | VertexKey | null} v1 - The parameter `v1` represents a vertex or vertex ID. It can be of type `VO` (vertex\n * object), `null`, or `VertexKey` (a string or number representing the ID of a vertex).\n * @param {VO | VertexKey | null} v2 - The parameter `v2` represents a vertex or vertex ID. It can be of type `VO` (vertex\n * object), `null`, or `VertexKey` (vertex ID).\n * @returns an edge (EO) or null.\n */\n getEdge(v1: VO | VertexKey | null, v2: VO | VertexKey | null): EO | null {\n let edges: EO[] | undefined = [];\n\n if (v1 !== null && v2 !== null) {\n const vertex1: VO | null = this._getVertex(v1);\n const vertex2: VO | null = this._getVertex(v2);\n\n if (vertex1 && vertex2) {\n edges = this._edges.get(vertex1)?.filter(e => e.vertices.includes(vertex2.key));\n }\n }\n\n return edges ? edges[0] || null : null;\n }\n\n /**\n * The function removes an edge between two vertices 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 null if either of the vertices (VO) does not exist.\n */\n deleteEdgeBetween(v1: VO | VertexKey, v2: VO | VertexKey): EO | null {\n const vertex1: VO | null = this._getVertex(v1);\n const vertex2: VO | null = this._getVertex(v2);\n\n if (!vertex1 || !vertex2) {\n return null;\n }\n\n const v1Edges = this._edges.get(vertex1);\n let removed: EO | null = null;\n if (v1Edges) {\n removed = arrayRemove<EO>(v1Edges, (e: EO) => e.vertices.includes(vertex2.key))[0] || null;\n }\n const v2Edges = this._edges.get(vertex2);\n if (v2Edges) {\n arrayRemove<EO>(v2Edges, (e: EO) => e.vertices.includes(vertex1.key));\n }\n return removed;\n }\n\n /**\n * The deleteEdge function removes an edge between two vertices in a graph.\n * @param {EO} edge - The parameter \"edge\" is of type EO, which represents an edge in a graph.\n * @returns The method is returning either the removed edge (of type EO) or null if the edge was not found.\n */\n deleteEdge(edge: EO): EO | null {\n return this.deleteEdgeBetween(edge.vertices[0], edge.vertices[1]);\n }\n\n /**\n * The function `degreeOf` returns the degree of a vertex in a graph, which is the number of edges 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 * edges connected to that vertex.\n */\n degreeOf(vertexOrKey: VertexKey | VO): number {\n const vertex = this._getVertex(vertexOrKey);\n if (vertex) {\n return this._edges.get(vertex)?.length || 0;\n } else {\n return 0;\n }\n }\n\n /**\n * The function returns the edges 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 edges.\n */\n edgesOf(vertexOrKey: VertexKey | VO): EO[] {\n const vertex = this._getVertex(vertexOrKey);\n if (vertex) {\n return this._edges.get(vertex) || [];\n } else {\n return [];\n }\n }\n\n /**\n * The function \"edgeSet\" returns an array of unique edges from a set of edges.\n * @returns The method `edgeSet()` returns an array of type `EO[]`.\n */\n edgeSet(): EO[] {\n const edgeSet: Set<EO> = new Set();\n this._edges.forEach(edges => {\n edges.forEach(edge => {\n edgeSet.add(edge);\n });\n });\n return [...edgeSet];\n }\n\n /**\n * The function \"getNeighbors\" returns an array of neighboring vertices 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 vertices (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.vertices.filter(e => e !== vertex.key)[0]);\n if (neighbor) {\n neighbors.push(neighbor);\n }\n }\n }\n return neighbors;\n }\n\n /**\n * The function \"getEndsOfEdge\" returns the vertices at the ends of an edge if the edge exists in the graph, otherwise\n * it returns null.\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 vertices `[VO, VO]` if the edge exists in the\n * graph. If the edge does not exist, it returns `null`.\n */\n getEndsOfEdge(edge: EO): [VO, VO] | null {\n if (!this.hasEdge(edge.vertices[0], edge.vertices[1])) {\n return null;\n }\n const v1 = this._getVertex(edge.vertices[0]);\n const v2 = this._getVertex(edge.vertices[1]);\n if (v1 && v2) {\n return [v1, v2];\n } else {\n return null;\n }\n }\n\n /**\n * The function adds an edge to the graph by updating the adjacency list with the vertices 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 _addEdgeOnly(edge: EO): boolean {\n for (const end of edge.vertices) {\n const endVertex = this._getVertex(end);\n if (endVertex === null) return false;\n if (endVertex) {\n const edges = this._edges.get(endVertex);\n if (edges) {\n edges.push(edge);\n } else {\n this._edges.set(endVertex, [edge]);\n }\n }\n }\n return true;\n }\n}\n","import {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\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 origin and bottomRight properties of a MapGraphCoordinate object.\n * @param {MapGraphCoordinate} origin - The `origin` 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(origin: MapGraphCoordinate, bottomRight?: MapGraphCoordinate) {\n super();\n this._origin = origin;\n this._bottomRight = bottomRight;\n }\n\n protected _origin: MapGraphCoordinate = [0, 0];\n\n get origin(): MapGraphCoordinate {\n return this._origin;\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(key: VertexKey, value?: V, lat: number = this.origin[0], long: number = this.origin[1]): 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","import {BinaryTreeNode} from '../../../data-structures';\n\n/**\n * Enum representing different loop types.\n *\n * - `iterative`: Indicates the iterative loop type (with loops that use iterations).\n * - `recursive`: Indicates the recursive loop type (with loops that call themselves).\n */\n\nexport enum IterationType {\n ITERATIVE = 'ITERATIVE',\n RECURSIVE = 'RECURSIVE'\n}\n\nexport enum FamilyPosition {\n ROOT = 'ROOT',\n LEFT = 'LEFT',\n RIGHT = 'RIGHT',\n ROOT_LEFT = 'ROOT_LEFT',\n ROOT_RIGHT = 'ROOT_RIGHT',\n ISOLATED = 'ISOLATED',\n MAL_NODE = 'MAL_NODE'\n}\n\nexport type BTNKey = number;\n\nexport type BinaryTreeDeletedResult<N> = { deleted: N | null | undefined; needBalanced: N | null | undefined };\n\nexport type BinaryTreeNodeNested<T> = BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\nexport type BinaryTreeOptions = { iterationType?: IterationType }\n","import {RBTreeNode} from '../../../data-structures';\nimport {BSTOptions} from \"./bst\";\n\nexport enum RBTNColor { RED = 1, BLACK = 0}\n\nexport type RBTreeNodeNested<T> = RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, RBTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\nexport type RBTreeOptions = BSTOptions & {};","// 0 means unknown, 1 means visiting, 2 means visited;\nexport type TopologicalStatus = 0 | 1 | 2;\n\nexport enum TopologicalProperty {\n VAL = 'VAL',\n NODE = 'NODE',\n ID = 'ID'\n}\n","export type Comparator<T> = (a: T, b: T) => number;\n\nexport type DFSOrderPattern = 'pre' | 'in' | 'post';\n\nexport type BTNCallback<N, D = any> = (node: N) => D;\n\nexport enum CP {\n lt = 'lt',\n eq = 'eq',\n gt = 'gt'\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n\nimport type {BinaryTreeNodeNested, BinaryTreeOptions, BTNCallback, BTNKey} from '../../types';\nimport {BinaryTreeDeletedResult, DFSOrderPattern, FamilyPosition, IterationType} from '../../types';\nimport {IBinaryTree} from '../../interfaces';\nimport {trampoline} from '../../utils';\nimport {Queue} from '../queue';\n\n/**\n * Represents a node in a binary tree.\n * @template V - The type of data stored in the node.\n * @template N - The type of the family relationship in the binary tree.\n */\nexport class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>> {\n /**\n * The key associated with the node.\n */\n key: BTNKey;\n\n /**\n * The value stored in the node.\n */\n value: V | undefined;\n\n /**\n * The parent node of the current node.\n */\n parent: N | null | undefined;\n\n /**\n * Creates a new instance of BinaryTreeNode.\n * @param {BTNKey} key - The key associated with the node.\n * @param {V} value - The value stored in the node.\n */\n constructor(key: BTNKey, value?: V) {\n this.key = key;\n this.value = value;\n }\n\n protected _left: N | null | undefined;\n\n /**\n * Get the left child node.\n */\n get left(): N | null | undefined {\n return this._left;\n }\n\n /**\n * Set the left child node.\n * @param {N | null | undefined} v - The left child node.\n */\n set left(v: N | null | undefined) {\n if (v) {\n v.parent = this as unknown as N;\n }\n this._left = v;\n }\n\n protected _right: N | null | undefined;\n\n /**\n * Get the right child node.\n */\n get right(): N | null | undefined {\n return this._right;\n }\n\n /**\n * Set the right child node.\n * @param {N | null | undefined} v - The right child node.\n */\n set right(v: N | null | undefined) {\n if (v) {\n v.parent = this as unknown as N;\n }\n this._right = v;\n }\n\n /**\n * Get the position of the node within its family.\n * @returns {FamilyPosition} - The family position of the node.\n */\n get familyPosition(): FamilyPosition {\n const that = this as unknown as N;\n if (!this.parent) {\n return this.left || this.right ? FamilyPosition.ROOT : FamilyPosition.ISOLATED;\n }\n\n if (this.parent.left === that) {\n return this.left || this.right ? FamilyPosition.ROOT_LEFT : FamilyPosition.LEFT;\n } else if (this.parent.right === that) {\n return this.left || this.right ? FamilyPosition.ROOT_RIGHT : FamilyPosition.RIGHT;\n }\n\n return FamilyPosition.MAL_NODE;\n }\n}\n\n/**\n * Represents a binary tree data structure.\n * @template N - The type of the binary tree's nodes.\n */\nexport class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>>\n implements IBinaryTree<V, N>\n{\n iterationType: IterationType = IterationType.ITERATIVE;\n\n /**\n * Creates a new instance of BinaryTree.\n * @param {BinaryTreeOptions} [options] - The options for the binary tree.\n */\n constructor(options?: BinaryTreeOptions) {\n if (options !== undefined) {\n const {iterationType = IterationType.ITERATIVE} = options;\n this.iterationType = iterationType;\n }\n }\n\n protected _root: N | null | undefined = undefined;\n\n /**\n * Get the root node of the binary tree.\n */\n get root(): N | null | undefined {\n return this._root;\n }\n\n protected _size = 0;\n\n /**\n * Get the number of nodes in the binary tree.\n */\n get size(): number {\n return this._size;\n }\n\n /**\n * Creates a new instance of BinaryTreeNode with the given key and value.\n * @param {BTNKey} key - The key for the new node.\n * @param {V} value - The value for the new node.\n * @returns {N} - The newly created BinaryTreeNode.\n */\n createNode(key: BTNKey, value?: V): N {\n return new BinaryTreeNode<V, N>(key, value) as N;\n }\n\n /**\n * Clear the binary tree, removing all nodes.\n */\n clear() {\n this._setRoot(undefined);\n this._size = 0;\n }\n\n /**\n * Check if the binary tree is empty.\n * @returns {boolean} - True if the binary tree is empty, false otherwise.\n */\n isEmpty(): boolean {\n return this.size === 0;\n }\n\n /**\n * Add a node with the given key and value to the binary tree.\n * @param {BTNKey | N | null} keyOrNode - The key or node to add to the binary tree.\n * @param {V} value - The value for the new node (optional).\n * @returns {N | null | undefined} - The inserted node, or null if nothing was inserted, or undefined if the operation failed.\n */\n add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | null | undefined {\n const _bfs = (root: N, newNode: N | null): N | undefined | null => {\n const queue = new Queue<N | null>([root]);\n while (queue.size > 0) {\n const cur = queue.shift();\n if (cur) {\n if (newNode && cur.key === newNode.key) {\n cur.value = newNode.value;\n return;\n }\n const inserted = this._addTo(newNode, cur);\n if (inserted !== undefined) return inserted;\n if (cur.left) queue.push(cur.left);\n if (cur.right) queue.push(cur.right);\n } else return;\n }\n return;\n };\n\n let inserted: N | null | undefined, needInsert: N | null;\n\n if (keyOrNode === null) {\n needInsert = null;\n } else if (typeof keyOrNode === 'number') {\n needInsert = this.createNode(keyOrNode, value);\n } else if (keyOrNode instanceof BinaryTreeNode) {\n needInsert = keyOrNode;\n } else {\n return;\n }\n\n // const key = typeof keyOrNode === 'number' ? keyOrNode : keyOrNode ? keyOrNode.key : undefined;\n // const existNode = key !== undefined ? this.getNode(key, (node: N) => node.key) : undefined;\n\n if (this.root) {\n // if (existNode) {\n // existNode.value = value;\n // inserted = existNode;\n // } else {\n inserted = _bfs(this.root, needInsert);\n // }\n } else {\n this._setRoot(needInsert);\n if (needInsert !== null) {\n this._size = 1;\n } else {\n this._size = 0;\n }\n inserted = this.root;\n }\n return inserted;\n }\n\n /**\n * The `addMany` function takes an array of binary tree node IDs or nodes, and optionally an array of corresponding data\n * values, and adds them to the binary tree.\n * @param {(BTNKey | null)[] | (N | null)[]} keysOrNodes - An array of BTNKey or BinaryTreeNode\n * objects, or null values.\n * @param {V[]} [values] - The `values` parameter is an optional array of values (`V[]`) that corresponds to\n * the nodes or node IDs being added. It is used to set the value of each node being added. If `values` is not provided,\n * the value of the nodes will be `undefined`.\n * @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.\n */\n addMany(keysOrNodes: (BTNKey | null | undefined)[] | (N | null | undefined)[], values?: V[]): (N | null | undefined)[] {\n // TODO not sure addMany not be run multi times\n return keysOrNodes.map((keyOrNode, i) => {\n if (keyOrNode instanceof BinaryTreeNode) {\n return this.add(keyOrNode.key, keyOrNode.value);\n }\n\n if (keyOrNode === null) {\n return this.add(null);\n }\n\n const value = values?.[i];\n return this.add(keyOrNode, value);\n });\n }\n\n /**\n * The `refill` function clears the binary tree and adds multiple nodes with the given IDs or nodes and optional data.\n * @param {(BTNKey | N)[]} keysOrNodes - The `keysOrNodes` parameter is an array that can contain either\n * `BTNKey` or `N` values.\n * @param {N[] | Array<V>} [data] - The `data` parameter is an optional array of values that will be assigned to\n * the nodes being added. If provided, the length of the `data` array should be equal to the length of the `keysOrNodes`\n * array. Each value in the `data` array will be assigned to the\n * @returns The method is returning a boolean value.\n */\n refill(keysOrNodes: (BTNKey | null | undefined)[] | (N | null | undefined)[], data?: Array<V>): boolean {\n this.clear();\n return keysOrNodes.length === this.addMany(keysOrNodes, data).length;\n }\n\n delete<C extends BTNCallback<N, BTNKey>>(identifier: BTNKey, callback?: C): BinaryTreeDeletedResult<N>[];\n\n delete<C extends BTNCallback<N, N>>(identifier: N | null | undefined, callback?: C): BinaryTreeDeletedResult<N>[];\n\n delete<C extends BTNCallback<N>>(identifier: ReturnType<C>, callback: C): BinaryTreeDeletedResult<N>[];\n\n /**\n * The `delete` function removes a node from a binary search tree and returns the deleted node along\n * with the parent node that needs to be balanced.\n * a key (`BTNKey`). If it is a key, the function will find the corresponding node in the\n * binary tree.\n * @returns an array of `BinaryTreeDeletedResult<N>` objects.\n * @param {ReturnType<C>} identifier - The `identifier` parameter is either a\n * `BTNKey` or a generic type `N`. It represents the property of the node that we are\n * searching for. It can be a specific key value or any other property of the node.\n * @param callback - The `callback` parameter is a function that takes a node as input and returns a\n * value. This value is compared with the `identifier` parameter to determine if the node should be\n * included in the result. The `callback` parameter has a default value of\n * `this.defaultOneParamCallback`, which\n */\n delete<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | null | undefined,\n callback: C = this.defaultOneParamCallback as C\n ): BinaryTreeDeletedResult<N>[] {\n const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];\n if (!this.root) return bstDeletedResult;\n if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;\n\n const curr = this.getNode(identifier, callback);\n if (!curr) return bstDeletedResult;\n\n const parent: N | null | undefined = curr?.parent ? curr.parent : null;\n let needBalanced: N | null | undefined = null,\n orgCurrent = curr;\n\n if (!curr.left) {\n if (!parent) {\n // Handle the case when there's only one root node\n this._setRoot(null);\n } else {\n const {familyPosition: fp} = curr;\n if (fp === FamilyPosition.LEFT || fp === FamilyPosition.ROOT_LEFT) {\n parent.left = curr.right;\n } else if (fp === FamilyPosition.RIGHT || fp === FamilyPosition.ROOT_RIGHT) {\n parent.right = curr.right;\n }\n needBalanced = parent;\n }\n } else {\n const leftSubTreeRightMost = curr.left ? this.getRightMost(curr.left) : null;\n if (leftSubTreeRightMost) {\n const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;\n orgCurrent = this._swap(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 }\n this._size = this.size - 1;\n\n bstDeletedResult.push({deleted: orgCurrent, needBalanced});\n return bstDeletedResult;\n }\n\n /**\n * The function `getDepth` calculates the depth of a given node in a binary tree relative to a\n * specified root node.\n * @param {BTNKey | N | null | undefined} distNode - The `distNode` parameter represents the node\n * whose depth we want to find in the binary tree. It can be either a node object (`N`), a key value\n * of the node (`BTNKey`), or `null`.\n * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the\n * starting node from which we want to calculate the depth. It can be either a node object or the key\n * of a node in the binary tree. If no value is provided for `beginRoot`, it defaults to the root\n * node of the binary tree.\n * @returns the depth of the `distNode` relative to the `beginRoot`.\n */\n getDepth(distNode: BTNKey | N | null | undefined, beginRoot: BTNKey | N | null | undefined = this.root): number {\n if (typeof distNode === 'number') distNode = this.getNode(distNode);\n if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);\n let depth = 0;\n while (distNode?.parent) {\n if (distNode === beginRoot) {\n return depth;\n }\n depth++;\n distNode = distNode.parent;\n }\n return depth;\n }\n\n /**\n * The `getHeight` function calculates the maximum height of a binary tree using either recursive or\n * iterative approach.\n * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the\n * starting node from which the height of the binary tree is calculated. It can be either a node\n * object (`N`), a key value of a node in the tree (`BTNKey`), or `null` if no starting\n * node is specified. If `\n * @param iterationType - The `iterationType` parameter is used to determine whether to calculate the\n * height of the binary tree using a recursive approach or an iterative approach. It can have two\n * possible values:\n * @returns the height of the binary tree.\n */\n getHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): number {\n if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);\n if (!beginRoot) return -1;\n\n if (iterationType === IterationType.RECURSIVE) {\n const _getMaxHeight = (cur: N | null | undefined): number => {\n if (!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(beginRoot);\n } else {\n if (!beginRoot) {\n return -1;\n }\n\n const stack: {node: N; depth: number}[] = [{node: beginRoot, depth: 0}];\n let maxHeight = 0;\n\n while (stack.length > 0) {\n const {node, depth} = stack.pop()!;\n\n if (node.left) {\n stack.push({node: node.left, depth: depth + 1});\n }\n\n if (node.right) {\n stack.push({node: node.right, depth: depth + 1});\n }\n\n maxHeight = Math.max(maxHeight, depth);\n }\n\n return maxHeight;\n }\n }\n\n /**\n * The `getMinHeight` function calculates the minimum height of a binary tree using either a\n * recursive or iterative approach.\n * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which we want to\n * calculate the minimum height of the tree. It is optional and defaults to the root of the tree if\n * not provided.\n * @param iterationType - The `iterationType` parameter is used to determine the method of iteration\n * to calculate the minimum height of a binary tree. It can have two possible values:\n * @returns The function `getMinHeight` returns the minimum height of a binary tree.\n */\n getMinHeight(beginRoot: N | null | undefined = this.root, iterationType = this.iterationType): number {\n if (!beginRoot) return -1;\n\n if (iterationType === IterationType.RECURSIVE) {\n const _getMinHeight = (cur: N | null | undefined): number => {\n if (!cur) return 0;\n if (!cur.left && !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(beginRoot);\n } else {\n const stack: N[] = [];\n let node: N | null | undefined = beginRoot,\n last: N | null | undefined = null;\n const depths: Map<N, number> = new Map();\n\n while (stack.length > 0 || node) {\n if (node) {\n stack.push(node);\n 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 leftMinHeight = node.left ? depths.get(node.left) ?? -1 : -1;\n const rightMinHeight = node.right ? depths.get(node.right) ?? -1 : -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(beginRoot) ?? -1;\n }\n }\n\n /**\n * The function checks if a binary tree is perfectly balanced by comparing the minimum height and the\n * height of the tree.\n * @param {N | null | undefined} beginRoot - The parameter `beginRoot` is of type `N | null | undefined`, which means it can\n * either be of type `N` (representing a node in a tree) or `null` (representing an empty tree).\n * @returns The method is returning a boolean value.\n */\n isPerfectlyBalanced(beginRoot: N | null | undefined = this.root): boolean {\n return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);\n }\n\n getNodes<C extends BTNCallback<N, BTNKey>>(\n identifier: BTNKey,\n callback?: C,\n onlyOne?: boolean,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): N[];\n\n getNodes<C extends BTNCallback<N, N>>(\n identifier: N | null | undefined,\n callback?: C,\n onlyOne?: boolean,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): N[];\n\n getNodes<C extends BTNCallback<N>>(\n identifier: ReturnType<C>,\n callback: C,\n onlyOne?: boolean,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): N[];\n\n /**\n * The function `getNodes` returns an array of nodes that match a given node property, using either\n * recursive or iterative traversal.\n * @param {ReturnType<C>} identifier - The `identifier` parameter is either a\n * `BTNKey` or a generic type `N`. It represents the property of the node that we are\n * searching for. It can be a specific key value or any other property of the node.\n * @param callback - The `callback` parameter is a function that takes a node as input and returns a\n * value. This value is compared with the `identifier` parameter to determine if the node should be\n * included in the result. The `callback` parameter has a default value of\n * `this.defaultOneParamCallback`, which\n * @param [onlyOne=false] - A boolean value indicating whether to stop searching after finding the\n * first node that matches the identifier. If set to true, the function will return an array with\n * only one element (or an empty array if no matching node is found). If set to false (default), the\n * function will continue searching for all\n * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which the\n * traversal of the binary tree will begin. It is optional and defaults to the root of the binary\n * tree.\n * @param iterationType - The `iterationType` parameter determines the type of iteration used to\n * traverse the binary tree. It can have two possible values:\n * @returns The function `getNodes` returns an array of nodes (`N[]`).\n */\n getNodes<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | null | undefined,\n callback: C = this.defaultOneParamCallback as C,\n onlyOne = false,\n beginRoot: N | null | undefined = this.root,\n iterationType = this.iterationType\n ): N[] {\n if (!beginRoot) return [];\n if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;\n const ans: N[] = [];\n\n if (iterationType === IterationType.RECURSIVE) {\n const _traverse = (cur: N) => {\n if (callback(cur) === identifier) {\n ans.push(cur);\n if (onlyOne) return;\n }\n if (!cur.left && !cur.right) return;\n cur.left && _traverse(cur.left);\n cur.right && _traverse(cur.right);\n };\n\n _traverse(beginRoot);\n } else {\n const queue = new Queue<N>([beginRoot]);\n while (queue.size > 0) {\n const cur = queue.shift();\n if (cur) {\n if (callback(cur) === identifier) {\n ans.push(cur);\n if (onlyOne) return ans;\n }\n cur.left && queue.push(cur.left);\n cur.right && queue.push(cur.right);\n }\n }\n }\n\n return ans;\n }\n\n has<C extends BTNCallback<N, BTNKey>>(\n identifier: BTNKey,\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): boolean;\n\n has<C extends BTNCallback<N, N>>(\n identifier: N | null | undefined,\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): boolean;\n\n has<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | null | undefined,\n callback: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): boolean;\n\n /**\n * The function checks if a binary tree has a node with a given property or key.\n * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of\n * the node that you want to find in the binary tree. It can be either a `BTNKey` or a\n * generic type `N`.\n * @param callback - The `callback` parameter is a function that is used to determine whether a node\n * matches the desired criteria. It takes a node as input and returns a boolean value indicating\n * whether the node matches the criteria or not. The default callback function\n * `this.defaultOneParamCallback` is used if no callback function is\n * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies\n * the node from which the search should begin. By default, it is set to `this.root`, which means the\n * search will start from the root node of the binary tree. However, you can provide a different node\n * as\n * @param iterationType - The `iterationType` parameter specifies the type of iteration to be\n * performed when searching for nodes in the binary tree. It can have one of the following values:\n * @returns a boolean value.\n */\n has<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | null | undefined,\n callback: C = this.defaultOneParamCallback as C,\n beginRoot = this.root,\n iterationType = this.iterationType\n ): boolean {\n if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;\n\n return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;\n }\n\n getNode<C extends BTNCallback<N, BTNKey>>(\n identifier: BTNKey,\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): N | null | undefined;\n\n getNode<C extends BTNCallback<N, N>>(\n identifier: N | null | undefined,\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): N | null | undefined;\n\n getNode<C extends BTNCallback<N>>(\n identifier: ReturnType<C>,\n callback: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): N | null | undefined;\n\n /**\n * The function `get` returns the first node in a binary tree that matches the given property or key.\n * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of\n * the node that you want to find in the binary tree. It can be either a `BTNKey` or `N`\n * type.\n * @param callback - The `callback` parameter is a function that is used to determine whether a node\n * matches the desired criteria. It takes a node as input and returns a boolean value indicating\n * whether the node matches the criteria or not. The default callback function\n * (`this.defaultOneParamCallback`) is used if no callback function is\n * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies\n * the root node from which the search should begin.\n * @param iterationType - The `iterationType` parameter specifies the type of iteration to be\n * performed when searching for a node in the binary tree. It can have one of the following values:\n * @returns either the found node (of type N) or null if no node is found.\n */\n getNode<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | null | undefined,\n callback: C = this.defaultOneParamCallback as C,\n beginRoot = this.root,\n iterationType = this.iterationType\n ): N | null | undefined {\n if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;\n\n return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;\n }\n\n get<C extends BTNCallback<N, BTNKey>>(\n identifier: BTNKey,\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): V | undefined;\n\n get<C extends BTNCallback<N, N>>(\n identifier: N | null | undefined,\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): V | undefined;\n\n get<C extends BTNCallback<N>>(\n identifier: ReturnType<C>,\n callback: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType\n ): V | undefined;\n\n /**\n * The function `get` returns the first node value in a binary tree that matches the given property or key.\n * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of\n * the node that you want to find in the binary tree. It can be either a `BTNKey` or `N`\n * type.\n * @param callback - The `callback` parameter is a function that is used to determine whether a node\n * matches the desired criteria. It takes a node as input and returns a boolean value indicating\n * whether the node matches the criteria or not. The default callback function\n * (`this.defaultOneParamCallback`) is used if no callback function is\n * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies\n * the root node from which the search should begin.\n * @param iterationType - The `iterationType` parameter specifies the type of iteration to be\n * performed when searching for a node in the binary tree. It can have one of the following values:\n * @returns either the found value (of type V) or undefined if no node value is found.\n */\n get<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | null | undefined,\n callback: C = this.defaultOneParamCallback as C,\n beginRoot = this.root,\n iterationType = this.iterationType\n ): V | undefined {\n if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;\n\n return this.getNode(identifier, callback, beginRoot, iterationType)?.value ?? undefined;\n }\n\n /**\n * The function `getPathToRoot` returns an array of nodes starting from a given node and traversing\n * up to the root node, with the option to reverse the order of the nodes.\n * @param {N} beginRoot - The `beginRoot` parameter represents the starting node from which you want\n * to find the path to the root node.\n * @param [isReverse=true] - The `isReverse` parameter is a boolean flag that determines whether the\n * resulting path should be reversed or not. If `isReverse` is set to `true`, the path will be\n * reversed before returning it. If `isReverse` is set to `false` or not provided, the path will\n * @returns The function `getPathToRoot` returns an array of type `N[]`.\n */\n getPathToRoot(beginRoot: N, isReverse = true): N[] {\n // TODO to support get path through passing key\n const result: N[] = [];\n while (beginRoot.parent) {\n // Array.push + Array.reverse is more efficient than Array.unshift\n // TODO may consider using Deque, so far this is not the performance bottleneck\n result.push(beginRoot);\n beginRoot = beginRoot.parent;\n }\n result.push(beginRoot);\n return isReverse ? result.reverse() : result;\n }\n\n /**\n * The function `getLeftMost` returns the leftmost node in a binary tree, either using recursive or\n * iterative traversal.\n * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point\n * for finding the leftmost node in a binary tree. It can be either a node object (`N`), a key value\n * of a node (`BTNKey`), or `null` if the tree is empty.\n * @param iterationType - The `iterationType` parameter is used to determine the type of iteration to\n * be performed when finding the leftmost node in a binary tree. It can have two possible values:\n * @returns The function `getLeftMost` returns the leftmost node (`N`) in a binary tree. If there is\n * no leftmost node, it returns `null`.\n */\n getLeftMost(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {\n if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);\n\n if (!beginRoot) return beginRoot;\n\n if (iterationType === IterationType.RECURSIVE) {\n const _traverse = (cur: N): N => {\n if (!cur.left) return cur;\n return _traverse(cur.left);\n };\n\n return _traverse(beginRoot);\n } else {\n // Indirect implementation of iteration using tail recursion optimization\n const _traverse = trampoline((cur: N) => {\n if (!cur.left) return cur;\n return _traverse.cont(cur.left);\n });\n\n return _traverse(beginRoot);\n }\n }\n\n /**\n * The function `getRightMost` returns the rightmost node in a binary tree, either recursively or\n * iteratively.\n * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which we want to\n * find the rightmost node. It is of type `N | null | undefined`, which means it can either be a node of type `N`\n * or `null`. If it is `null`, it means there is no starting node\n * @param iterationType - The `iterationType` parameter is used to determine the type of iteration to\n * be performed when finding the rightmost node in a binary tree. It can have two possible values:\n * @returns The function `getRightMost` returns the rightmost node (`N`) in a binary tree. If the\n * `beginRoot` parameter is `null`, it returns `null`.\n */\n getRightMost(beginRoot: N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {\n // TODO support get right most by passing key in\n if (!beginRoot) return beginRoot;\n\n if (iterationType === IterationType.RECURSIVE) {\n const _traverse = (cur: N): N => {\n if (!cur.right) return cur;\n return _traverse(cur.right);\n };\n\n return _traverse(beginRoot);\n } else {\n // Indirect implementation of iteration using tail recursion optimization\n const _traverse = trampoline((cur: N) => {\n if (!cur.right) return cur;\n return _traverse.cont(cur.right);\n });\n\n return _traverse(beginRoot);\n }\n }\n\n /**\n * The function `isSubtreeBST` checks if a given binary tree is a valid binary search tree.\n * @param {N} beginRoot - The `beginRoot` parameter is the root node of the binary tree that you want\n * to check if it is a binary search tree (BST) subtree.\n * @param iterationType - The `iterationType` parameter is an optional parameter that specifies the\n * type of iteration to use when checking if a subtree is a binary search tree (BST). It can have two\n * possible values:\n * @returns The function `isSubtreeBST` returns a boolean value.\n */\n isSubtreeBST(beginRoot: N | null | undefined, iterationType = this.iterationType): boolean {\n // TODO there is a bug\n if (!beginRoot) return true;\n\n if (iterationType === IterationType.RECURSIVE) {\n const dfs = (cur: N | null | undefined, min: BTNKey, max: BTNKey): boolean => {\n if (!cur) return true;\n if (cur.key <= min || cur.key >= max) return false;\n return dfs(cur.left, min, cur.key) && dfs(cur.right, cur.key, max);\n };\n\n return dfs(beginRoot, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);\n } else {\n const stack = [];\n let prev = Number.MIN_SAFE_INTEGER,\n curr: N | null | undefined = beginRoot;\n while (curr || stack.length > 0) {\n while (curr) {\n stack.push(curr);\n curr = curr.left;\n }\n curr = stack.pop()!;\n if (!curr || prev >= curr.key) return false;\n prev = curr.key;\n curr = curr.right;\n }\n return true;\n }\n }\n\n /**\n * The function checks if a binary tree is a binary search tree.\n * @param iterationType - The parameter \"iterationType\" is used to specify the type of iteration to\n * be used when checking if the binary tree is a binary search tree (BST). It is an optional\n * parameter with a default value of \"this.iterationType\". The value of \"this.iterationType\" is not\n * provided in\n * @returns a boolean value.\n */\n isBST(iterationType = this.iterationType): boolean {\n if (this.root === null) return true;\n return this.isSubtreeBST(this.root, iterationType);\n }\n\n subTreeTraverse<C extends BTNCallback<N>>(\n callback?: C,\n beginRoot?: BTNKey | N | null | undefined,\n iterationType?: IterationType,\n includeNull?: false\n ): ReturnType<C>[];\n\n subTreeTraverse<C extends BTNCallback<N>>(\n callback?: C,\n beginRoot?: BTNKey | N | null | undefined,\n iterationType?: IterationType,\n includeNull?: undefined\n ): ReturnType<C>[];\n\n subTreeTraverse<C extends BTNCallback<N | null | undefined>>(\n callback?: C,\n beginRoot?: BTNKey | N | null | undefined,\n iterationType?: IterationType,\n includeNull?: true\n ): ReturnType<C>[];\n\n /**\n * The function `subTreeTraverse` traverses a binary tree and applies a callback function to each\n * node, either recursively or iteratively.\n * @param callback - The `callback` parameter is a function that will be called on each node in the\n * subtree traversal. It takes a single argument, which is the current node being traversed, and\n * returns a value. The return values from each callback invocation will be collected and returned as\n * an array.\n * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point\n * for traversing the subtree. It can be either a node object, a key value of a node, or `null` to\n * start from the root of the tree.\n * @param iterationType - The `iterationType` parameter determines the type of traversal to be\n * performed on the binary tree. It can have two possible values:\n * @param includeNull - The choice to output null values during binary tree traversal should be provided.\n * @returns The function `subTreeTraverse` returns an array of `ReturnType<BTNCallback<N>>`.\n */\n subTreeTraverse<C extends BTNCallback<N | null | undefined>>(\n callback: C = this.defaultOneParamCallback as C,\n beginRoot: BTNKey | N | null | undefined = this.root,\n iterationType = this.iterationType,\n includeNull = false\n ): ReturnType<C>[] {\n if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);\n\n const ans: (ReturnType<BTNCallback<N>> | null | undefined)[] = [];\n if (!beginRoot) return ans;\n\n if (iterationType === IterationType.RECURSIVE) {\n const _traverse = (cur: N | null | undefined) => {\n if (cur !== undefined) {\n ans.push(callback(cur));\n if (includeNull) {\n cur && this.isNodeOrNull(cur.left) && _traverse(cur.left);\n cur && this.isNodeOrNull(cur.right) && _traverse(cur.right);\n } else {\n cur && cur.left && _traverse(cur.left);\n cur && cur.right && _traverse(cur.right);\n }\n }\n };\n\n _traverse(beginRoot);\n } else {\n const stack: (N | null | undefined)[] = [beginRoot];\n\n while (stack.length > 0) {\n const cur = stack.pop();\n if (cur !== undefined) {\n ans.push(callback(cur));\n if (includeNull) {\n cur && this.isNodeOrNull(cur.right) && stack.push(cur.right);\n cur && this.isNodeOrNull(cur.left) && stack.push(cur.left);\n } else {\n cur && cur.right && stack.push(cur.right);\n cur && cur.left && stack.push(cur.left);\n }\n }\n }\n }\n return ans;\n }\n \n isNode(node: any): node is N {\n return node instanceof BinaryTreeNode && node.key.toString() !== 'NaN';\n }\n\n isNIL(node: any) {\n return node instanceof BinaryTreeNode && node.key.toString() === 'NaN';\n }\n\n isNodeOrNull(node: any): node is (N | null){\n return this.isNode(node) || node === null;\n }\n\n dfs<C extends BTNCallback<N>>(\n callback?: C,\n pattern?: DFSOrderPattern,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: false\n ): ReturnType<C>[];\n\n dfs<C extends BTNCallback<N>>(\n callback?: C,\n pattern?: DFSOrderPattern,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: undefined\n ): ReturnType<C>[];\n\n dfs<C extends BTNCallback<N | null | undefined>>(\n callback?: C,\n pattern?: DFSOrderPattern,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: true\n ): ReturnType<C>[];\n\n /**\n * The `dfs` function performs a depth-first search traversal on a binary tree, executing a callback\n * function on each node according to a specified order pattern.\n * @param callback - The `callback` parameter is a function that will be called on each node during\n * the depth-first search traversal. It takes a node as input and returns a value. The default value\n * is `this.defaultOneParamCallback`, which is a callback function defined elsewhere in the code.\n * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter determines the order in which the\n * nodes are visited during the depth-first search. There are three possible values for `pattern`:\n * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the depth-first\n * search. It determines where the search will begin in the tree or graph structure. If `beginRoot`\n * is `null`, an empty array will be returned.\n * @param {IterationType} iterationType - The `iterationType` parameter determines the type of\n * iteration used in the depth-first search algorithm. It can have two possible values:\n * @param includeNull - The choice to output null values during binary tree traversal should be provided.\n * @returns The function `dfs` returns an array of `ReturnType<BTNCallback<N>>` values.\n */\n dfs<C extends BTNCallback<N | null | undefined>>(\n callback: C = this.defaultOneParamCallback as C,\n pattern: DFSOrderPattern = 'in',\n beginRoot: N | null | undefined = this.root,\n iterationType: IterationType = IterationType.ITERATIVE,\n includeNull = false\n ): ReturnType<C>[] {\n if (!beginRoot) return [];\n const ans: ReturnType<C>[] = [];\n if (iterationType === IterationType.RECURSIVE) {\n const _traverse = (node: N | null | undefined) => {\n switch (pattern) {\n case 'in':\n if (includeNull) {\n if (node && this.isNodeOrNull(node.left)) _traverse(node.left);\n this.isNodeOrNull(node) && ans.push(callback(node));\n if (node && this.isNodeOrNull(node.right)) _traverse(node.right);\n } else {\n if (node && node.left) _traverse(node.left);\n this.isNode(node) && ans.push(callback(node));\n if (node && node.right) _traverse(node.right);\n }\n break;\n case 'pre':\n if (includeNull) {\n this.isNodeOrNull(node) && ans.push(callback(node));\n if (node && this.isNodeOrNull(node.left)) _traverse(node.left);\n if (node && this.isNodeOrNull(node.right)) _traverse(node.right);\n } else {\n this.isNode(node) && ans.push(callback(node));\n if (node && node.left) _traverse(node.left);\n if (node && node.right) _traverse(node.right);\n }\n break;\n case 'post':\n if (includeNull) {\n if (node && this.isNodeOrNull(node.left)) _traverse(node.left);\n if (node && this.isNodeOrNull(node.right)) _traverse(node.right);\n this.isNodeOrNull(node) && ans.push(callback(node));\n } else {\n if (node && node.left) _traverse(node.left);\n if (node && node.right) _traverse(node.right);\n this.isNode(node) && ans.push(callback(node));\n }\n\n break;\n }\n };\n\n _traverse(beginRoot);\n } else {\n // 0: visit, 1: print\n const stack: {opt: 0 | 1; node: N | null | undefined}[] = [{opt: 0, node: beginRoot}];\n\n while (stack.length > 0) {\n const cur = stack.pop();\n if (cur === undefined || this.isNIL(cur.node)) continue;\n if (includeNull) {\n if (cur.node === undefined) continue;\n } else {\n if (cur.node === null || cur.node === undefined) continue;\n }\n if (cur.opt === 1) {\n ans.push(callback(cur.node));\n } else {\n switch (pattern) {\n case 'in':\n cur.node && stack.push({opt: 0, node: cur.node.right});\n stack.push({opt: 1, node: cur.node});\n cur.node && stack.push({opt: 0, node: cur.node.left});\n break;\n case 'pre':\n cur.node && stack.push({opt: 0, node: cur.node.right});\n cur.node && stack.push({opt: 0, node: cur.node.left});\n stack.push({opt: 1, node: cur.node});\n break;\n case 'post':\n stack.push({opt: 1, node: cur.node});\n cur.node && stack.push({opt: 0, node: cur.node.right});\n cur.node && stack.push({opt: 0, node: cur.node.left});\n break;\n default:\n cur.node && stack.push({opt: 0, node: cur.node.right});\n stack.push({opt: 1, node: cur.node});\n cur.node && stack.push({opt: 0, node: cur.node.left});\n break;\n }\n }\n }\n }\n\n return ans;\n }\n\n bfs<C extends BTNCallback<N>>(\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: false\n ): ReturnType<C>[];\n\n bfs<C extends BTNCallback<N>>(\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: undefined\n ): ReturnType<C>[];\n\n bfs<C extends BTNCallback<N | null | undefined>>(\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: true\n ): ReturnType<C>[];\n\n /**\n * The bfs function performs a breadth-first search traversal on a binary tree, executing a callback\n * function on each node.\n * @param callback - The `callback` parameter is a function that will be called for each node in the\n * breadth-first search. It takes a node of type `N` as its argument and returns a value of type\n * `ReturnType<BTNCallback<N>>`. The default value for this parameter is `this.defaultOneParamCallback\n * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the breadth-first\n * search. It determines from which node the search will begin. If `beginRoot` is `null`, the search\n * will not be performed and an empty array will be returned.\n * @param iterationType - The `iterationType` parameter determines the type of iteration to be used\n * in the breadth-first search (BFS) algorithm. It can have two possible values:\n * @param includeNull - The choice to output null values during binary tree traversal should be provided.\n * @returns The function `bfs` returns an array of `ReturnType<BTNCallback<N>>[]`.\n */\n bfs<C extends BTNCallback<N | null | undefined>>(\n callback: C = this.defaultOneParamCallback as C,\n beginRoot: N | null | undefined = this.root,\n iterationType = this.iterationType,\n includeNull = false\n ): ReturnType<C>[] {\n if (!beginRoot) return [];\n\n const ans: ReturnType<BTNCallback<N>>[] = [];\n\n if (iterationType === IterationType.RECURSIVE) {\n const queue: Queue<N | null | undefined> = new Queue<N | null | undefined>([beginRoot]);\n\n const traverse = (level: number) => {\n if (queue.size === 0) return;\n\n const current = queue.shift()!;\n ans.push(callback(current));\n\n if (includeNull) {\n if (current && this.isNodeOrNull(current.left)) queue.push(current.left);\n if (current && this.isNodeOrNull(current.right)) queue.push(current.right);\n } else {\n if (current.left) queue.push(current.left);\n if (current.right) queue.push(current.right);\n }\n\n traverse(level + 1);\n };\n\n traverse(0);\n } else {\n const queue = new Queue<N | null | undefined>([beginRoot]);\n while (queue.size > 0) {\n const levelSize = queue.size;\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.isNodeOrNull(current.left)) queue.push(current.left);\n if (current && this.isNodeOrNull(current.right)) queue.push(current.right);\n } else {\n if (current.left) queue.push(current.left);\n if (current.right) queue.push(current.right);\n }\n }\n }\n }\n return ans;\n }\n\n listLevels<C extends BTNCallback<N>>(\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: false\n ): ReturnType<C>[][];\n\n listLevels<C extends BTNCallback<N>>(\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: undefined\n ): ReturnType<C>[][];\n\n listLevels<C extends BTNCallback<N | null | undefined>>(\n callback?: C,\n beginRoot?: N | null | undefined,\n iterationType?: IterationType,\n includeNull?: true\n ): ReturnType<C>[][];\n\n /**\n * The `listLevels` function takes a binary tree node and a callback function, and returns an array\n * of arrays representing the levels of the tree.\n * @param {C} callback - The `callback` parameter is a function that will be called on each node in\n * the tree. It takes a node as input and returns a value. The return type of the callback function\n * is determined by the generic type `C`.\n * @param {N | null | undefined} beginRoot - The `beginRoot` parameter represents the starting node of the binary tree\n * traversal. It can be any node in the binary tree. If no node is provided, the traversal will start\n * from the root node of the binary tree.\n * @param iterationType - The `iterationType` parameter determines whether the tree traversal is done\n * recursively or iteratively. It can have two possible values:\n * @param includeNull - The choice to output null values during binary tree traversal should be provided.\n * @returns The function `listLevels` returns an array of arrays, where each inner array represents a\n * level in a binary tree. Each inner array contains the return type of the provided callback\n * function `C` applied to the nodes at that level.\n */\n listLevels<C extends BTNCallback<N | null | undefined>>(\n callback: C = this.defaultOneParamCallback as C,\n beginRoot: N | null | undefined = this.root,\n iterationType = this.iterationType,\n includeNull = false\n ): ReturnType<C>[][] {\n if (!beginRoot) return [];\n const levelsNodes: ReturnType<C>[][] = [];\n\n if (iterationType === IterationType.RECURSIVE) {\n const _recursive = (node: N | null | undefined, level: number) => {\n if (!levelsNodes[level]) levelsNodes[level] = [];\n levelsNodes[level].push(callback(node));\n if (includeNull) {\n if (node && this.isNodeOrNull(node.left)) _recursive(node.left, level + 1);\n if (node && this.isNodeOrNull(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(beginRoot, 0);\n } else {\n const stack: [N | null | undefined, number][] = [[beginRoot, 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.isNodeOrNull(node.right)) stack.push([node.right, level + 1]);\n if (node && this.isNodeOrNull(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 /**\n * The function returns the predecessor node of a given node in a binary tree.\n * @param {N} node - The parameter \"node\" represents a node in a binary tree.\n * @returns The function `getPredecessor` returns the predecessor node of the given node `node`.\n */\n getPredecessor(node: N): N {\n if (node.left) {\n let predecessor: N | null | undefined = node.left;\n while (!predecessor || (predecessor.right && predecessor.right !== node)) {\n if (predecessor) {\n predecessor = predecessor.right;\n }\n }\n return predecessor;\n } else {\n return node;\n }\n }\n\n /**\n * The function `getSuccessor` returns the next node in a binary tree given a node `x`, or `null` if\n * `x` is the last node.\n * @param {N} x - N - a node in a binary tree\n * @returns The function `getSuccessor` returns a value of type `N` (the successor node), or `null`\n * if there is no successor, or `undefined` if the input `x` is `undefined`.\n */\n getSuccessor(x: N): N | null | undefined {\n if (x.right) {\n return this.getLeftMost(x.right);\n }\n\n let y: N | null | undefined = x.parent;\n while (y && y && x === y.right) {\n x = y;\n y = y.parent;\n }\n return y;\n }\n\n /**\n * The `morris` function performs a depth-first traversal of a binary tree using the Morris traversal\n * algorithm and returns an array of values obtained by applying a callback function to each node.\n * @param callback - The `callback` parameter is a function that will be called on each node in the\n * tree. It takes a node of type `N` as input and returns a value of type `ReturnType<BTNCallback<N>>`. The\n * default value for this parameter is `this.defaultOneParamCallback`.\n * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter in the `morris` function\n * determines the order in which the nodes of a binary tree are traversed. It can have one of the\n * following values:\n * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the Morris\n * traversal. It specifies the root node of the tree from which the traversal should begin. If\n * `beginRoot` is `null`, an empty array will be returned.\n * @returns The `morris` function returns an array of `ReturnType<BTNCallback<N>>` values.\n */\n morris<C extends BTNCallback<N>>(\n callback: C = this.defaultOneParamCallback as C,\n pattern: DFSOrderPattern = 'in',\n beginRoot: N | null | undefined = this.root\n ): ReturnType<C>[] {\n if (beginRoot === null) return [];\n const ans: ReturnType<BTNCallback<N>>[] = [];\n\n let cur: N | null | undefined = beginRoot;\n const _reverseEdge = (node: N | null | undefined) => {\n let pre: N | null | undefined = null;\n let next: N | 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: N | null | undefined) => {\n const tail: N | null | undefined = _reverseEdge(node);\n let cur: N | 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(beginRoot);\n break;\n }\n return ans;\n }\n\n // --- start additional methods ---\n\n /**\n * The above function is an iterator for a binary tree that can be used to traverse the tree in\n * either an iterative or recursive manner.\n * @param node - The `node` parameter represents the current node in the binary tree from which the\n * iteration starts. It is an optional parameter with a default value of `this.root`, which means\n * that if no node is provided, the iteration will start from the root of the binary tree.\n * @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the\n * binary tree nodes in a specific order.\n */\n *[Symbol.iterator](node = this.root): Generator<BTNKey, void, undefined> {\n if (!node) {\n return;\n }\n\n if (this.iterationType === IterationType.ITERATIVE) {\n const stack: (N | null | undefined)[] = [];\n let current: N | null | undefined = node;\n\n while (current || stack.length > 0) {\n while (current) {\n stack.push(current);\n current = current.left;\n }\n\n current = stack.pop();\n\n if (current) yield current.key;\n if (current) current = current.right;\n }\n } else {\n if (node.left) {\n // @ts-ignore\n yield* this[Symbol.iterator](node.left);\n }\n yield node.key;\n if (node.right) {\n // @ts-ignore\n yield* this[Symbol.iterator](node.right);\n }\n }\n }\n\n protected defaultOneParamCallback = (node: N) => node.key;\n\n /**\n * Swap the data of two nodes in the binary tree.\n * @param {N} srcNode - The source node to swap.\n * @param {N} destNode - The destination node to swap.\n * @returns {N} - The destination node after the swap.\n */\n protected _swap(srcNode: N, destNode: N): N {\n const {key, value} = destNode;\n const tempNode = this.createNode(key, value);\n\n if (tempNode) {\n destNode.key = srcNode.key;\n destNode.value = srcNode.value;\n\n srcNode.key = tempNode.key;\n srcNode.value = tempNode.value;\n }\n\n return destNode;\n }\n\n /**\n * The function `_addTo` adds a new node to a binary tree if there is an available position.\n * @param {N | null | undefined} newNode - The `newNode` parameter represents the node that you want to add to\n * the binary tree. It can be either a node object or `null`.\n * @param {N} parent - The `parent` parameter represents the parent node to which the new node will\n * be added as a child.\n * @returns either the left or right child node of the parent node, depending on which child is\n * available for adding the new node. If a new node is added, the function also updates the size of\n * the binary tree. If neither the left nor right child is available, the function returns undefined.\n * If the parent node is null, the function also returns undefined.\n */\n protected _addTo(newNode: N | null | undefined, parent: N): N | null | undefined {\n if (parent) {\n // When all leaf nodes are null, it will no longer be possible to add new entity nodes to this binary tree.\n // In this scenario, null nodes serve as \"sentinel nodes,\" \"virtual nodes,\" or \"placeholder nodes.\"\n if (parent.left === undefined) {\n parent.left = newNode;\n if (newNode) {\n this._size = this.size + 1;\n }\n return parent.left;\n } else if (parent.right === undefined) {\n parent.right = newNode;\n if (newNode) {\n this._size = this.size + 1;\n }\n return parent.right;\n } else {\n return;\n }\n } else {\n return;\n }\n }\n\n /**\n * The function sets the root property of an object to a given value, and if the value is not null,\n * it also sets the parent property of the value to undefined.\n * @param {N | null | undefined} v - The parameter `v` is of type `N | null | undefined`, which means it can either be of\n * type `N` or `null`.\n */\n protected _setRoot(v: N | null | undefined) {\n if (v) {\n v.parent = undefined;\n }\n this._root = v;\n }\n\n print(beginRoot: N | null | undefined = this.root) {\n const display = (root: N | null | undefined): void => {\n const [lines, , ,] = _displayAux(root);\n for (const line of lines) {\n console.log(line);\n }\n };\n\n const _displayAux = (node: N | null | undefined): [string[], number, number, number] => {\n if (node === undefined || node === null) {\n return [[], 0, 0, 0];\n }\n\n if (node && node.right === undefined && node.left === undefined) {\n const line = `${node.key}`;\n const width = line.length;\n const height = 1;\n const middle = Math.floor(width / 2);\n return [[line], width, height, middle];\n }\n\n if (node && node.right === undefined) {\n const [lines, n, p, x] = _displayAux(node.left);\n const s = `${node.key}`;\n const u = s.length;\n const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s;\n const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u);\n const shifted_lines = lines.map(line => line + ' '.repeat(u));\n return [[first_line, second_line, ...shifted_lines], n + u, p + 2, n + Math.floor(u / 2)];\n }\n\n if (node && node.left === undefined) {\n const [lines, n, p, u] = _displayAux(node.right);\n const s = `${node.key}`;\n const x = s.length;\n const first_line = s + '_'.repeat(x) + ' '.repeat(n - x);\n const second_line = ' '.repeat(u + x) + '\\\\' + ' '.repeat(n - x - 1);\n const shifted_lines = lines.map(line => ' '.repeat(u) + line);\n return [[first_line, second_line, ...shifted_lines], n + x, p + 2, Math.floor(u / 2)];\n }\n\n const [left, n, p, x] = _displayAux(node.left);\n const [right, m, q, y] = _displayAux(node.right);\n const s = `${node.key}`;\n const u = s.length;\n const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s + '_'.repeat(y) + ' '.repeat(m - y);\n const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u + y) + '\\\\' + ' '.repeat(m - y - 1);\n if (p < q) {\n left.push(...new Array(q - p).fill(' '.repeat(n)));\n } else if (q < p) {\n right.push(...new Array(p - q).fill(' '.repeat(m)));\n }\n const zipped_lines = left.map((a, i) => a + ' '.repeat(u) + right[i]);\n return [[first_line, second_line, ...zipped_lines], n + m + u, Math.max(p, q) + 2, n + Math.floor(u / 2)];\n };\n\n display(beginRoot);\n }\n // --- end additional methods ---\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type {BSTComparator, BSTNodeNested, BSTOptions, BTNCallback, BTNKey} from '../../types';\nimport {CP, IterationType} from '../../types';\nimport {BinaryTree, BinaryTreeNode} from './binary-tree';\nimport {IBinaryTree} from '../../interfaces';\nimport {Queue} from '../queue';\n\nexport class BSTNode<V = any, N extends BSTNode<V, N> = BSTNodeNested<V>> extends BinaryTreeNode<V, N> {\n override parent: N | undefined;\n constructor(key: BTNKey, value?: V) {\n super(key, value);\n this.parent = undefined;\n this._left = undefined;\n this._right = undefined;\n }\n\n protected override _left: N | undefined;\n\n /**\n * Get the left child node.\n */\n override get left(): N | undefined {\n return this._left;\n }\n\n /**\n * Set the left child node.\n * @param {N | undefined} v - The left child node.\n */\n override set left(v: N | undefined) {\n if (v) {\n v.parent = this as unknown as N;\n }\n this._left = v;\n }\n\n\n protected override _right: N | undefined;\n\n /**\n * Get the right child node.\n */\n override get right(): N | undefined {\n return this._right;\n }\n\n /**\n * Set the right child node.\n * @param {N | undefined} v - The right child node.\n */\n override set right(v: N | undefined) {\n if (v) {\n v.parent = this as unknown as N;\n }\n this._right = v;\n }\n}\n\nexport class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>>\n extends BinaryTree<V, N>\n implements IBinaryTree<V, N>\n{\n /**\n * The constructor function initializes a binary search tree object with an optional comparator\n * function.\n * @param {BSTOptions} [options] - An optional object that contains configuration options for the\n * binary search tree.\n */\n constructor(options?: BSTOptions) {\n super(options);\n this._root = undefined;\n if (options !== undefined) {\n const {comparator} = options;\n if (comparator !== undefined) {\n this._comparator = comparator;\n }\n }\n }\n protected override _root: N | undefined = undefined;\n\n /**\n * Get the root node of the binary tree.\n */\n override get root(): N | undefined {\n return this._root;\n }\n\n /**\n * The function creates a new binary search tree node with the given key and value.\n * @param {BTNKey} key - The key parameter is the key value that will be associated with\n * the new node. It is used to determine the position of the node in the binary search tree.\n * @param [value] - The parameter `value` is an optional value that can be assigned to the node. It\n * represents the value associated with the node in a binary search tree.\n * @returns a new instance of the BSTNode class with the specified key and value.\n */\n override createNode(key: BTNKey, value?: V): N {\n return new BSTNode<V, N>(key, value) as N;\n }\n\n /**\n * The `add` function in a binary search tree class inserts a new node with a given key and value\n * into the tree.\n * @param {BTNKey | N | undefined} keyOrNode - The `keyOrNode` parameter can be either a\n * `BTNKey` (which can be a number or a string), a `BSTNode` object, or `undefined`.\n * @param [value] - The `value` parameter is the value to be assigned to the new node being added to the\n * binary search tree.\n * @returns the inserted node (N) if it was successfully added to the binary search tree. If the node\n * was not added or if the parameters were invalid, it returns undefined or undefined.\n */\n override add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | undefined {\n if (keyOrNode === 8) {\n debugger\n }\n if (keyOrNode === null) return undefined;\n // TODO support node as a parameter\n let inserted:N | undefined;\n let newNode:N | undefined;\n if (keyOrNode instanceof BSTNode) {\n newNode = keyOrNode;\n } else if (typeof keyOrNode === 'number') {\n newNode = this.createNode(keyOrNode, value);\n } else {\n newNode = undefined;\n }\n if (this.root === undefined) {\n this._setRoot(newNode);\n this._size = this.size + 1;\n inserted = this.root;\n } else {\n let cur = this.root;\n let traversing = true;\n while (traversing) {\n if (cur !== undefined && newNode !== undefined) {\n if (this._compare(cur.key, newNode.key) === CP.eq) {\n if (newNode) {\n cur.value = newNode.value;\n }\n //Duplicates are not accepted.\n traversing = false;\n inserted = cur;\n } else if (this._compare(cur.key, newNode.key) === CP.gt) {\n // Traverse left of the node\n if (cur.left === undefined) {\n if (newNode) {\n newNode.parent = cur;\n }\n //Add to the left of the current node\n cur.left = newNode;\n this._size = this.size + 1;\n traversing = false;\n inserted = cur.left;\n } else {\n //Traverse the left of the current node\n if (cur.left) cur = cur.left;\n }\n } else if (this._compare(cur.key, newNode.key) === CP.lt) {\n // Traverse right of the node\n if (cur.right === undefined) {\n if (newNode) {\n newNode.parent = cur;\n }\n //Add to the right of the current node\n cur.right = newNode;\n this._size = this.size + 1;\n traversing = false;\n inserted = cur.right;\n } else {\n //Traverse the left of the current node\n if (cur.right) cur = cur.right;\n }\n }\n } else {\n traversing = false;\n }\n }\n }\n return inserted;\n }\n\n /**\n * The `addMany` function is used to efficiently add multiple nodes to a binary search tree while\n * maintaining balance.\n * @param {[BTNKey | N, V][]} keysOrNodes - The `arr` parameter in the `addMany` function\n * represents an array of keys or nodes that need to be added to the binary search tree. It can be an\n * array of `BTNKey` or `N` (which represents the node type in the binary search tree) or\n * `undefined\n * @param {V[]} data - The values of tree nodes\n * @param {boolean} isBalanceAdd - If true the nodes will be balance inserted in binary search method.\n * @param iterationType - The `iterationType` parameter determines the type of iteration to be used.\n * It can have two possible values:\n * @returns The `addMany` function returns an array of `N`, `undefined`, or `undefined` values.\n */\n\n override addMany(\n keysOrNodes: (BTNKey | undefined)[] | (N | undefined)[],\n data?: V[],\n isBalanceAdd = true,\n iterationType = this.iterationType\n ): (N | undefined)[] {\n // TODO this addMany function is inefficient, it should be optimized\n function hasNoNull(arr: (BTNKey | undefined)[] | (N | undefined)[]): arr is BTNKey[] | N[] {\n return arr.indexOf(undefined) === -1;\n }\n\n if (!isBalanceAdd || !hasNoNull(keysOrNodes)) {\n return super.addMany(keysOrNodes, data).map(n => n ?? undefined);\n }\n const inserted: (N | undefined)[] = [];\n const combinedArr: [BTNKey | N, V][] = keysOrNodes.map(\n (value: BTNKey | N, index) => [value, data?.[index]] as [BTNKey | N, V]\n );\n let sorted = [];\n\n function isNodeOrNullTuple(arr: [BTNKey | N, V][]): arr is [N, V][] {\n for (const [keyOrNode] of arr) if (keyOrNode instanceof BSTNode) return true;\n return false;\n }\n\n function isBinaryTreeKeyOrNullTuple(arr: [BTNKey | N, V][]): arr is [BTNKey, V][] {\n for (const [keyOrNode] of arr) if (typeof keyOrNode === 'number') return true;\n return false;\n }\n\n let sortedKeysOrNodes: (number | N | undefined)[] = [],\n sortedData: (V | undefined)[] | undefined = [];\n\n if (isNodeOrNullTuple(combinedArr)) {\n sorted = combinedArr.sort((a, b) => a[0].key - b[0].key);\n } else if (isBinaryTreeKeyOrNullTuple(combinedArr)) {\n sorted = combinedArr.sort((a, b) => a[0] - b[0]);\n } else {\n throw new Error('Invalid input keysOrNodes');\n }\n sortedKeysOrNodes = sorted.map(([keyOrNode]) => keyOrNode);\n sortedData = sorted.map(([, value]) => value);\n const recursive = (arr: (BTNKey | undefined | N)[], data?: (V | undefined)[]) => {\n if (arr.length === 0) return;\n\n const mid = Math.floor((arr.length - 1) / 2);\n const newNode = this.add(arr[mid], data?.[mid]);\n inserted.push(newNode);\n recursive(arr.slice(0, mid), data?.slice(0, mid));\n recursive(arr.slice(mid + 1), data?.slice(mid + 1));\n };\n const iterative = () => {\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 newNode = this.add(sortedKeysOrNodes[m], sortedData?.[m]);\n inserted.push(newNode);\n stack.push([m + 1, r]);\n stack.push([l, m - 1]);\n }\n }\n }\n };\n if (iterationType === IterationType.RECURSIVE) {\n recursive(sortedKeysOrNodes, sortedData);\n } else {\n iterative();\n }\n\n return inserted;\n }\n\n /**\n * The function `lastKey` returns the key of the rightmost node if the comparison result is less\n * than, the key of the leftmost node if the comparison result is greater than, and the key of the\n * rightmost node otherwise.\n * @param {N | undefined} beginRoot - The `beginRoot` parameter is the starting point for finding the last\n * key in a binary tree. It represents the root node of the subtree from which the search for the\n * last key should begin. If no specific `beginRoot` is provided, the search will start from the root\n * of the entire binary\n * @param iterationType - The `iterationType` parameter is used to specify the type of iteration to\n * be performed when finding the last key. It determines whether the iteration should be performed in\n * pre-order, in-order, or post-order.\n * @returns the key of the rightmost node in the binary tree if the comparison result is less than,\n * the key of the leftmost node if the comparison result is greater than, and the key of the\n * rightmost node otherwise. If no node is found, it returns 0.\n */\n lastKey(beginRoot: N | undefined = this.root, iterationType = this.iterationType): BTNKey {\n if (this._compare(0, 1) === CP.lt) return this.getRightMost(beginRoot, iterationType)?.key ?? 0;\n else if (this._compare(0, 1) === CP.gt) return this.getLeftMost(beginRoot, iterationType)?.key ?? 0;\n else return this.getRightMost(beginRoot, iterationType)?.key ?? 0;\n }\n\n /**\n * The function `getNodes` retrieves nodes from a binary tree based on a given node property or key,\n * using either recursive or iterative traversal.\n * @param {ReturnType<C> | N} identifier - The `nodeProperty` parameter represents the property\n * of the binary tree node that you want to search for. It can be either a `BTNKey` or a\n * generic type `N`.\n * @param callback - The `callback` parameter is a function that takes a node as input and returns a\n * value. This value is compared with the `nodeProperty` parameter to determine if the node should be\n * included in the result. The default value for `callback` is `this.defaultOneParamCallback`, which is\n * a\n * @param [onlyOne=false] - A boolean value indicating whether to stop the traversal after finding\n * the first node that matches the nodeProperty. If set to true, the function will return an array\n * containing only that node. If set to false (default), the function will continue the traversal and\n * return an array containing all nodes that match the node\n * @param {N | undefined} beginRoot - The `beginRoot` parameter is the starting node for the traversal. It\n * specifies the root node of the binary tree from which the traversal should begin. If `beginRoot`\n * is `undefined`, an empty array will be returned.\n * @param iterationType - The `iterationType` parameter determines the type of iteration used to\n * traverse the binary tree. It can have one of the following values:\n * @returns an array of nodes (N[]).\n */\n override getNodes<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | undefined,\n callback: C = this.defaultOneParamCallback as C,\n onlyOne = false,\n beginRoot: N | undefined = this.root,\n iterationType = this.iterationType\n ): N[] {\n if (!beginRoot) return [];\n const ans: N[] = [];\n\n if (iterationType === IterationType.RECURSIVE) {\n const _traverse = (cur: N) => {\n const callbackResult = callback(cur);\n if (callbackResult === identifier) {\n ans.push(cur);\n if (onlyOne) return;\n }\n\n if (!cur.left && !cur.right) return;\n // TODO potential bug\n if (callback === this.defaultOneParamCallback) {\n if (this._compare(cur.key, identifier as number) === CP.gt) cur.left && _traverse(cur.left);\n if (this._compare(cur.key, identifier as number) === CP.lt) cur.right && _traverse(cur.right);\n } else {\n cur.left && _traverse(cur.left);\n cur.right && _traverse(cur.right);\n }\n };\n\n _traverse(beginRoot);\n } else {\n const queue = new Queue<N>([beginRoot]);\n while (queue.size > 0) {\n const cur = queue.shift();\n if (cur) {\n const callbackResult = callback(cur);\n if (callbackResult === identifier) {\n ans.push(cur);\n if (onlyOne) return ans;\n }\n // TODO potential bug\n if (callback === this.defaultOneParamCallback) {\n if (this._compare(cur.key, identifier as number) === CP.gt) cur.left && queue.push(cur.left);\n if (this._compare(cur.key, identifier as number) === CP.lt) cur.right && queue.push(cur.right);\n } else {\n cur.left && queue.push(cur.left);\n cur.right && queue.push(cur.right);\n }\n }\n }\n }\n\n return ans;\n }\n\n // --- start additional functions\n\n /**\n * The `lesserOrGreaterTraverse` function traverses a binary tree and applies a callback function to\n * nodes that have a key value lesser or greater than a target key value.\n * @param callback - The `callback` parameter is a function that will be called for each node that\n * meets the condition specified by the `lesserOrGreater` parameter. It takes a node as an argument\n * and returns a value.\n * @param {CP} lesserOrGreater - The `lesserOrGreater` parameter is used to determine whether to\n * traverse nodes that are lesser than, greater than, or equal to the `targetNode`. It can take one\n * of the following values:\n * @param {BTNKey | N | undefined} targetNode - The `targetNode` parameter in the\n * `lesserOrGreaterTraverse` function is used to specify the node from which the traversal should\n * start. It can be either a reference to a specific node (`N`), the key of a node\n * (`BTNKey`), or `undefined` to\n * @param iterationType - The `iterationType` parameter determines whether the traversal should be\n * done recursively or iteratively. It can have two possible values:\n * @returns The function `lesserOrGreaterTraverse` returns an array of `ReturnType<BTNCallback<N>>`.\n */\n lesserOrGreaterTraverse<C extends BTNCallback<N>>(\n callback: C = this.defaultOneParamCallback as C,\n lesserOrGreater: CP = CP.lt,\n targetNode: BTNKey | N | undefined = this.root,\n iterationType = this.iterationType\n ): ReturnType<C>[] {\n if (typeof targetNode === 'number') targetNode = this.getNode(targetNode) ?? undefined;\n const ans: ReturnType<BTNCallback<N>>[] = [];\n if (!targetNode) return ans;\n const targetKey = targetNode.key;\n if (!this.root) return ans;\n\n if (iterationType === IterationType.RECURSIVE) {\n const _traverse = (cur: N) => {\n const compared = this._compare(cur.key, targetKey);\n if (compared === lesserOrGreater) ans.push(callback(cur));\n\n if (!cur.left && !cur.right) return;\n if (cur.left && this._compare(cur.left.key, targetKey) === lesserOrGreater) _traverse(cur.left);\n if (cur.right && this._compare(cur.right.key, targetKey) === lesserOrGreater) _traverse(cur.right);\n };\n\n _traverse(this.root);\n return ans;\n } else {\n const queue = new Queue<N>([this.root]);\n while (queue.size > 0) {\n const cur = queue.shift();\n if (cur) {\n const compared = this._compare(cur.key, targetKey);\n if (compared === lesserOrGreater) ans.push(callback(cur));\n\n if (cur.left && this._compare(cur.left.key, targetKey) === lesserOrGreater) queue.push(cur.left);\n if (cur.right && this._compare(cur.right.key, targetKey) === lesserOrGreater) queue.push(cur.right);\n }\n }\n return ans;\n }\n }\n\n /**\n * Balancing Adjustment:\n * Perfectly Balanced Binary Tree: Since the balance of a perfectly balanced binary tree is already fixed, no additional balancing adjustment is needed. Any insertion or deletion operation will disrupt the perfect balance, often requiring a complete reconstruction of the tree.\n * AVL Tree: After insertion or deletion operations, an AVL tree performs rotation adjustments based on the balance factor of nodes to restore the tree's balance. These rotations can be left rotations, right rotations, left-right rotations, or right-left rotations, performed as needed.\n *\n * Use Cases and Efficiency:\n * Perfectly Balanced Binary Tree: Perfectly balanced binary trees are typically used in specific scenarios such as complete binary heaps in heap sort or certain types of Huffman trees. However, they are not suitable for dynamic operations requiring frequent insertions and deletions, as these operations often necessitate full tree reconstruction.\n * AVL Tree: AVL trees are well-suited for scenarios involving frequent searching, insertion, and deletion operations. Through rotation adjustments, AVL trees maintain their balance, ensuring average and worst-case time complexity of O(log n).\n */\n\n /**\n * The `perfectlyBalance` function balances a binary search tree by adding nodes in a way that\n * ensures the tree is perfectly balanced.\n * @param iterationType - The `iterationType` parameter is an optional parameter that specifies the\n * type of iteration to use when building a balanced binary search tree. It can have two possible\n * values:\n * @returns The function `perfectlyBalance` returns a boolean value.\n */\n perfectlyBalance(iterationType = this.iterationType): boolean {\n const sorted = this.dfs(node => node, 'in'),\n n = sorted.length;\n this.clear();\n\n if (sorted.length < 1) return false;\n if (iterationType === 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 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 debugger\n 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 * The function checks if a binary tree is AVL balanced using either recursive or iterative approach.\n * @param iterationType - The `iterationType` parameter is used to determine the method of iteration\n * to check if the AVL tree is balanced. It can have two possible values:\n * @returns a boolean value.\n */\n isAVLBalanced(iterationType = this.iterationType): boolean {\n if (!this.root) return true;\n\n let balanced = true;\n\n if (iterationType === IterationType.RECURSIVE) {\n const _height = (cur: N | 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: N[] = [];\n let node: N | undefined = this.root,\n last:N | undefined = undefined;\n const depths: Map<N, number> = new Map();\n\n while (stack.length > 0 || node) {\n if (node) {\n stack.push(node);\n 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 : -1;\n const right = node.right ? depths.get(node.right) ?? -1 : -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 protected _comparator: BSTComparator = (a, b) => a - b;\n\n protected _setRoot(v: N | undefined) {\n if (v) {\n v.parent = undefined;\n }\n this._root = v;\n }\n\n /**\n * The function compares two values using a comparator function and returns whether the first value\n * is greater than, less than, or equal to the second value.\n * @param {BTNKey} a - The parameter \"a\" is of type BTNKey.\n * @param {BTNKey} b - The parameter \"b\" in the above code represents a BTNKey.\n * @returns a value of type CP (ComparisonResult). The possible return values are CP.gt (greater\n * than), CP.lt (less than), or CP.eq (equal).\n */\n protected _compare(a: BTNKey, b: BTNKey): CP {\n const compared = this._comparator(a, b);\n if (compared > 0) return CP.gt;\n else if (compared < 0) return CP.lt;\n else return CP.eq;\n }\n\n // --- end additional functions\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport {getMSB} from '../../utils';\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 get freqMap(): Record<number, number> {\n return this._freqMap;\n }\n\n protected _msb: number;\n\n get msb(): number {\n return this._msb;\n }\n\n protected _negativeCount: number;\n\n get negativeCount(): number {\n return this._negativeCount;\n }\n\n get freq(): number {\n return this._freq;\n }\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 Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n\nimport type {SegmentTreeNodeVal} from '../../types';\n\nexport class SegmentTreeNode {\n start = 0;\n end = 0;\n value: SegmentTreeNodeVal | null = null;\n sum = 0;\n left: SegmentTreeNode | null = null;\n right: SegmentTreeNode | null = null;\n\n constructor(start: number, end: number, sum: number, value?: SegmentTreeNodeVal | null) {\n this.start = start;\n this.end = end;\n this.sum = sum;\n this.value = value || null;\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 = null;\n this._values = [];\n }\n }\n\n protected _values: number[] = [];\n\n get values(): number[] {\n return this._values;\n }\n\n protected _start = 0;\n\n get start(): number {\n return this._start;\n }\n\n protected _end: number;\n\n get end(): number {\n return this._end;\n }\n\n protected _root: SegmentTreeNode | null;\n\n get root(): SegmentTreeNode | null {\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 || null;\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 || null;\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 Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport {BST, BSTNode} from './bst';\nimport type {AVLTreeNodeNested, AVLTreeOptions, BinaryTreeDeletedResult, BTNKey} from '../../types';\nimport {BTNCallback} from '../../types';\nimport {IBinaryTree} from '../../interfaces';\n\nexport class AVLTreeNode<V = any, N extends AVLTreeNode<V, N> = AVLTreeNodeNested<V>> extends BSTNode<V, N> {\n height: number;\n\n constructor(key: BTNKey, value?: V) {\n super(key, value);\n this.height = 0;\n }\n}\n\nexport class AVLTree<V = any, N extends AVLTreeNode<V, N> = AVLTreeNode<V, AVLTreeNodeNested<V>>>\n extends BST<V, N>\n implements IBinaryTree<V, N>\n{\n /**\n * This is a constructor function for an AVL tree data structure in TypeScript.\n * @param {AVLTreeOptions} [options] - The `options` parameter is an optional object that can be passed to the\n * constructor of the AVLTree class. It allows you to customize the behavior of the AVL tree by providing different\n * options.\n */\n constructor(options?: AVLTreeOptions) {\n super(options);\n }\n\n /**\n * The function creates a new AVL tree node with the specified key and value.\n * @param {BTNKey} key - The key parameter is the key value that will be associated with\n * the new node. It is used to determine the position of the node in the binary search tree.\n * @param [value] - The parameter `value` is an optional value that can be assigned to the node. It is of\n * type `V`, which means it can be any value that is assignable to the `value` property of the\n * node type `N`.\n * @returns a new AVLTreeNode object with the specified key and value.\n */\n override createNode(key: BTNKey, value?: V): N {\n return new AVLTreeNode<V, N>(key, value) as N;\n }\n\n /**\n * The function overrides the add method of a binary tree node and balances the tree after inserting\n * a new node.\n * @param {BTNKey | N | undefined} keyOrNode - The `keyOrNode` parameter can accept either a\n * `BTNKey` or a `N` (which represents a node in the binary tree) or `null`.\n * @param [value] - The `value` parameter is the value that you want to assign to the new node that you\n * are adding to the binary search tree.\n * @returns The method is returning the inserted node (`N`), `null`, or `undefined`.\n */\n override add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | undefined {\n if (keyOrNode === null) return undefined;\n const inserted = super.add(keyOrNode, value);\n if (inserted) this._balancePath(inserted);\n return inserted;\n }\n\n /**\n * The function overrides the delete method of a binary tree and balances the tree after deleting a\n * node if necessary.\n * @param {ReturnType<C>} identifier - The `identifier` parameter is either a\n * `BTNKey` or a generic type `N`. It represents the property of the node that we are\n * searching for. It can be a specific key value or any other property of the node.\n * @param callback - The `callback` parameter is a function that takes a node as input and returns a\n * value. This value is compared with the `identifier` parameter to determine if the node should be\n * included in the result. The `callback` parameter has a default value of\n * `this.defaultOneParamCallback`\n * @returns The method is returning an array of `BinaryTreeDeletedResult<N>` objects.\n */\n override delete<C extends BTNCallback<N>>(\n identifier: ReturnType<C>,\n callback: C = this.defaultOneParamCallback as C\n ): BinaryTreeDeletedResult<N>[] {\n if ((identifier as any) instanceof AVLTreeNode) callback = (node => node) as C;\n const deletedResults = super.delete(identifier, callback);\n for (const {needBalanced} of deletedResults) {\n if (needBalanced) {\n this._balancePath(needBalanced);\n }\n }\n return deletedResults;\n }\n\n /**\n * The function swaps the key, value, and height properties between two nodes in a binary tree.\n * @param {N} srcNode - The `srcNode` parameter represents the source node that needs to be swapped\n * with the `destNode`.\n * @param {N} destNode - The `destNode` parameter represents the destination node where the values\n * from the source node (`srcNode`) will be swapped to.\n * @returns The method is returning the `destNode` after swapping its properties with the `srcNode`.\n */\n protected override _swap(srcNode: N, destNode: N): N {\n const {key, value, height} = destNode;\n const tempNode = this.createNode(key, value);\n\n if (tempNode) {\n tempNode.height = height;\n\n destNode.key = srcNode.key;\n destNode.value = srcNode.value;\n destNode.height = srcNode.height;\n\n srcNode.key = tempNode.key;\n srcNode.value = tempNode.value;\n srcNode.height = tempNode.height;\n }\n\n return destNode;\n }\n\n /**\n * The function calculates the balance factor of a node in a binary tree.\n * @param {N} node - The parameter \"node\" represents a node in a 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: N): 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 * 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 {N} node - The parameter \"node\" represents a node in a binary tree data structure.\n */\n protected _updateHeight(node: N): 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 * 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 {N} node - The `node` parameter in the `_balancePath` function represents the node in the\n * AVL tree that needs to be balanced.\n */\n protected _balancePath(node: N): void {\n const path = this.getPathToRoot(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 // 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 * The function `_balanceLL` performs a left-left rotation to balance a binary tree.\n * @param {N} A - A is a node in a binary tree.\n */\n protected _balanceLL(A: N): void {\n const parentOfA = A.parent;\n const B = A.left;\n 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 * The `_balanceLR` function performs a left-right rotation to balance a binary tree.\n * @param {N} A - A is a node in a binary tree.\n */\n protected _balanceLR(A: N): 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) A.parent = C;\n if (B) B.parent = C;\n\n if (C) {\n if (C.left) {\n 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 B && this._updateHeight(B);\n C && this._updateHeight(C);\n }\n\n /**\n * The function `_balanceRR` performs a right-right rotation to balance a binary tree.\n * @param {N} A - A is a node in a binary tree.\n */\n protected _balanceRR(A: N): void {\n const parentOfA = A.parent;\n const B = A.right;\n 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 B && this._updateHeight(B);\n }\n\n /**\n * The function `_balanceRL` performs a right-left rotation to balance a binary tree.\n * @param {N} A - A is a node in a binary tree.\n */\n protected _balanceRL(A: N): 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 A.parent = C;\n if (B) B.parent = C;\n\n if (C) {\n if (C.left) {\n C.left.parent = A;\n }\n if (C.right) {\n 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 B && this._updateHeight(B);\n C && this._updateHeight(C);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n\nimport {\n BinaryTreeDeletedResult,\n BTNCallback,\n BTNKey,\n IterationType,\n RBTNColor,\n RBTreeNodeNested,\n RBTreeOptions\n} from '../../types';\nimport {BST, BSTNode} from \"./bst\";\nimport {IBinaryTree} from \"../../interfaces\";\nimport {BinaryTreeNode} from \"./binary-tree\";\n\nexport class RBTreeNode<V = any, N extends RBTreeNode<V, N> = RBTreeNodeNested<V>> extends BSTNode<V, N> {\n color: RBTNColor;\n constructor(key: BTNKey, value?: V, color: RBTNColor = RBTNColor.BLACK) {\n super(key, value);\n this.color = color;\n }\n}\n\n/**\n * 1. Each node is either red or black.\n * 2. The root node is always black.\n * 3. Leaf nodes are typically NIL nodes and are considered black.\n * 4. Red nodes must have black children.\n * 5. Black balance: Every path from any node to each of its leaf nodes contains the same number of black nodes.\n */\nexport class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RBTreeNodeNested<V>>>\n extends BST<V, N>\n implements IBinaryTree<V, N>\n{\n\n constructor(options?: RBTreeOptions) {\n super(options);\n this._root = this.NIL;\n }\n\n protected _root: N;\n\n get root(): N {\n return this._root;\n }\n\n protected _size: number = 0;\n\n get size(): number {\n return this._size;\n }\n\n NIL: N = new RBTreeNode<V>(NaN) as unknown as N;\n\n override add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | undefined {\n let node: N;\n if (typeof keyOrNode === 'number') {\n node = this.createNode(keyOrNode, value, RBTNColor.RED);\n } else if(keyOrNode instanceof RBTreeNode) {\n node = keyOrNode;\n } else if (keyOrNode === null) {\n return;\n } else if (keyOrNode === undefined) {\n return;\n } else {\n return;\n }\n\n node.left = this.NIL;\n node.right = this.NIL;\n\n let y: N | undefined = undefined;\n let x: N | undefined = this.root;\n\n while (x !== this.NIL) {\n y = x;\n if (x && node.key < x.key) {\n x = x.left;\n } else {\n x = x?.right;\n }\n }\n\n node.parent = y;\n if (y === undefined) {\n this._setRoot(node);\n } else if (node.key < y.key) {\n y.left = node;\n } else {\n y.right = node;\n }\n\n if (node.parent === undefined) {\n node.color = RBTNColor.BLACK;\n this._size++;\n return;\n }\n\n if (node.parent.parent === undefined) {\n this._size++;\n return;\n }\n\n this._fixInsert(node);\n this._size++;\n }\n\n override createNode(key: BTNKey, value?: V, color: RBTNColor = RBTNColor.BLACK): N {\n return new RBTreeNode<V, N>(key, value, color) as N;\n }\n\n\n delete<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | null | undefined,\n callback: C = this.defaultOneParamCallback as C\n ): BinaryTreeDeletedResult<N>[] {\n const ans: BinaryTreeDeletedResult<N>[] = [];\n if (identifier === null) return ans;\n const helper = (node: N | undefined): void => {\n let z: N = this.NIL;\n let x: N | undefined, y: N;\n while (node !== this.NIL) {\n if (node && callback(node) === identifier) {\n z = node;\n }\n\n if (node && identifier && callback(node) <= identifier) {\n node = node.right;\n } else {\n node = node?.left;\n }\n }\n\n if (z === this.NIL) {\n this._size--;\n return;\n }\n\n y = z;\n let yOriginalColor: number = y.color;\n if (z.left === this.NIL) {\n x = z.right;\n this._rbTransplant(z, z.right!);\n } else if (z.right === this.NIL) {\n x = z.left;\n this._rbTransplant(z, z.left!);\n } else {\n y = this.getLeftMost(z.right);\n yOriginalColor = y.color;\n x = y.right;\n if (y.parent === z) {\n x!.parent = y;\n } else {\n this._rbTransplant(y, y.right!);\n y.right = z.right;\n y.right!.parent = y;\n }\n\n this._rbTransplant(z, y);\n y.left = z.left;\n y.left!.parent = y;\n y.color = z.color;\n }\n if (yOriginalColor === RBTNColor.BLACK) {\n this._fixDelete(x!);\n }\n this._size--;\n };\n helper(this.root);\n // TODO\n return ans;\n }\n\n isNode(node: N | undefined): node is N {\n return node !== this.NIL && node !== undefined;\n }\n\n getNode<C extends BTNCallback<N, BTNKey>>(\n identifier: BTNKey,\n callback?: C,\n beginRoot?: N | undefined,\n iterationType?: IterationType\n ): N | undefined;\n\n getNode<C extends BTNCallback<N, N>>(\n identifier: N | undefined,\n callback?: C,\n beginRoot?: N | undefined,\n iterationType?: IterationType\n ): N | undefined;\n\n getNode<C extends BTNCallback<N>>(\n identifier: ReturnType<C>,\n callback: C,\n beginRoot?: N | undefined,\n iterationType?: IterationType\n ): N | undefined;\n\n /**\n * The function `get` returns the first node in a binary tree that matches the given property or key.\n * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of\n * the node that you want to find in the binary tree. It can be either a `BTNKey` or `N`\n * type.\n * @param callback - The `callback` parameter is a function that is used to determine whether a node\n * matches the desired criteria. It takes a node as input and returns a boolean value indicating\n * whether the node matches the criteria or not. The default callback function\n * (`this.defaultOneParamCallback`) is used if no callback function is\n * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies\n * the root node from which the search should begin.\n * @param iterationType - The `iterationType` parameter specifies the type of iteration to be\n * performed when searching for a node in the binary tree. It can have one of the following values:\n * @returns either the found node (of type N) or null if no node is found.\n */\n getNode<C extends BTNCallback<N>>(\n identifier: ReturnType<C> | undefined,\n callback: C = this.defaultOneParamCallback as C,\n beginRoot = this.root,\n iterationType = this.iterationType\n ): N | null | undefined {\n if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;\n\n return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;\n }\n\n /**\n * The function returns the leftmost node in a red-black tree.\n * @param {RBTreeNode} node - The parameter \"node\" is of type RBTreeNode, which represents a node in\n * a Red-Black Tree.\n * @returns The leftmost node in the given RBTreeNode.\n */\n getLeftMost(node: N = this.root): N {\n while (node.left !== undefined && node.left !== this.NIL) {\n node = node.left;\n }\n return node;\n }\n\n /**\n * The function returns the rightmost node in a red-black tree.\n * @param {RBTreeNode} node - The parameter \"node\" is of type RBTreeNode.\n * @returns the rightmost node in a red-black tree.\n */\n getRightMost(node: N): N {\n while (node.right !== undefined && node.right !== this.NIL) {\n node = node.right;\n }\n return node;\n }\n\n /**\n * The function returns the successor of a given node in a red-black tree.\n * @param {RBTreeNode} x - RBTreeNode - The node for which we want to find the successor.\n * @returns the successor of the given RBTreeNode.\n */\n getSuccessor(x: N): N | undefined {\n if (x.right !== this.NIL) {\n return this.getLeftMost(x.right);\n }\n\n let y: N | undefined = x.parent;\n while (y !== this.NIL && y !== undefined && x === y.right) {\n x = y;\n y = y.parent;\n }\n return y;\n }\n\n /**\n * The function returns the predecessor of a given node in a red-black tree.\n * @param {RBTreeNode} x - The parameter `x` is of type `RBTreeNode`, which represents a node in a\n * Red-Black Tree.\n * @returns the predecessor of the given RBTreeNode 'x'.\n */\n getPredecessor(x: N): N {\n if (x.left !== this.NIL) {\n return this.getRightMost(x.left!);\n }\n\n let y: N | undefined = x.parent;\n while (y !== this.NIL && x === y!.left) {\n x = y!;\n y = y!.parent;\n }\n\n return y!;\n }\n\n override clear() {\n this._root = this.NIL;\n this._size = 0;\n }\n\n protected override _setRoot(v: N) {\n if (v) {\n v.parent = undefined;\n }\n this._root = v;\n }\n\n /**\n * The function performs a left rotation on a red-black tree node.\n * @param {RBTreeNode} x - The parameter `x` is a RBTreeNode object.\n */\n protected _leftRotate(x: N): void {\n if (x.right) {\n const y: N = x.right;\n x.right = y.left;\n if (y.left !== this.NIL) {\n if (y.left) y.left.parent = x;\n }\n y.parent = x.parent;\n if (x.parent === undefined) {\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 y.left = x;\n x.parent = y;\n }\n }\n\n /**\n * The function performs a right rotation on a red-black tree node.\n * @param {RBTreeNode} x - x is a RBTreeNode, which represents the node that needs to be right\n * rotated.\n */\n protected _rightRotate(x: N): void {\n if (x.left) {\n const y: N = x.left;\n x.left = y.right;\n if (y.right !== this.NIL) {\n if (y.right) y.right.parent = x;\n }\n y.parent = x.parent;\n if (x.parent === undefined) {\n this._setRoot(y);\n } else if (x === x.parent.right) {\n x.parent.right = y;\n } else {\n x.parent.left = y;\n }\n y.right = x;\n x.parent = y;\n }\n }\n\n /**\n * The _fixDelete function is used to rebalance the Red-Black Tree after a node deletion.\n * @param {RBTreeNode} x - The parameter `x` is of type `RBTreeNode`, which represents a node in a\n * red-black tree.\n */\n protected _fixDelete(x: N): void {\n let s: N | undefined;\n while (x !== this.root && x.color === RBTNColor.BLACK) {\n if (x.parent && x === x.parent.left) {\n s = x.parent.right!;\n if (s.color === 1) {\n s.color = RBTNColor.BLACK;\n x.parent.color = RBTNColor.RED;\n this._leftRotate(x.parent);\n s = x.parent.right!;\n }\n\n if (s.left !== undefined && s.left.color === RBTNColor.BLACK && s.right && s.right.color === RBTNColor.BLACK) {\n s.color = RBTNColor.RED;\n x = x.parent;\n } else {\n if (s.right && s.right.color === RBTNColor.BLACK) {\n if (s.left) s.left.color = RBTNColor.BLACK;\n s.color = RBTNColor.RED;\n this._rightRotate(s);\n s = x.parent.right;\n }\n\n if (s) s.color = x.parent.color;\n x.parent.color = RBTNColor.BLACK;\n if (s && s.right) s.right.color = RBTNColor.BLACK;\n this._leftRotate(x.parent);\n x = this.root;\n }\n } else {\n s = x.parent!.left!;\n if (s.color === 1) {\n s.color = RBTNColor.BLACK;\n x.parent!.color = RBTNColor.RED;\n this._rightRotate(x.parent!);\n s = x.parent!.left;\n }\n\n if (s && s.right && s.right.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {\n s.color = RBTNColor.RED;\n x = x.parent!;\n } else {\n if (s && s.left && s.left.color === RBTNColor.BLACK) {\n if (s.right) s.right.color = RBTNColor.BLACK;\n s.color = RBTNColor.RED;\n this._leftRotate(s);\n s = x.parent!.left;\n }\n\n if (s) s.color = x.parent!.color;\n x.parent!.color = RBTNColor.BLACK;\n if (s && s.left) s.left.color = RBTNColor.BLACK;\n this._rightRotate(x.parent!);\n x = this.root;\n }\n }\n }\n x.color = RBTNColor.BLACK;\n }\n\n /**\n * The function `_rbTransplant` replaces one node in a red-black tree with another node.\n * @param {RBTreeNode} u - The parameter \"u\" represents a RBTreeNode object.\n * @param {RBTreeNode} v - The parameter \"v\" is a RBTreeNode object.\n */\n protected _rbTransplant(u: N, v: N): void {\n if (u.parent === undefined) {\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 v.parent = u.parent;\n }\n\n /**\n * The `_fixInsert` function is used to fix the red-black tree after an insertion operation.\n * @param {RBTreeNode} k - The parameter `k` is a RBTreeNode object, which represents a node in a\n * red-black tree.\n */\n protected _fixInsert(k: N): void {\n let u: N | undefined;\n while (k.parent && k.parent.color === 1) {\n if (k.parent.parent && k.parent === k.parent.parent.right) {\n u = k.parent.parent.left;\n if (u && u.color === 1) {\n u.color = RBTNColor.BLACK;\n k.parent.color = RBTNColor.BLACK;\n k.parent.parent.color = RBTNColor.RED;\n k = k.parent.parent;\n } else {\n if (k === k.parent.left) {\n k = k.parent;\n this._rightRotate(k);\n }\n\n k.parent!.color = RBTNColor.BLACK;\n k.parent!.parent!.color = RBTNColor.RED;\n this._leftRotate(k.parent!.parent!);\n }\n } else {\n u = k.parent.parent!.right;\n\n if (u && u.color === 1) {\n u.color = RBTNColor.BLACK;\n k.parent.color = RBTNColor.BLACK;\n k.parent.parent!.color = RBTNColor.RED;\n k = k.parent.parent!;\n } else {\n if (k === k.parent.right) {\n k = k.parent;\n this._leftRotate(k);\n }\n\n k.parent!.color = RBTNColor.BLACK;\n k.parent!.parent!.color = RBTNColor.RED;\n this._rightRotate(k.parent!.parent!);\n }\n }\n if (k === this.root) {\n break;\n }\n }\n this.root.color = RBTNColor.BLACK;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport type {BTNKey, TreeMultimapNodeNested, TreeMultimapOptions} from '../../types';\nimport {BinaryTreeDeletedResult, BTNCallback, CP, FamilyPosition, IterationType} from '../../types';\nimport {IBinaryTree} from '../../interfaces';\nimport {AVLTree, AVLTreeNode} from './avl-tree';\n\nexport class TreeMultimapNode<\n V = any,\n N extends TreeMultimapNode<V, N> = TreeMultimapNodeNested<V>\n> extends AVLTreeNode<V, N> {\n count: number;\n\n /**\n * The constructor function initializes a BinaryTreeNode object with a key, value, and count.\n * @param {BTNKey} key - The `key` parameter is of type `BTNKey` 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: BTNKey, value?: V, count = 1) {\n super(key, value);\n this.count = count;\n }\n}\n\n/**\n * The only distinction between a TreeMultimap and a AVLTree lies in the ability of the former to store duplicate nodes through the utilization of counters.\n */\nexport class TreeMultimap<V = any, N extends TreeMultimapNode<V, N> = TreeMultimapNode<V, TreeMultimapNodeNested<V>>>\n extends AVLTree<V, N>\n implements IBinaryTree<V, N>\n{\n /**\n * The constructor function for a TreeMultimap class in TypeScript, which extends another class and sets an option to\n * merge duplicated values.\n * @param {TreeMultimapOptions} [options] - An optional object that contains additional configuration options for the\n * TreeMultimap.\n */\n constructor(options?: TreeMultimapOptions) {\n super(options);\n }\n\n private _count = 0;\n\n get count(): number {\n return this._count;\n }\n\n /**\n * The function creates a new BSTNode with the given key, value, and count.\n * @param {BTNKey} key - The key parameter is the unique identifier for the binary tree node. It is used to\n * distinguish one node from another in the tree.\n * @param {N} value - The `value` parameter represents the value that will be stored in the binary search tree node.\n * @param {number} [count] - The \"count\" parameter is an optional parameter of type number. It represents the number of\n * occurrences of the value in the binary search tree node. If not provided, the count will default to 1.\n * @returns A new instance of the BSTNode class with the specified key, value, and count (if provided).\n */\n override createNode(key: BTNKey, value?: V, count?: number): N {\n return new TreeMultimapNode(key, value, count) as N;\n }\n\n /**\n * The `add` function adds a new node to a binary search tree, updating the count if the key already\n * exists, and balancing the tree if necessary.\n * @param {BTNKey | N | undefined} keyOrNode - The `keyOrNode` parameter can be either a\n * `BTNKey` (which represents the key of the node to be added), a `N` (which represents a\n * node to be added), or `undefined` (which represents a undefined node).\n * @param [value] - The `value` parameter represents the value associated with the key that is being\n * added to the binary tree.\n * @param [count=1] - The `count` parameter represents the number of occurrences of the key/value\n * pair that will be added to the binary tree. It has a default value of 1, which means that if no\n * count is specified, the default count will be 1.\n * @returns The function `add` returns a value of type `N | undefined | undefined`.\n */\n override add(keyOrNode: BTNKey | N | null | undefined, value?: V, count = 1): N | undefined {\n if(keyOrNode === null) return undefined;\n let inserted: N | undefined = undefined,\n newNode: N | undefined;\n if (keyOrNode instanceof TreeMultimapNode) {\n newNode = this.createNode(keyOrNode.key, keyOrNode.value, keyOrNode.count);\n } else if (keyOrNode === undefined) {\n newNode = undefined;\n } else {\n newNode = this.createNode(keyOrNode, value, count);\n }\n if (!this.root) {\n this._setRoot(newNode);\n this._size = this.size + 1;\n newNode && this._setCount(this.count + newNode.count);\n inserted = this.root;\n } else {\n let cur = this.root;\n let traversing = true;\n while (traversing) {\n if (cur) {\n if (newNode) {\n if (this._compare(cur.key, newNode.key) === CP.eq) {\n cur.value = newNode.value;\n cur.count += newNode.count;\n this._setCount(this.count + newNode.count);\n traversing = false;\n inserted = cur;\n } else if (this._compare(cur.key, newNode.key) === CP.gt) {\n // Traverse left of the node\n if (cur.left === undefined) {\n //Add to the left of the current node\n cur.left = newNode;\n this._size = this.size + 1;\n this._setCount(this.count + newNode.count);\n\n traversing = false;\n inserted = cur.left;\n } else {\n //Traverse the left of the current node\n if (cur.left) cur = cur.left;\n }\n } else if (this._compare(cur.key, newNode.key) === CP.lt) {\n // Traverse right of the node\n if (cur.right === undefined) {\n //Add to the right of the current node\n cur.right = newNode;\n this._size = this.size + 1;\n this._setCount(this.count + newNode.count);\n\n traversing = false;\n inserted = cur.right;\n } else {\n //Traverse the left of the current node\n if (cur.right) cur = cur.right;\n }\n }\n } else {\n // TODO may need to support undefined inserted\n }\n } else {\n traversing = false;\n }\n }\n }\n if (inserted) this._balancePath(inserted);\n return inserted;\n }\n\n /**\n * The function adds a new node to a binary tree if there is an available slot in the parent node.\n * @param {N | undefined} newNode - The `newNode` parameter represents the node that needs to be added to\n * the tree. It can be either a node object (`N`) or `undefined`.\n * @param {N} parent - The `parent` parameter represents the parent node to which the new node will\n * be added as a child.\n * @returns The method `_addTo` returns either the `parent.left`, `parent.right`, or `undefined`.\n */\n override _addTo(newNode: N | undefined, parent: N): N | undefined {\n if (parent) {\n if (parent.left === undefined) {\n parent.left = newNode;\n if (newNode !== undefined) {\n this._size = this.size + 1;\n this._setCount(this.count + newNode.count);\n }\n\n return parent.left;\n } else if (parent.right === undefined) {\n parent.right = newNode;\n if (newNode !== undefined) {\n this._size = this.size + 1;\n this._setCount(this.count + newNode.count);\n }\n return parent.right;\n } else {\n return;\n }\n } else {\n return;\n }\n }\n\n /**\n * The `addMany` function adds multiple keys or nodes to a TreeMultimap and returns an array of the\n * inserted nodes.\n * @param {(BTNKey | undefined)[] | (N | undefined)[]} keysOrNodes - An array of keys or nodes to be\n * added to the multiset. Each element can be either a BTNKey or a TreeMultimapNode.\n * @param {V[]} [data] - The `data` parameter is an optional array of values that correspond\n * to the keys or nodes being added to the multiset. It is used to associate additional data with\n * each key or node.\n * @returns The function `addMany` returns an array of `N`, `undefined`, or `undefined` values.\n */\n override addMany(keysOrNodes: (BTNKey | undefined)[] | (N | undefined)[], data?: V[]): (N | undefined)[] {\n const inserted: (N | undefined | undefined)[] = [];\n\n for (let i = 0; i < keysOrNodes.length; i++) {\n const keyOrNode = keysOrNodes[i];\n\n if (keyOrNode instanceof TreeMultimapNode) {\n inserted.push(this.add(keyOrNode.key, keyOrNode.value, keyOrNode.count));\n continue;\n }\n\n if (keyOrNode === undefined) {\n inserted.push(this.add(NaN, undefined, 0));\n continue;\n }\n\n inserted.push(this.add(keyOrNode, data?.[i], 1));\n }\n return inserted;\n }\n\n /**\n * The `perfectlyBalance` function in TypeScript takes a sorted array of nodes and builds a balanced\n * binary search tree using either a recursive or iterative approach.\n * @param iterationType - The `iterationType` parameter is an optional parameter that specifies the\n * type of iteration to use when building a balanced binary search tree. It can have two possible\n * values:\n * @returns a boolean value.\n */\n override perfectlyBalance(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 === 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 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 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 * The `delete` function in a binary search tree deletes a node from the tree and returns the deleted\n * node along with the parent node that needs to be balanced.\n * @param {ReturnType<C>} identifier - The `identifier` parameter is either a\n * `BTNKey` or a generic type `N`. It represents the property of the node that we are\n * searching for. It can be a specific key value or any other property of the node.\n * @param callback - The `callback` parameter is a function that takes a node as input and returns a\n * value. This value is compared with the `identifier` parameter to determine if the node should be\n * included in the result. The `callback` parameter has a default value of\n * `this.defaultOneParamCallback`\n * @param [ignoreCount=false] - A boolean flag indicating whether to ignore the count of the node\n * being deleted. If set to true, the count of the node will not be considered and the node will be\n * deleted regardless of its count. If set to false (default), the count of the node will be\n * decremented by 1 and\n * @returns The method `delete` returns an array of `BinaryTreeDeletedResult<N>` objects.\n */\n override delete<C extends BTNCallback<N>>(\n identifier: ReturnType<C>,\n callback: C = this.defaultOneParamCallback as C,\n ignoreCount = false\n ): BinaryTreeDeletedResult<N>[] {\n const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];\n if (!this.root) return bstDeletedResult;\n\n const curr: N | undefined = this.getNode(identifier, callback) ?? undefined;\n if (!curr) return bstDeletedResult;\n\n const parent: N | undefined = curr?.parent ? curr.parent : undefined;\n let needBalanced: N | undefined = undefined,\n orgCurrent = curr;\n\n if (curr.count > 1 && !ignoreCount) {\n curr.count--;\n this._setCount(this.count - 1);\n } else {\n if (!curr.left) {\n if (!parent) {\n if (curr.right !== undefined) this._setRoot(curr.right);\n } else {\n const {familyPosition: fp} = curr;\n if (fp === FamilyPosition.LEFT || fp === FamilyPosition.ROOT_LEFT) {\n parent.left = curr.right;\n } else if (fp === FamilyPosition.RIGHT || fp === FamilyPosition.ROOT_RIGHT) {\n parent.right = curr.right;\n }\n needBalanced = parent;\n }\n } else {\n const leftSubTreeRightMost = curr.left ? this.getRightMost(curr.left) : undefined;\n if (leftSubTreeRightMost) {\n const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;\n orgCurrent = this._swap(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 this._setCount(this.count - orgCurrent.count);\n }\n\n bstDeletedResult.push({deleted: orgCurrent, needBalanced});\n\n if (needBalanced) {\n this._balancePath(needBalanced);\n }\n\n return bstDeletedResult;\n }\n\n /**\n * The clear() function clears the contents of a data structure and sets the count to zero.\n */\n clear() {\n super.clear();\n this._setCount(0);\n }\n\n /**\n * The function swaps the values of two nodes in a binary tree.\n * @param {N} srcNode - The source node that needs to be swapped with the destination node.\n * @param {N} destNode - The `destNode` parameter represents the destination node where the values\n * from `srcNode` will be swapped into.\n * @returns The method is returning the `destNode` after swapping its properties with the `srcNode`.\n */\n protected override _swap(srcNode: N, destNode: N): N {\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 destNode.value = srcNode.value;\n destNode.count = srcNode.count;\n destNode.height = srcNode.height;\n\n srcNode.key = tempNode.key;\n srcNode.value = tempNode.value;\n srcNode.count = tempNode.count;\n srcNode.height = tempNode.height;\n }\n\n return destNode;\n }\n\n /**\n * The function sets the value of the \"_count\" property.\n * @param {number} v - number\n */\n protected _setCount(v: number) {\n this._count = v;\n }\n}\n","export class TreeNode<V = any> {\n key: string;\n value?: V | undefined;\n children?: TreeNode<V>[] | undefined;\n\n constructor(key: string, value?: V, children?: TreeNode<V>[]) {\n this.key = key;\n this.value = value || undefined;\n this.children = children || [];\n }\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 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","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n// todo need to be improved\nexport class MatrixNTI2D<V = any> {\n protected readonly _matrix: Array<Array<V>>;\n\n /**\n * The constructor creates a matrix with the specified number of rows and columns, and initializes all elements to a\n * given initial value or 0 if not provided.\n * @param options - An object containing the following properties:\n */\n constructor(options: {row: number; col: number; initialVal?: V}) {\n const {row, col, initialVal} = options;\n this._matrix = new Array(row).fill(undefined).map(() => new Array(col).fill(initialVal || 0));\n }\n\n /* The `toArray` method returns the matrix as a two-dimensional array. It converts the internal representation of the\n matrix, which is an array of arrays, into a format that is more commonly used in JavaScript. */\n toArray(): Array<Array<V>> {\n return this._matrix;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nexport class Vector2D {\n constructor(\n public x: number = 0,\n public y: number = 0,\n public w: number = 1 // needed for matrix multiplication\n ) {}\n\n /**\n * The function checks if the x and y values of a point are both zero.\n * @returns A boolean value indicating whether both the x and y properties of the object are equal to 0.\n */\n get isZero(): boolean {\n return this.x === 0 && this.y === 0;\n }\n\n /**\n * The above function calculates the length of a vector using the Pythagorean theorem.\n * @returns The length of a vector, calculated using the Pythagorean theorem.\n */\n get length(): number {\n return Math.sqrt(this.x * this.x + this.y * this.y);\n }\n\n /**\n * The function calculates the square of the length of a vector.\n * @returns The method is returning the sum of the squares of the x and y values.\n */\n get lengthSq(): number {\n return this.x * this.x + this.y * this.y;\n }\n\n /**\n * The \"rounded\" function returns a new Vector2D object with the x and y values rounded to the nearest whole number.\n * @returns The method is returning a new instance of the Vector2D class with the x and y values rounded to the nearest\n * whole number.\n */\n get rounded(): Vector2D {\n return new Vector2D(Math.round(this.x), Math.round(this.y));\n }\n\n /**\n * The function \"add\" takes two Vector2D objects as parameters and returns a new Vector2D object with the sum of their\n * x and y components.\n * @param {Vector2D} vector1 - The parameter `vector1` is an instance of the `Vector2D` class. It represents a\n * 2-dimensional vector with an `x` and `y` component.\n * @param {Vector2D} vector2 - The parameter \"vector2\" is of type Vector2D. It represents a 2-dimensional vector with\n * an x and y component.\n * @returns The method is returning a new instance of the Vector2D class with the x and y components of the two input\n * vectors added together.\n */\n static add(vector1: Vector2D, vector2: Vector2D): Vector2D {\n return new Vector2D(vector1.x + vector2.x, vector1.y + vector2.y);\n }\n\n /**\n * The subtract function takes two Vector2D objects as parameters and returns a new Vector2D object with the x and y\n * components subtracted.\n * @param {Vector2D} vector1 - The parameter `vector1` is an instance of the `Vector2D` class, representing a\n * 2-dimensional vector. It has properties `x` and `y` which represent the x and y components of the vector\n * respectively.\n * @param {Vector2D} vector2 - The parameter \"vector2\" is a Vector2D object. It represents the second vector that you\n * want to subtract from the first vector.\n * @returns The method is returning a new Vector2D object with the x and y components subtracted from vector1 and\n * vector2.\n */\n static subtract(vector1: Vector2D, vector2: Vector2D): Vector2D {\n return new Vector2D(vector1.x - vector2.x, vector1.y - vector2.y);\n }\n\n /**\n * The function subtracts a given value from the x and y components of a Vector2D object and returns a new Vector2D\n * object.\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D, which represents a 2-dimensional vector with\n * x and y components.\n * @param {number} value - The \"value\" parameter is a number that will be subtracted from both the x and y components\n * of the \"vector\" parameter.\n * @returns A new Vector2D object with the x and y values subtracted by the given value.\n */\n static subtractValue(vector: Vector2D, value: number): Vector2D {\n return new Vector2D(vector.x - value, vector.y - value);\n }\n\n /**\n * The function multiplies a Vector2D object by a given value.\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D, which represents a 2-dimensional vector with\n * x and y components.\n * @param {number} value - The \"value\" parameter is a number that represents the value by which the x and y components\n * of the vector will be multiplied.\n * @returns A new Vector2D object with the x and y values multiplied by the given value.\n */\n static multiply(vector: Vector2D, value: number): Vector2D {\n return new Vector2D(vector.x * value, vector.y * value);\n }\n\n /**\n * The function divides the x and y components of a Vector2D by a given value and returns a new Vector2D.\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D, which represents a 2-dimensional vector with\n * x and y components.\n * @param {number} value - The value parameter is a number that will be used to divide the x and y components of the\n * vector.\n * @returns A new instance of the Vector2D class with the x and y values divided by the given value.\n */\n static divide(vector: Vector2D, value: number): Vector2D {\n return new Vector2D(vector.x / value, vector.y / value);\n }\n\n /**\n * The function checks if two Vector2D objects are equal by comparing their x and y values.\n * @param {Vector2D} vector1 - The parameter `vector1` is of type `Vector2D`, which represents a 2-dimensional vector.\n * It has two properties: `x` and `y`, which represent the x and y components of the vector, respectively.\n * @param {Vector2D} vector2 - The parameter \"vector2\" is of type Vector2D.\n * @returns a boolean value, which indicates whether the two input vectors are equal or not.\n */\n static equals(vector1: Vector2D, vector2: Vector2D): boolean {\n return vector1.x === vector2.x && vector1.y === vector2.y;\n }\n\n /**\n * The function checks if two Vector2D objects are equal within a specified rounding factor.\n * @param {Vector2D} vector1 - The first vector to compare.\n * @param {Vector2D} vector2 - The parameter \"vector2\" is a Vector2D object, which represents a 2-dimensional vector.\n * It is used as one of the inputs for the \"equalsRounded\" function.\n * @param [roundingFactor=12] - The roundingFactor parameter is used to determine the threshold for considering two\n * vectors as equal. If the absolute difference in the x and y components of the vectors is less than the\n * roundingFactor, the vectors are considered equal.\n * @returns a boolean value.\n */\n static equalsRounded(vector1: Vector2D, vector2: Vector2D, roundingFactor = 12): boolean {\n const vector = Vector2D.abs(Vector2D.subtract(vector1, vector2));\n if (vector.x < roundingFactor && vector.y < roundingFactor) {\n return true;\n }\n\n return false;\n }\n\n /**\n * The normalize function takes a vector as input and returns a normalized version of the vector.Normalizes the vector if it matches a certain condition\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D.\n * @returns the normalized vector if its length is greater than a very small value (epsilon), otherwise it returns the\n * original vector.\n */\n static normalize(vector: Vector2D): Vector2D {\n const length = vector.length;\n if (length > 2.220446049250313e-16) {\n // Epsilon\n return Vector2D.divide(vector, length);\n }\n\n return vector;\n }\n\n /**\n * The function truncates a vector to a maximum length if it exceeds that length.Adjusts x and y so that the length of the vector does not exceed max\n * @param {Vector2D} vector - A 2D vector represented by the Vector2D class.\n * @param {number} max - The `max` parameter is a number that represents the maximum length that the `vector` should\n * have.\n * @returns either the original vector or a truncated version of the vector, depending on whether the length of the\n * vector is greater than the maximum value specified.\n */\n static truncate(vector: Vector2D, max: number): Vector2D {\n if (vector.length > max) {\n return Vector2D.multiply(Vector2D.normalize(vector), max);\n }\n\n return vector;\n }\n\n /**\n * The function returns a new Vector2D object that is perpendicular to the input vector.The vector that is perpendicular to this one\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D.\n * @returns A new Vector2D object is being returned.\n */\n static perp(vector: Vector2D): Vector2D {\n return new Vector2D(-vector.y, vector.x);\n }\n\n /**\n * The reverse function takes a Vector2D object and returns a new Vector2D object with the negated x and y values.\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D, which represents a 2-dimensional vector. It\n * has two properties: \"x\" and \"y\", which represent the x and y components of the vector, respectively.\n * @returns A new Vector2D object with the negated x and y values of the input vector. Returns the vector that is the reverse of this vector\n */\n static reverse(vector: Vector2D): Vector2D {\n return new Vector2D(-vector.x, -vector.y);\n }\n\n /**\n * The function takes a Vector2D object as input and returns a new Vector2D object with the absolute values of its x\n * and y components.\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D, which represents a 2-dimensional vector. It\n * has two properties: \"x\" and \"y\", which represent the x and y components of the vector, respectively.\n * @returns The method is returning a new Vector2D object with the absolute values of the x and y components of the\n * input vector.\n */\n static abs(vector: Vector2D): Vector2D {\n return new Vector2D(Math.abs(vector.x), Math.abs(vector.y));\n }\n\n /**\n * The dot function calculates the dot product of two 2D vectors.The dot product of v1 and v2\n * @param {Vector2D} vector1 - The parameter `vector1` represents a 2D vector with its x and y components.\n * @param {Vector2D} vector2 - The \"vector2\" parameter is a Vector2D object. It represents a two-dimensional vector\n * with an x and y component.\n * @returns The dot product of the two input vectors.\n */\n static dot(vector1: Vector2D, vector2: Vector2D): number {\n return vector1.x * vector2.x + vector1.y * vector2.y;\n }\n\n // /**\n // * Transform vectors based on the current tranformation matrices: translation, rotation and scale\n // * @param vectors The vectors to transform\n // */\n // static transform(vector: Vector2D, transformation: Matrix2D): Vector2D {\n // return Matrix2D.multiplyByVector(transformation, vector)\n // }\n\n // /**\n // * Transform vectors based on the current tranformation matrices: translation, rotation and scale\n // * @param vectors The vectors to transform\n // */\n // static transformList(vectors: Vector2D[], transformation: Matrix2D): Vector2D[] {\n // return vectors.map(vector => Matrix2D.multiplyByVector(transformation, vector))\n // }\n\n /**\n * The function calculates the distance between two points in a two-dimensional space.\n * @param {Vector2D} vector1 - The parameter `vector1` represents the first vector in 2D space, while `vector2`\n * represents the second vector. Each vector has an `x` and `y` component, which represent their respective coordinates\n * in the 2D space.\n * @param {Vector2D} vector2 - The `vector2` parameter represents the second vector in the calculation of distance. It\n * is an instance of the `Vector2D` class, which typically has properties `x` and `y` representing the coordinates of\n * the vector in a 2D space.\n * @returns The distance between vector1 and vector2.\n */\n static distance(vector1: Vector2D, vector2: Vector2D): number {\n const ySeparation = vector2.y - vector1.y;\n const xSeparation = vector2.x - vector1.x;\n return Math.sqrt(ySeparation * ySeparation + xSeparation * xSeparation);\n }\n\n /**\n * The function calculates the squared distance between two 2D vectors.\n * @param {Vector2D} vector1 - The parameter `vector1` represents the first vector, which is an instance of the\n * `Vector2D` class. It contains the x and y coordinates of the vector.\n * @param {Vector2D} vector2 - The `vector2` parameter represents the second vector in a two-dimensional space. It has\n * properties `x` and `y` which represent the coordinates of the vector.\n * @returns the square of the distance between the two input vectors.\n */\n static distanceSq(vector1: Vector2D, vector2: Vector2D): number {\n const ySeparation = vector2.y - vector1.y;\n const xSeparation = vector2.x - vector1.x;\n return ySeparation * ySeparation + xSeparation * xSeparation;\n }\n\n /**\n * The sign function determines the sign of the cross product between two 2D vectors.\n * (assuming the Y axis is pointing down, X axis to right like a Window app)\n * @param {Vector2D} vector1 - The parameter `vector1` is of type `Vector2D`, which represents a 2-dimensional vector.\n * It likely has properties `x` and `y` representing the x and y components of the vector, respectively.\n * @param {Vector2D} vector2 - The above code defines a function called \"sign\" that takes two parameters: vector1 and\n * vector2. Both vector1 and vector2 are of type Vector2D.\n * @returns either -1 or 1. Returns positive if v2 is clockwise of this vector, negative if counterclockwise\n */\n static sign(vector1: Vector2D, vector2: Vector2D): number {\n if (vector1.y * vector2.x > vector1.x * vector2.y) {\n return -1;\n }\n\n return 1;\n }\n\n /**\n * The function calculates the angle between a given vector and the negative y-axis.\n * @param {Vector2D} vector - The \"vector\" parameter is an instance of the Vector2D class, which represents a\n * 2-dimensional vector. It has two properties: \"x\" and \"y\", which represent the x and y components of the vector,\n * respectively.\n * @returns the angle between the given vector and the vector (0, -1) in radians.Returns the angle between origin and the given vector in radians\n */\n static angle(vector: Vector2D): number {\n const origin = new Vector2D(0, -1);\n const radian = Math.acos(Vector2D.dot(vector, origin) / (vector.length * origin.length));\n return Vector2D.sign(vector, origin) === 1 ? Math.PI * 2 - radian : radian;\n }\n\n /**\n * The function \"random\" generates a random Vector2D object with x and y values within the specified range.\n * @param {number} maxX - The maxX parameter represents the maximum value for the x-coordinate of the random vector.\n * @param {number} maxY - The `maxY` parameter represents the maximum value for the y-coordinate of the generated\n * random vector.\n * @returns a new instance of the Vector2D class with random x and y values.\n */\n static random(maxX: number, maxY: number): Vector2D {\n const randX = Math.floor(Math.random() * maxX - maxX / 2);\n const randY = Math.floor(Math.random() * maxY - maxY / 2);\n return new Vector2D(randX, randY);\n }\n\n /**\n * The function sets the values of x and y to zero.\n */\n zero(): void {\n this.x = 0;\n this.y = 0;\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\nimport {Vector2D} from './vector2d';\n\nexport class Matrix2D {\n protected readonly _matrix: number[][];\n\n /**\n * The constructor function initializes a Matrix2D object with either a default identity matrix, or a provided matrix\n * or Vector2D object.\n * @param {number[][] | Vector2D} [value] - The `value` parameter can be either a 2D array of numbers (`number[][]`) or\n * an instance of the `Vector2D` class.\n */\n constructor(value?: number[][] | Vector2D) {\n if (typeof value === 'undefined') {\n this._matrix = Matrix2D.identity;\n } else if (value instanceof Vector2D) {\n this._matrix = Matrix2D.identity;\n this._matrix[0][0] = value.x;\n this._matrix[1][0] = value.y;\n this._matrix[2][0] = value.w;\n } else {\n this._matrix = value;\n }\n }\n\n /**\n * The function returns a 2D array with three empty arrays.\n * @returns An empty 2-dimensional array with 3 empty arrays inside.\n */\n static get empty(): number[][] {\n return [[], [], []];\n }\n\n /**\n * The above function returns a 3x3 identity matrix.\n * @returns The method is returning a 2-dimensional array of numbers representing the identity matrix.\n */\n static get identity(): number[][] {\n return [\n [1, 0, 0],\n [0, 1, 0],\n [0, 0, 1]\n ];\n }\n\n /**\n * The function returns a two-dimensional array of numbers.\n * @returns The getter method is returning the value of the private variable `_matrix`, which is a two-dimensional\n * array of numbers.\n */\n get m(): number[][] {\n return this._matrix;\n }\n\n /**\n * The function takes two 2D matrices as input and returns their sum as a new 2D matrix.\n * @param {Matrix2D} matrix1 - Matrix2D - The first matrix to be added.\n * @param {Matrix2D} matrix2 - The parameter `matrix2` is a Matrix2D object.\n * @returns a new instance of the Matrix2D class, which is created using the result array.\n */\n static add(matrix1: Matrix2D, matrix2: Matrix2D): Matrix2D {\n const result = Matrix2D.empty;\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < 3; j++) {\n result[i][j] = matrix1.m[i][j] + matrix2.m[i][j];\n }\n }\n return new Matrix2D(result);\n }\n\n /**\n * The function subtracts two 2D matrices and returns the result as a new Matrix2D object.\n * @param {Matrix2D} matrix1 - Matrix2D - The first matrix to subtract from.\n * @param {Matrix2D} matrix2 - Matrix2D is a class representing a 2D matrix. It has a property `m` which is a 2D array\n * representing the matrix elements.\n * @returns a new instance of the Matrix2D class, which is created using the result array.\n */\n static subtract(matrix1: Matrix2D, matrix2: Matrix2D): Matrix2D {\n const result = Matrix2D.empty;\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < 3; j++) {\n result[i][j] = matrix1.m[i][j] - matrix2.m[i][j];\n }\n }\n return new Matrix2D(result);\n }\n\n /**\n * The function multiplies two 2D matrices and returns the result as a new Matrix2D object.\n * @param {Matrix2D} matrix1 - A 2D matrix represented by the Matrix2D class.\n * @param {Matrix2D} matrix2 - The parameter `matrix2` is a 2D matrix of size 3x3.\n * @returns a new instance of the Matrix2D class, created using the result array.\n */\n static multiply(matrix1: Matrix2D, matrix2: Matrix2D): Matrix2D {\n const result = Matrix2D.empty;\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < 3; j++) {\n result[i][j] = 0;\n for (let k = 0; k < 3; k++) {\n result[i][j] += matrix1.m[i][k] * matrix2.m[k][j];\n }\n }\n }\n return new Matrix2D(result);\n }\n\n /**\n * The function multiplies each element of a 2D matrix by a given value and returns the resulting matrix.\n * @param {Matrix2D} matrix - The `matrix` parameter is an instance of the `Matrix2D` class, which represents a 2D\n * matrix. It contains a property `m` that is a 2D array representing the matrix elements.\n * @param {number} value - The `value` parameter is a number that you want to multiply each element of the `matrix` by.\n * @returns a new instance of the Matrix2D class, which is created using the result array.\n */\n static multiplyByValue(matrix: Matrix2D, value: number): Matrix2D {\n const result = Matrix2D.empty;\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < 3; j++) {\n result[i][j] = matrix.m[i][j] * value;\n }\n }\n return new Matrix2D(result);\n }\n\n /**\n * The function multiplies a 2D matrix by a 2D vector and returns the result as a 2D vector.\n * @param {Matrix2D} matrix - The parameter \"matrix\" is of type Matrix2D. It represents a 2-dimensional matrix.\n * @param {Vector2D} vector - The \"vector\" parameter is a 2D vector, represented by an object of type Vector2D.\n * @returns a Vector2D.\n */\n static multiplyByVector(matrix: Matrix2D, vector: Vector2D): Vector2D {\n const resultMatrix = Matrix2D.multiply(matrix, new Matrix2D(vector));\n return resultMatrix.toVector();\n }\n\n /**\n * The function returns a 2D matrix that scales and flips a vector around the center of a given width and height.\n * @param {number} width - The width parameter represents the width of the view or the canvas. It is a number that\n * specifies the width in pixels or any other unit of measurement.\n * @param {number} height - The height parameter represents the height of the view or the canvas. It is used to\n * calculate the centerY value, which is the vertical center of the view.\n * @returns a Matrix2D object.\n */\n static view(width: number, height: number): Matrix2D {\n const scaleStep = 1; // Scale every vector * scaleStep\n const centerX = width / 2;\n const centerY = height / 2;\n const flipX = Math.cos(Math.PI); // rotate 180deg / 3.14radian around X-axis\n\n return new Matrix2D([\n [scaleStep, 0, centerX],\n [0, flipX * scaleStep, centerY],\n [0, 0, 1]\n ]);\n }\n\n /**\n * The function scales a matrix by a given factor.\n * @param {number} factor - The factor parameter is a number that represents the scaling factor by which the matrix\n * should be scaled.\n * @returns the result of multiplying a new instance of Matrix2D by the given factor.\n */\n static scale(factor: number) {\n return Matrix2D.multiplyByValue(new Matrix2D(), factor);\n }\n\n /**\n * The function \"rotate\" takes an angle in radians and returns a 2D transformation matrix for rotating objects.\n * @param {number} radians - The \"radians\" parameter is the angle in radians by which you want to rotate an object.\n * @returns The code is returning a new instance of a Matrix2D object.\n */\n static rotate(radians: number) {\n const cos = Math.cos(radians);\n const sin = Math.sin(radians);\n\n return new Matrix2D([\n [cos, -sin, 0],\n [sin, cos, 0],\n [0, 0, 1]\n ]);\n }\n\n /**\n * The translate function takes a 2D vector and returns a 2D matrix that represents a translation transformation.\n * @param {Vector2D} vector - The parameter \"vector\" is of type Vector2D. It represents a 2D vector with components x\n * and y, and an optional w component.\n * @returns The method is returning a new instance of the Matrix2D class.\n */\n static translate(vector: Vector2D): Matrix2D {\n return new Matrix2D([\n [1, 0, vector.x],\n [0, 1, vector.y],\n [0, 0, vector.w]\n ]);\n }\n\n /**\n * The function \"toVector\" returns a new Vector2D object with the values from the first and second elements of the\n * _matrix array.\n * @returns A new instance of the Vector2D class is being returned. The values of the returned vector are taken from\n * the first column of the matrix.\n */\n toVector(): Vector2D {\n return new Vector2D(this._matrix[0][0], this._matrix[1][0]);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler 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\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 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 this.onMove && this.onMove(this._cur);\n }\n}\n","/**\n * data-structure-typed\n *\n * @author Tyler Zeng\n * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>\n * @license MIT License\n */\n\n/**\n * TrieNode represents a node in the Trie data structure. It holds a character key, a map of children nodes,\n * and a flag indicating whether it's the end of a word.\n */\nexport class TrieNode {\n key: string;\n children: Map<string, TrieNode>;\n isEnd: boolean;\n\n constructor(key: string) {\n this.key = key;\n this.isEnd = false;\n this.children = new Map<string, TrieNode>();\n }\n}\n\n/**\n * Trie represents a Trie data structure. It provides basic Trie operations and additional methods.\n */\nexport class Trie {\n constructor(words?: string[], caseSensitive = true) {\n this._root = new TrieNode('');\n this._caseSensitive = caseSensitive;\n if (words) {\n for (const i of words) {\n this.add(i);\n }\n }\n }\n\n protected _caseSensitive: boolean;\n\n get caseSensitive(): boolean {\n return this._caseSensitive;\n }\n\n protected _root: TrieNode;\n\n get root() {\n return this._root;\n }\n\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 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 cur.isEnd = true;\n return true;\n }\n\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 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 * 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) {\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 return isDeleted;\n }\n\n getHeight() {\n const beginRoot = this.root;\n let maxDepth = 0;\n if (beginRoot) {\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(beginRoot, 0);\n }\n return maxDepth;\n }\n\n // --- start additional methods ---\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 * 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 * 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 * 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 * 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) startNode = nodeC;\n }\n }\n\n if (isAllWhenEmptyPrefix || startNode !== this.root) dfs(startNode, prefix);\n\n return words;\n }\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 // --- end additional methods ---\n}\n"],"mappings":"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","names":["src_exports","__export","AVLTree","AVLTreeNode","AbstractEdge","AbstractGraph","AbstractVertex","ArrayDeque","BST","BSTNode","BinaryIndexedTree","BinaryTree","BinaryTreeNode","CP","Character","CoordinateMap","CoordinateSet","Deque","DirectedEdge","DirectedGraph","DirectedVertex","DoublyLinkedList","DoublyLinkedListNode","FamilyPosition","FibonacciHeap","FibonacciHeapNode","HashMap","HashTable","HashTableNode","Heap","IterationType","LinkedListQueue","MapEdge","MapGraph","MapVertex","Matrix2D","MatrixNTI2D","MaxHeap","MaxPriorityQueue","MinHeap","MinPriorityQueue","Navigator","ObjectDeque","PriorityQueue","Queue","RBTNColor","RBTreeNode","RedBlackTree","SegmentTree","SegmentTreeNode","SinglyLinkedList","SinglyLinkedListNode","SkipList","SkipListNode","Stack","THUNK_SYMBOL","TopologicalProperty","TreeMap","TreeMultimap","TreeMultimapNode","TreeNode","TreeSet","Trie","TrieNode","UndirectedEdge","UndirectedGraph","UndirectedVertex","Vector2D","arrayRemove","getMSB","isThunk","toThunk","trampoline","trampolineAsync","uuidV4","HashTableNode","key","value","HashTable","_HashTable","capacity","hashFn","index","newNode","currentNode","prevNode","keyString","hash","i","charCode","A","M","char","newCapacity","newBuckets","bucket","newIndex","currentNewNode","CoordinateMap","joint","key","value","CoordinateSet","joint","value","TreeMap","TreeSet","HashMap","initialCapacity","loadFactor","hashFn","key","strKey","hash","i","value","index","k","v","bucket","newCapacity","newTable","newIndex","SinglyLinkedListNode","value","SinglyLinkedList","_SinglyLinkedList","data","singlyLinkedList","item","newNode","current","removedNode","index","i","prevNode","valueOrNode","prev","array","next","callback","existingValueOrNode","newValue","existingValue","existingNode","count","mappedList","filteredList","initialValue","accumulator","DoublyLinkedListNode","value","DoublyLinkedList","_DoublyLinkedList","data","doublyLinkedList","item","newNode","removedNode","index","current","i","prevNode","nextNode","existingValueOrNode","newValue","existingNode","valOrNode","node","array","callback","next","mappedList","filteredList","initialValue","accumulator","SkipListNode","key","value","level","SkipList","maxLevel","probability","newNode","update","current","i","firstNode","nextNode","lastLess","Stack","_Stack","elements","element","LinkedListQueue","SinglyLinkedList","value","Queue","_Queue","elements","element","first","index","item","Deque","DoublyLinkedList","ObjectDeque","capacity","value","mid","index","ArrayDeque","uuidV4","c","r","arrayRemove","array","predicate","i","len","result","value","THUNK_SYMBOL","isThunk","fnOrValue","toThunk","fn","thunk","trampoline","args","trampolineAsync","getMSB","Heap","_Heap","options","element","topValue","nodes","order","result","dfsHelper","index","clonedHeap","visitedNode","cloned","top","parentIndex","parent","leftChildIndex","rightChildIndex","length","targetIndex","temp","i","FibonacciHeapNode","degree","FibonacciHeap","comparator","node","head","flag","z","heapToMerge","thisRoot","otherRoot","thisRootRight","otherRootLeft","a","b","y","x","A","d","t","MaxHeap","Heap","options","a","b","MinHeap","Heap","options","a","b","PriorityQueue","Heap","options","MinPriorityQueue","PriorityQueue","options","a","b","MaxPriorityQueue","PriorityQueue","options","a","b","AbstractVertex","key","value","AbstractEdge","weight","uuidV4","AbstractGraph","vertexKey","vertexOrKey","keyOrVertex","newVertex","vertices","removed","v","v1","v2","srcOrEdge","dest","newEdge","srcOrKey","destOrKey","edge","limit","paths","vertex1","vertex2","stack","vertex","path","neighbors","neighbor","newPath","sum","i","isWeight","allPaths","min","visited","queue","Queue","cost","cur","isDFS","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","PriorityQueue","a","b","curHeapNode","dist","distSrcToNeighbor","scanNegativeCycle","getMin","genPath","hasNegativeCycle","numOfVertices","edges","numOfEdges","j","ends","s","sWeight","dWeight","idAndVertices","n","costs","predecessor","k","needCutVertexes","needBridges","needSCCs","needCycles","dfnMap","lowMap","root","cutVertexes","bridges","dfn","childCount","childLow","curLow","edgeCurToNeighbor","SCCs","getSCCs","low","cycles","SCC","DirectedVertex","AbstractVertex","key","value","DirectedEdge","AbstractEdge","src","dest","weight","DirectedGraph","AbstractGraph","srcOrKey","destOrKey","edges","srcOutEdges","edge","removed","arrayRemove","destInEdges","v1","v2","v1ToV2","v2ToV1","vertexOrKey","target","vertex","destinations","outgoingEdges","outEdge","child","propertyName","statusMap","entry","sorted","hasCycle","dfs","cur","children","childStatus","outEdges","neighbors","neighbor","srcVertex","destVertex","UndirectedVertex","AbstractVertex","key","value","UndirectedEdge","AbstractEdge","v1","v2","weight","UndirectedGraph","AbstractGraph","edges","vertex1","vertex2","e","v1Edges","removed","arrayRemove","v2Edges","edge","vertexOrKey","vertex","edgeSet","neighbors","neighborEdges","neighbor","end","endVertex","MapVertex","DirectedVertex","key","value","lat","long","MapEdge","DirectedEdge","src","dest","weight","MapGraph","DirectedGraph","origin","bottomRight","IterationType","FamilyPosition","RBTNColor","TopologicalProperty","CP","BinaryTreeNode","key","value","v","that","BinaryTree","options","iterationType","keyOrNode","_bfs","root","newNode","queue","Queue","cur","inserted","needInsert","keysOrNodes","values","i","data","identifier","callback","bstDeletedResult","node","curr","parent","needBalanced","orgCurrent","leftSubTreeRightMost","parentOfLeftSubTreeMax","fp","distNode","beginRoot","depth","_getMaxHeight","leftHeight","rightHeight","stack","maxHeight","_getMinHeight","leftMinHeight","rightMinHeight","last","depths","onlyOne","ans","_traverse","isReverse","result","trampoline","dfs","min","max","prev","includeNull","pattern","traverse","level","current","levelSize","levelsNodes","_recursive","head","predecessor","x","y","_reverseEdge","pre","next","_printEdge","tail","srcNode","destNode","tempNode","display","lines","_displayAux","line","width","height","middle","n","p","s","u","first_line","second_line","shifted_lines","left","right","m","q","zipped_lines","a","BSTNode","BinaryTreeNode","key","value","v","BST","BinaryTree","options","comparator","keyOrNode","inserted","newNode","cur","traversing","keysOrNodes","data","isBalanceAdd","iterationType","hasNoNull","arr","n","combinedArr","index","sorted","isNodeOrNullTuple","isBinaryTreeKeyOrNullTuple","sortedKeysOrNodes","sortedData","a","recursive","mid","iterative","stack","popped","l","r","beginRoot","identifier","callback","onlyOne","ans","_traverse","queue","Queue","lesserOrGreater","targetNode","targetKey","node","buildBalanceBST","m","midNode","balanced","_height","leftHeight","rightHeight","last","depths","left","right","b","compared","BinaryIndexedTree","frequency","max","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","SegmentTree","values","mid","left","right","cur","index","root","dfs","indexA","indexB","i","j","leftSum","rightSum","AVLTreeNode","BSTNode","key","value","AVLTree","BST","options","keyOrNode","inserted","identifier","callback","node","deletedResults","needBalanced","srcNode","destNode","height","tempNode","rightHeight","path","i","A","parentOfA","B","C","RBTreeNode","BSTNode","key","value","color","RedBlackTree","BST","options","keyOrNode","node","y","x","identifier","callback","ans","z","yOriginalColor","beginRoot","iterationType","BinaryTreeNode","v","s","u","k","TreeMultimapNode","AVLTreeNode","key","value","count","TreeMultimap","AVLTree","options","keyOrNode","inserted","newNode","cur","traversing","parent","keysOrNodes","data","i","iterationType","sorted","node","n","buildBalanceBST","l","r","m","midNode","stack","popped","identifier","callback","ignoreCount","bstDeletedResult","curr","needBalanced","orgCurrent","leftSubTreeRightMost","parentOfLeftSubTreeMax","fp","srcNode","destNode","height","tempNode","v","TreeNode","_TreeNode","key","value","children","maxDepth","bfs","node","level","i","len","MatrixNTI2D","options","row","col","initialVal","Vector2D","_Vector2D","x","y","w","vector1","vector2","vector","value","roundingFactor","length","max","ySeparation","xSeparation","origin","radian","maxX","maxY","randX","randY","Matrix2D","_Matrix2D","value","Vector2D","matrix1","matrix2","result","i","j","k","matrix","vector","width","height","centerX","centerY","flipX","factor","radians","cos","sin","Character","_Character","direction","turning","Navigator","matrix","onMove","cur","charDir","VISITED","forward","row","j","i","TrieNode","key","Trie","words","caseSensitive","i","word","cur","c","nodeC","isDeleted","dfs","char","child","beginRoot","maxDepth","bfs","node","level","children","input","commonPre","prefix","max","isAllWhenEmptyPrefix","found","charNode","startNode","str"]}