data-structure-typed 2.0.4 → 2.1.0

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 (261) hide show
  1. package/CHANGELOG.md +3 -1
  2. package/COMMANDS.md +17 -0
  3. package/README.md +11 -11
  4. package/benchmark/report.html +13 -77
  5. package/benchmark/report.json +158 -190
  6. package/dist/cjs/data-structures/base/iterable-element-base.d.ts +186 -83
  7. package/dist/cjs/data-structures/base/iterable-element-base.js +149 -107
  8. package/dist/cjs/data-structures/base/iterable-element-base.js.map +1 -1
  9. package/dist/cjs/data-structures/base/iterable-entry-base.d.ts +95 -119
  10. package/dist/cjs/data-structures/base/iterable-entry-base.js +59 -116
  11. package/dist/cjs/data-structures/base/iterable-entry-base.js.map +1 -1
  12. package/dist/cjs/data-structures/base/linear-base.d.ts +250 -192
  13. package/dist/cjs/data-structures/base/linear-base.js +137 -274
  14. package/dist/cjs/data-structures/base/linear-base.js.map +1 -1
  15. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
  16. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js +171 -205
  17. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
  18. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
  19. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
  20. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  21. package/dist/cjs/data-structures/binary-tree/avl-tree.d.ts +138 -149
  22. package/dist/cjs/data-structures/binary-tree/avl-tree.js +208 -195
  23. package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
  24. package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +476 -632
  25. package/dist/cjs/data-structures/binary-tree/binary-tree.js +608 -875
  26. package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  27. package/dist/cjs/data-structures/binary-tree/bst.d.ts +258 -306
  28. package/dist/cjs/data-structures/binary-tree/bst.js +505 -481
  29. package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
  30. package/dist/cjs/data-structures/binary-tree/red-black-tree.d.ts +107 -179
  31. package/dist/cjs/data-structures/binary-tree/red-black-tree.js +114 -209
  32. package/dist/cjs/data-structures/binary-tree/red-black-tree.js.map +1 -1
  33. package/dist/cjs/data-structures/binary-tree/tree-counter.d.ts +132 -154
  34. package/dist/cjs/data-structures/binary-tree/tree-counter.js +172 -203
  35. package/dist/cjs/data-structures/binary-tree/tree-counter.js.map +1 -1
  36. package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
  37. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +105 -85
  38. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  39. package/dist/cjs/data-structures/graph/abstract-graph.d.ts +238 -233
  40. package/dist/cjs/data-structures/graph/abstract-graph.js +267 -237
  41. package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
  42. package/dist/cjs/data-structures/graph/directed-graph.d.ts +108 -224
  43. package/dist/cjs/data-structures/graph/directed-graph.js +146 -233
  44. package/dist/cjs/data-structures/graph/directed-graph.js.map +1 -1
  45. package/dist/cjs/data-structures/graph/map-graph.d.ts +49 -55
  46. package/dist/cjs/data-structures/graph/map-graph.js +56 -59
  47. package/dist/cjs/data-structures/graph/map-graph.js.map +1 -1
  48. package/dist/cjs/data-structures/graph/undirected-graph.d.ts +103 -146
  49. package/dist/cjs/data-structures/graph/undirected-graph.js +129 -149
  50. package/dist/cjs/data-structures/graph/undirected-graph.js.map +1 -1
  51. package/dist/cjs/data-structures/hash/hash-map.d.ts +164 -338
  52. package/dist/cjs/data-structures/hash/hash-map.js +270 -457
  53. package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
  54. package/dist/cjs/data-structures/heap/heap.d.ts +214 -289
  55. package/dist/cjs/data-structures/heap/heap.js +340 -349
  56. package/dist/cjs/data-structures/heap/heap.js.map +1 -1
  57. package/dist/cjs/data-structures/heap/max-heap.d.ts +11 -47
  58. package/dist/cjs/data-structures/heap/max-heap.js +11 -66
  59. package/dist/cjs/data-structures/heap/max-heap.js.map +1 -1
  60. package/dist/cjs/data-structures/heap/min-heap.d.ts +12 -47
  61. package/dist/cjs/data-structures/heap/min-heap.js +11 -66
  62. package/dist/cjs/data-structures/heap/min-heap.js.map +1 -1
  63. package/dist/cjs/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
  64. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js +368 -494
  65. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  66. package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +261 -310
  67. package/dist/cjs/data-structures/linked-list/singly-linked-list.js +447 -466
  68. package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
  69. package/dist/cjs/data-structures/linked-list/skip-linked-list.d.ts +0 -107
  70. package/dist/cjs/data-structures/linked-list/skip-linked-list.js +0 -100
  71. package/dist/cjs/data-structures/linked-list/skip-linked-list.js.map +1 -1
  72. package/dist/cjs/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
  73. package/dist/cjs/data-structures/priority-queue/max-priority-queue.js +11 -78
  74. package/dist/cjs/data-structures/priority-queue/max-priority-queue.js.map +1 -1
  75. package/dist/cjs/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
  76. package/dist/cjs/data-structures/priority-queue/min-priority-queue.js +10 -79
  77. package/dist/cjs/data-structures/priority-queue/min-priority-queue.js.map +1 -1
  78. package/dist/cjs/data-structures/priority-queue/priority-queue.d.ts +2 -61
  79. package/dist/cjs/data-structures/priority-queue/priority-queue.js +8 -83
  80. package/dist/cjs/data-structures/priority-queue/priority-queue.js.map +1 -1
  81. package/dist/cjs/data-structures/queue/deque.d.ts +227 -254
  82. package/dist/cjs/data-structures/queue/deque.js +309 -348
  83. package/dist/cjs/data-structures/queue/deque.js.map +1 -1
  84. package/dist/cjs/data-structures/queue/queue.d.ts +180 -201
  85. package/dist/cjs/data-structures/queue/queue.js +265 -248
  86. package/dist/cjs/data-structures/queue/queue.js.map +1 -1
  87. package/dist/cjs/data-structures/stack/stack.d.ts +124 -102
  88. package/dist/cjs/data-structures/stack/stack.js +181 -125
  89. package/dist/cjs/data-structures/stack/stack.js.map +1 -1
  90. package/dist/cjs/data-structures/trie/trie.d.ts +164 -165
  91. package/dist/cjs/data-structures/trie/trie.js +189 -172
  92. package/dist/cjs/data-structures/trie/trie.js.map +1 -1
  93. package/dist/cjs/interfaces/binary-tree.d.ts +56 -6
  94. package/dist/cjs/interfaces/graph.d.ts +16 -0
  95. package/dist/cjs/types/data-structures/base/base.d.ts +1 -1
  96. package/dist/cjs/types/data-structures/graph/abstract-graph.d.ts +4 -0
  97. package/dist/cjs/types/utils/utils.d.ts +6 -6
  98. package/dist/cjs/utils/utils.d.ts +110 -49
  99. package/dist/cjs/utils/utils.js +148 -73
  100. package/dist/cjs/utils/utils.js.map +1 -1
  101. package/dist/esm/data-structures/base/iterable-element-base.d.ts +186 -83
  102. package/dist/esm/data-structures/base/iterable-element-base.js +155 -107
  103. package/dist/esm/data-structures/base/iterable-element-base.js.map +1 -1
  104. package/dist/esm/data-structures/base/iterable-entry-base.d.ts +95 -119
  105. package/dist/esm/data-structures/base/iterable-entry-base.js +59 -116
  106. package/dist/esm/data-structures/base/iterable-entry-base.js.map +1 -1
  107. package/dist/esm/data-structures/base/linear-base.d.ts +250 -192
  108. package/dist/esm/data-structures/base/linear-base.js +137 -274
  109. package/dist/esm/data-structures/base/linear-base.js.map +1 -1
  110. package/dist/esm/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
  111. package/dist/esm/data-structures/binary-tree/avl-tree-counter.js +171 -212
  112. package/dist/esm/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
  113. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
  114. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js +133 -94
  115. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  116. package/dist/esm/data-structures/binary-tree/avl-tree.d.ts +138 -149
  117. package/dist/esm/data-structures/binary-tree/avl-tree.js +206 -200
  118. package/dist/esm/data-structures/binary-tree/avl-tree.js.map +1 -1
  119. package/dist/esm/data-structures/binary-tree/binary-tree.d.ts +476 -632
  120. package/dist/esm/data-structures/binary-tree/binary-tree.js +613 -885
  121. package/dist/esm/data-structures/binary-tree/binary-tree.js.map +1 -1
  122. package/dist/esm/data-structures/binary-tree/bst.d.ts +258 -306
  123. package/dist/esm/data-structures/binary-tree/bst.js +507 -487
  124. package/dist/esm/data-structures/binary-tree/bst.js.map +1 -1
  125. package/dist/esm/data-structures/binary-tree/red-black-tree.d.ts +107 -179
  126. package/dist/esm/data-structures/binary-tree/red-black-tree.js +114 -215
  127. package/dist/esm/data-structures/binary-tree/red-black-tree.js.map +1 -1
  128. package/dist/esm/data-structures/binary-tree/tree-counter.d.ts +132 -154
  129. package/dist/esm/data-structures/binary-tree/tree-counter.js +175 -209
  130. package/dist/esm/data-structures/binary-tree/tree-counter.js.map +1 -1
  131. package/dist/esm/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
  132. package/dist/esm/data-structures/binary-tree/tree-multi-map.js +103 -92
  133. package/dist/esm/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  134. package/dist/esm/data-structures/graph/abstract-graph.d.ts +238 -233
  135. package/dist/esm/data-structures/graph/abstract-graph.js +267 -237
  136. package/dist/esm/data-structures/graph/abstract-graph.js.map +1 -1
  137. package/dist/esm/data-structures/graph/directed-graph.d.ts +108 -224
  138. package/dist/esm/data-structures/graph/directed-graph.js +145 -233
  139. package/dist/esm/data-structures/graph/directed-graph.js.map +1 -1
  140. package/dist/esm/data-structures/graph/map-graph.d.ts +49 -55
  141. package/dist/esm/data-structures/graph/map-graph.js +56 -59
  142. package/dist/esm/data-structures/graph/map-graph.js.map +1 -1
  143. package/dist/esm/data-structures/graph/undirected-graph.d.ts +103 -146
  144. package/dist/esm/data-structures/graph/undirected-graph.js +128 -149
  145. package/dist/esm/data-structures/graph/undirected-graph.js.map +1 -1
  146. package/dist/esm/data-structures/hash/hash-map.d.ts +164 -338
  147. package/dist/esm/data-structures/hash/hash-map.js +270 -457
  148. package/dist/esm/data-structures/hash/hash-map.js.map +1 -1
  149. package/dist/esm/data-structures/heap/heap.d.ts +214 -289
  150. package/dist/esm/data-structures/heap/heap.js +329 -349
  151. package/dist/esm/data-structures/heap/heap.js.map +1 -1
  152. package/dist/esm/data-structures/heap/max-heap.d.ts +11 -47
  153. package/dist/esm/data-structures/heap/max-heap.js +11 -66
  154. package/dist/esm/data-structures/heap/max-heap.js.map +1 -1
  155. package/dist/esm/data-structures/heap/min-heap.d.ts +12 -47
  156. package/dist/esm/data-structures/heap/min-heap.js +11 -66
  157. package/dist/esm/data-structures/heap/min-heap.js.map +1 -1
  158. package/dist/esm/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
  159. package/dist/esm/data-structures/linked-list/doubly-linked-list.js +368 -495
  160. package/dist/esm/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  161. package/dist/esm/data-structures/linked-list/singly-linked-list.d.ts +261 -310
  162. package/dist/esm/data-structures/linked-list/singly-linked-list.js +448 -467
  163. package/dist/esm/data-structures/linked-list/singly-linked-list.js.map +1 -1
  164. package/dist/esm/data-structures/linked-list/skip-linked-list.d.ts +0 -107
  165. package/dist/esm/data-structures/linked-list/skip-linked-list.js +0 -100
  166. package/dist/esm/data-structures/linked-list/skip-linked-list.js.map +1 -1
  167. package/dist/esm/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
  168. package/dist/esm/data-structures/priority-queue/max-priority-queue.js +11 -78
  169. package/dist/esm/data-structures/priority-queue/max-priority-queue.js.map +1 -1
  170. package/dist/esm/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
  171. package/dist/esm/data-structures/priority-queue/min-priority-queue.js +10 -79
  172. package/dist/esm/data-structures/priority-queue/min-priority-queue.js.map +1 -1
  173. package/dist/esm/data-structures/priority-queue/priority-queue.d.ts +2 -61
  174. package/dist/esm/data-structures/priority-queue/priority-queue.js +8 -83
  175. package/dist/esm/data-structures/priority-queue/priority-queue.js.map +1 -1
  176. package/dist/esm/data-structures/queue/deque.d.ts +227 -254
  177. package/dist/esm/data-structures/queue/deque.js +313 -348
  178. package/dist/esm/data-structures/queue/deque.js.map +1 -1
  179. package/dist/esm/data-structures/queue/queue.d.ts +180 -201
  180. package/dist/esm/data-structures/queue/queue.js +263 -248
  181. package/dist/esm/data-structures/queue/queue.js.map +1 -1
  182. package/dist/esm/data-structures/stack/stack.d.ts +124 -102
  183. package/dist/esm/data-structures/stack/stack.js +181 -125
  184. package/dist/esm/data-structures/stack/stack.js.map +1 -1
  185. package/dist/esm/data-structures/trie/trie.d.ts +164 -165
  186. package/dist/esm/data-structures/trie/trie.js +193 -172
  187. package/dist/esm/data-structures/trie/trie.js.map +1 -1
  188. package/dist/esm/interfaces/binary-tree.d.ts +56 -6
  189. package/dist/esm/interfaces/graph.d.ts +16 -0
  190. package/dist/esm/types/data-structures/base/base.d.ts +1 -1
  191. package/dist/esm/types/data-structures/graph/abstract-graph.d.ts +4 -0
  192. package/dist/esm/types/utils/utils.d.ts +6 -6
  193. package/dist/esm/utils/utils.d.ts +110 -49
  194. package/dist/esm/utils/utils.js +139 -68
  195. package/dist/esm/utils/utils.js.map +1 -1
  196. package/dist/umd/data-structure-typed.js +4737 -6525
  197. package/dist/umd/data-structure-typed.min.js +8 -6
  198. package/dist/umd/data-structure-typed.min.js.map +1 -1
  199. package/package.json +3 -4
  200. package/src/data-structures/base/iterable-element-base.ts +238 -115
  201. package/src/data-structures/base/iterable-entry-base.ts +96 -120
  202. package/src/data-structures/base/linear-base.ts +271 -277
  203. package/src/data-structures/binary-tree/avl-tree-counter.ts +198 -216
  204. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +192 -101
  205. package/src/data-structures/binary-tree/avl-tree.ts +239 -206
  206. package/src/data-structures/binary-tree/binary-tree.ts +677 -901
  207. package/src/data-structures/binary-tree/bst.ts +568 -570
  208. package/src/data-structures/binary-tree/red-black-tree.ts +161 -222
  209. package/src/data-structures/binary-tree/tree-counter.ts +199 -218
  210. package/src/data-structures/binary-tree/tree-multi-map.ts +131 -97
  211. package/src/data-structures/graph/abstract-graph.ts +339 -264
  212. package/src/data-structures/graph/directed-graph.ts +146 -236
  213. package/src/data-structures/graph/map-graph.ts +63 -60
  214. package/src/data-structures/graph/undirected-graph.ts +129 -152
  215. package/src/data-structures/hash/hash-map.ts +274 -496
  216. package/src/data-structures/heap/heap.ts +389 -402
  217. package/src/data-structures/heap/max-heap.ts +12 -76
  218. package/src/data-structures/heap/min-heap.ts +13 -76
  219. package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
  220. package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
  221. package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
  222. package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
  223. package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
  224. package/src/data-structures/priority-queue/priority-queue.ts +3 -92
  225. package/src/data-structures/queue/deque.ts +381 -357
  226. package/src/data-structures/queue/queue.ts +310 -264
  227. package/src/data-structures/stack/stack.ts +217 -131
  228. package/src/data-structures/trie/trie.ts +240 -175
  229. package/src/interfaces/binary-tree.ts +240 -6
  230. package/src/interfaces/graph.ts +37 -0
  231. package/src/types/data-structures/base/base.ts +5 -5
  232. package/src/types/data-structures/graph/abstract-graph.ts +5 -0
  233. package/src/types/utils/utils.ts +9 -5
  234. package/src/utils/utils.ts +152 -86
  235. package/test/integration/index.html +1 -1
  236. package/test/performance/benchmark-runner.ts +528 -0
  237. package/test/performance/reportor.mjs +43 -43
  238. package/test/performance/runner-config.json +39 -0
  239. package/test/performance/single-suite-runner.ts +69 -0
  240. package/test/unit/data-structures/binary-tree/avl-tree-counter.test.ts +3 -3
  241. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +5 -5
  242. package/test/unit/data-structures/binary-tree/avl-tree.test.ts +4 -4
  243. package/test/unit/data-structures/binary-tree/binary-tree.test.ts +350 -90
  244. package/test/unit/data-structures/binary-tree/bst.test.ts +84 -5
  245. package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +2 -2
  246. package/test/unit/data-structures/binary-tree/tree-counter.test.ts +25 -24
  247. package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +3 -3
  248. package/test/unit/data-structures/graph/abstract-graph.test.ts +0 -4
  249. package/test/unit/data-structures/graph/directed-graph.test.ts +1 -1
  250. package/test/unit/data-structures/heap/heap.test.ts +14 -21
  251. package/test/unit/data-structures/heap/max-heap.test.ts +5 -9
  252. package/test/unit/data-structures/heap/min-heap.test.ts +1 -4
  253. package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +14 -14
  254. package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +0 -7
  255. package/test/unit/data-structures/priority-queue/max-priority-queue.test.ts +8 -11
  256. package/test/unit/data-structures/priority-queue/min-priority-queue.test.ts +1 -4
  257. package/test/unit/data-structures/priority-queue/priority-queue.test.ts +1 -4
  258. package/test/unit/data-structures/queue/queue.test.ts +4 -5
  259. package/test/unit/utils/utils.test.ts +0 -1
  260. package/test/performance/data-structures/binary-tree/avl-tree.test.mjs +0 -71
  261. package/test/performance/data-structures/binary-tree/red-black-tree.test.mjs +0 -81
@@ -1,43 +1,82 @@
1
+ /**
2
+ * data-structure-typed
3
+ *
4
+ * @author Pablo Zeng
5
+ * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
6
+ * @license MIT License
7
+ */
1
8
  import { BinaryTree, BinaryTreeNode } from './binary-tree';
2
9
  import { Queue } from '../queue';
3
10
  import { isComparable } from '../../utils';
4
11
  import { Range } from '../../common';
12
+ /**
13
+ * Represents a Node in a Binary Search Tree.
14
+ *
15
+ * @template K - The type of the key.
16
+ * @template V - The type of the value.
17
+ */
5
18
  export class BSTNode extends BinaryTreeNode {
6
19
  parent = undefined;
7
20
  /**
8
- * This TypeScript constructor function initializes an instance with a key and an optional value.
9
- * @param {K} key - The `key` parameter is typically used to uniquely identify an object or element
10
- * within a data structure. It serves as a reference or identifier for accessing or manipulating the
11
- * associated value.
12
- * @param {V} [value] - The `value` parameter in the constructor is optional, meaning it does not
13
- * have to be provided when creating an instance of the class. If a value is not provided, it will
14
- * default to `undefined`.
21
+ * Creates an instance of BSTNode.
22
+ * @remarks Time O(1), Space O(1)
23
+ *
24
+ * @param key - The key of the node.
25
+ * @param [value] - The value associated with the key.
15
26
  */
16
27
  constructor(key, value) {
17
28
  super(key, value);
18
29
  }
19
30
  _left = undefined;
31
+ /**
32
+ * Gets the left child of the node.
33
+ * @remarks Time O(1), Space O(1)
34
+ *
35
+ * @returns The left child.
36
+ */
20
37
  get left() {
21
38
  return this._left;
22
39
  }
40
+ /**
41
+ * Sets the left child of the node and updates its parent reference.
42
+ * @remarks Time O(1), Space O(1)
43
+ *
44
+ * @param v - The node to set as the left child.
45
+ */
23
46
  set left(v) {
24
- if (v) {
47
+ if (v)
25
48
  v.parent = this;
26
- }
27
49
  this._left = v;
28
50
  }
29
51
  _right = undefined;
52
+ /**
53
+ * Gets the right child of the node.
54
+ * @remarks Time O(1), Space O(1)
55
+ *
56
+ * @returns The right child.
57
+ */
30
58
  get right() {
31
59
  return this._right;
32
60
  }
61
+ /**
62
+ * Sets the right child of the node and updates its parent reference.
63
+ * @remarks Time O(1), Space O(1)
64
+ *
65
+ * @param v - The node to set as the right child.
66
+ */
33
67
  set right(v) {
34
- if (v) {
68
+ if (v)
35
69
  v.parent = this;
36
- }
37
70
  this._right = v;
38
71
  }
39
72
  }
40
73
  /**
74
+ * Represents a Binary Search Tree (BST).
75
+ * Keys are ordered, allowing for faster search operations compared to a standard Binary Tree.
76
+ * @template K - The type of the key.
77
+ * @template V - The type of the value.
78
+ * @template R - The type of the raw data object (if using `toEntryFn`).
79
+ *
41
80
  * 1. Node Order: Each node's left child has a lesser value, and the right child has a greater value.
42
81
  * 2. Unique Keys: No duplicate keys in a standard BST.
43
82
  * 3. Efficient Search: Enables quick search, minimum, and maximum operations.
@@ -104,13 +143,11 @@ export class BSTNode extends BinaryTreeNode {
104
143
  */
105
144
  export class BST extends BinaryTree {
106
145
  /**
107
- * This TypeScript constructor initializes a binary search tree with optional options and adds
108
- * elements if provided.
109
- * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an
110
- * iterable that can contain elements of type `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It is used to
111
- * initialize the binary search tree with keys, nodes, entries, or raw data.
112
- * @param [options] - The `options` parameter is an optional object that can contain the following
113
- * properties:
146
+ * Creates an instance of BST.
147
+ * @remarks Time O(N log N) or O(N^2) depending on `isBalanceAdd` in `addMany` and input order. Space O(N).
148
+ *
149
+ * @param [keysNodesEntriesOrRaws=[]] - An iterable of items to add.
150
+ * @param [options] - Configuration options for the BST, including comparator.
114
151
  */
115
152
  constructor(keysNodesEntriesOrRaws = [], options) {
116
153
  super([], options);
@@ -125,13 +162,29 @@ export class BST extends BinaryTree {
125
162
  this.addMany(keysNodesEntriesOrRaws);
126
163
  }
127
164
  _root = undefined;
165
+ /**
166
+ * Gets the root node of the tree.
167
+ * @remarks Time O(1)
168
+ *
169
+ * @returns The root node.
170
+ */
128
171
  get root() {
129
172
  return this._root;
130
173
  }
131
174
  _isReverse = false;
175
+ /**
176
+ * Gets whether the tree's comparison logic is reversed.
177
+ * @remarks Time O(1)
178
+ *
179
+ * @returns True if the tree is reversed (e.g., a max-heap logic).
180
+ */
132
181
  get isReverse() {
133
182
  return this._isReverse;
134
183
  }
184
+ /**
185
+ * The default comparator function.
186
+ * @remarks Time O(1) (or O(C) if `specifyComparable` is used, C is complexity of that function).
187
+ */
135
188
  _comparator = (a, b) => {
136
189
  if (isComparable(a) && isComparable(b)) {
137
190
  if (a > b)
@@ -141,113 +194,234 @@ export class BST extends BinaryTree {
141
194
  return 0;
142
195
  }
143
196
  if (this._specifyComparable) {
144
- if (this._specifyComparable(a) > this._specifyComparable(b))
197
+ const va = this._specifyComparable(a);
198
+ const vb = this._specifyComparable(b);
199
+ if (va > vb)
145
200
  return 1;
146
- if (this._specifyComparable(a) < this._specifyComparable(b))
201
+ if (va < vb)
147
202
  return -1;
148
203
  return 0;
149
204
  }
150
205
  if (typeof a === 'object' || typeof b === 'object') {
151
- throw TypeError(`When comparing object types, a custom specifyComparable must be defined in the constructor's options parameter.`);
206
+ throw TypeError(`When comparing object types, a custom specifyComparable must be defined in the constructor's options.`);
152
207
  }
153
208
  return 0;
154
209
  };
210
+ /**
211
+ * Gets the comparator function used by the tree.
212
+ * @remarks Time O(1)
213
+ *
214
+ * @returns The comparator function.
215
+ */
155
216
  get comparator() {
156
217
  return this._comparator;
157
218
  }
158
219
  _specifyComparable;
159
- get specifyComparable() {
160
- return this._specifyComparable;
161
- }
162
220
  /**
163
- * Time Complexity: O(1)
164
- * Space Complexity: O(1)
221
+ * Gets the function used to extract a comparable value from a complex key.
222
+ * @remarks Time O(1)
165
223
  *
166
- * The function creates a new BSTNode with the given key and value and returns it.
167
- * @param {K} key - The key parameter is of type K, which represents the type of the key for the node
168
- * being created.
169
- * @param {V} [value] - The "value" parameter is an optional parameter of type V. It represents the
170
- * value associated with the key in the node being created.
171
- * @returns The method is returning a new instance of the BSTNode class, casted as the BSTNode<K, V> type.
224
+ * @returns The key-to-comparable conversion function.
172
225
  */
173
- createNode(key, value) {
174
- return new BSTNode(key, this._isMapMode ? undefined : value);
226
+ get specifyComparable() {
227
+ return this._specifyComparable;
175
228
  }
176
229
  /**
177
- * Time Complexity: O(1)
178
- * Space Complexity: O(1)
230
+ * (Protected) Creates a new BST node.
231
+ * @remarks Time O(1), Space O(1)
179
232
  *
180
- * The function creates a new binary search tree with the specified options.
181
- * @param [options] - The `options` parameter is an optional object that allows you to customize the
182
- * behavior of the `createTree` method. It accepts a partial `BSTOptions` object, which has the
183
- * following properties:
184
- * @returns a new instance of the BST class with the provided options.
233
+ * @param key - The key for the new node.
234
+ * @param [value] - The value for the new node (used if not in Map mode).
235
+ * @returns The newly created BSTNode.
185
236
  */
186
- createTree(options) {
187
- return new BST([], {
188
- iterationType: this.iterationType,
189
- isMapMode: this._isMapMode,
190
- specifyComparable: this._specifyComparable,
191
- toEntryFn: this._toEntryFn,
192
- isReverse: this._isReverse,
193
- ...options
194
- });
237
+ _createNode(key, value) {
238
+ return new BSTNode(key, this._isMapMode ? undefined : value);
195
239
  }
196
240
  /**
197
- * Time Complexity: O(log n)
198
- * Space Complexity: O(log n)
241
+ * Ensures the input is a node. If it's a key or entry, it searches for the node.
242
+ * @remarks Time O(log N) (height of the tree), O(N) worst-case.
199
243
  *
200
- * The function ensures the existence of a node in a data structure and returns it, or undefined if
201
- * it doesn't exist.
202
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
203
- * `keyNodeOrEntry` can accept a value of type `R`, which represents the key, node,
204
- * entry, or raw element that needs to be ensured in the tree.
205
- * @param {IterationType} [iterationType=ITERATIVE] - The `iterationType` parameter is an optional
206
- * parameter that specifies the type of iteration to be used when ensuring a node. It has a default
207
- * value of `'ITERATIVE'`.
208
- * @returns The method is returning either the node that was ensured or `undefined` if the node could
209
- * not be ensured.
244
+ * @param keyNodeOrEntry - The item to resolve to a node.
245
+ * @param [iterationType=this.iterationType] - The traversal method to use if searching.
246
+ * @returns The resolved node, or undefined if not found.
210
247
  */
211
248
  ensureNode(keyNodeOrEntry, iterationType = this.iterationType) {
212
249
  return super.ensureNode(keyNodeOrEntry, iterationType) ?? undefined;
213
250
  }
214
251
  /**
215
- * Time Complexity: O(1)
216
- * Space Complexity: O(1)
252
+ * Checks if the given item is a `BSTNode` instance.
253
+ * @remarks Time O(1), Space O(1)
217
254
  *
218
- * The function checks if the input is an instance of the BSTNode class.
219
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
220
- * `keyNodeOrEntry` can be of type `R` or `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.
221
- * @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is
222
- * an instance of the `BSTNode` class.
255
+ * @param keyNodeOrEntry - The item to check.
256
+ * @returns True if it's a BSTNode, false otherwise.
223
257
  */
224
258
  isNode(keyNodeOrEntry) {
225
259
  return keyNodeOrEntry instanceof BSTNode;
226
260
  }
227
261
  /**
228
- * Time Complexity: O(1)
229
- * Space Complexity: O(1)
262
+ * Checks if the given key is valid (comparable).
263
+ * @remarks Time O(1)
230
264
  *
231
- * The function "override isValidKey" checks if a key is comparable based on a given comparator.
232
- * @param {any} key - The `key` parameter is a value that will be checked to determine if it is of
233
- * type `K`.
234
- * @returns The `override isValidKey(key: any): key is K` function is returning a boolean value based on
235
- * the result of the `isComparable` function with the condition `this._compare !==
236
- * this._DEFAULT_COMPARATOR`.
265
+ * @param key - The key to validate.
266
+ * @returns True if the key is valid, false otherwise.
237
267
  */
238
268
  isValidKey(key) {
239
269
  return isComparable(key, this._specifyComparable !== undefined);
240
270
  }
241
271
  /**
242
- * Time Complexity: O(log n)
243
- * Space Complexity: O(log n)
272
+ * Performs a Depth-First Search (DFS) traversal.
273
+ * @remarks Time O(N), visits every node. Space O(log N) for the call/explicit stack. O(N) worst-case.
274
+ *
275
+ * @template C - The type of the callback function.
276
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
277
+ * @param [pattern='IN'] - The traversal order ('IN', 'PRE', 'POST').
278
+ * @param [onlyOne=false] - If true, stops after the first callback.
279
+ * @param [startNode=this._root] - The node to start from.
280
+ * @param [iterationType=this.iterationType] - The traversal method.
281
+ * @returns An array of callback results.
282
+ */
283
+ dfs(callback = this._DEFAULT_NODE_CALLBACK, pattern = 'IN', onlyOne = false, startNode = this._root, iterationType = this.iterationType) {
284
+ return super.dfs(callback, pattern, onlyOne, startNode, iterationType);
285
+ }
286
+ /**
287
+ * Performs a Breadth-First Search (BFS) or Level-Order traversal.
288
+ * @remarks Time O(N), visits every node. Space O(N) in the worst case for the queue.
289
+ *
290
+ * @template C - The type of the callback function.
291
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
292
+ * @param [startNode=this._root] - The node to start from.
293
+ * @param [iterationType=this.iterationType] - The traversal method.
294
+ * @returns An array of callback results.
295
+ */
296
+ bfs(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
297
+ return super.bfs(callback, startNode, iterationType, false);
298
+ }
299
+ /**
300
+ * Returns a 2D array of nodes, grouped by level.
301
+ * @remarks Time O(N), visits every node. Space O(N) for the result array and the queue/stack.
244
302
  *
245
- * The `add` function in TypeScript adds a new node to a binary search tree based on the key value.
246
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
247
- * `keyNodeOrEntry` can accept a value of type `R` or `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `.
248
- * @param {V} [value] - The `value` parameter is an optional value that can be associated with the
249
- * key in the binary search tree. If provided, it will be stored in the node along with the key.
250
- * @returns a boolean value.
303
+ * @template C - The type of the callback function.
304
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
305
+ * @param [startNode=this._root] - The node to start from.
306
+ * @param [iterationType=this.iterationType] - The traversal method.
307
+ * @returns A 2D array of callback results.
308
+ */
309
+ listLevels(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
310
+ return super.listLevels(callback, startNode, iterationType, false);
311
+ }
312
+ /**
313
+ * Gets the first node matching a predicate.
314
+ * @remarks Time O(log N) if searching by key, O(N) if searching by predicate. Space O(log N) or O(N).
315
+ *
316
+ * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
317
+ * @param [startNode=this._root] - The node to start the search from.
318
+ * @param [iterationType=this.iterationType] - The traversal method.
319
+ * @returns The first matching node, or undefined if not found.
320
+ */
321
+ getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
322
+ return this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0] ?? undefined;
323
+ }
324
+ /**
325
+ * Searches the tree for nodes matching a predicate, key, or range.
326
+ * @remarks This is an optimized search for a BST. If searching by key or range, it prunes branches.
327
+ * Time O(H + M) for key/range search (H=height, M=matches). O(N) for predicate search.
328
+ * Space O(log N) for the stack.
329
+ *
330
+ * @template C - The type of the callback function.
331
+ * @param keyNodeEntryOrPredicate - The key, node, entry, predicate, or range to search for.
332
+ * @param [onlyOne=false] - If true, stops after finding the first match.
333
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on matching nodes.
334
+ * @param [startNode=this._root] - The node to start the search from.
335
+ * @param [iterationType=this.iterationType] - Whether to use 'RECURSIVE' or 'ITERATIVE' search.
336
+ * @returns An array of results from the callback function for each matching node.
337
+ */
338
+ search(keyNodeEntryOrPredicate, onlyOne = false, callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
339
+ if (keyNodeEntryOrPredicate === undefined)
340
+ return [];
341
+ if (keyNodeEntryOrPredicate === null)
342
+ return [];
343
+ startNode = this.ensureNode(startNode);
344
+ if (!startNode)
345
+ return [];
346
+ let predicate;
347
+ const isRange = this.isRange(keyNodeEntryOrPredicate);
348
+ if (isRange) {
349
+ predicate = node => {
350
+ if (!node)
351
+ return false;
352
+ return keyNodeEntryOrPredicate.isInRange(node.key, this._comparator);
353
+ };
354
+ }
355
+ else {
356
+ predicate = this._ensurePredicate(keyNodeEntryOrPredicate);
357
+ }
358
+ // Optimization: Pruning logic
359
+ const shouldVisitLeft = (cur) => {
360
+ if (!cur)
361
+ return false;
362
+ if (!this.isRealNode(cur.left))
363
+ return false;
364
+ if (isRange) {
365
+ // Range search: Only go left if the current key is >= the lower bound
366
+ const range = keyNodeEntryOrPredicate;
367
+ const leftS = this.isReverse ? range.high : range.low;
368
+ const leftI = this.isReverse ? range.includeHigh : range.includeLow;
369
+ return (leftI && this._compare(cur.key, leftS) >= 0) || (!leftI && this._compare(cur.key, leftS) > 0);
370
+ }
371
+ if (!isRange && !this._isPredicate(keyNodeEntryOrPredicate)) {
372
+ // Key search: Only go left if current key > target key
373
+ const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
374
+ return benchmarkKey !== null && benchmarkKey !== undefined && this._compare(cur.key, benchmarkKey) > 0;
375
+ }
376
+ return true; // Predicate search: must visit all
377
+ };
378
+ const shouldVisitRight = (cur) => {
379
+ if (!cur)
380
+ return false;
381
+ if (!this.isRealNode(cur.right))
382
+ return false;
383
+ if (isRange) {
384
+ // Range search: Only go right if current key <= upper bound
385
+ const range = keyNodeEntryOrPredicate;
386
+ const rightS = this.isReverse ? range.low : range.high;
387
+ const rightI = this.isReverse ? range.includeLow : range.includeHigh;
388
+ return (rightI && this._compare(cur.key, rightS) <= 0) || (!rightI && this._compare(cur.key, rightS) < 0);
389
+ }
390
+ if (!isRange && !this._isPredicate(keyNodeEntryOrPredicate)) {
391
+ // Key search: Only go right if current key < target key
392
+ const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
393
+ return benchmarkKey !== null && benchmarkKey !== undefined && this._compare(cur.key, benchmarkKey) < 0;
394
+ }
395
+ return true; // Predicate search: must visit all
396
+ };
397
+ return super._dfs(callback, 'IN', // In-order is efficient for range/key search
398
+ onlyOne, startNode, iterationType, false, shouldVisitLeft, shouldVisitRight, () => true, // shouldVisitRoot (always visit)
399
+ // shouldVisitRoot (always visit)
400
+ cur => !!cur && predicate(cur) // shouldProcessRoot (only process if predicate matches)
401
+ );
402
+ }
403
+ /**
404
+ * Performs an optimized search for nodes within a given key range.
405
+ * @remarks Time O(H + M), where H is tree height and M is the number of matches.
406
+ *
407
+ * @template C - The type of the callback function.
408
+ * @param range - A `Range` object or a `[low, high]` tuple.
409
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on matching nodes.
410
+ * @param [startNode=this._root] - The node to start the search from.
411
+ * @param [iterationType=this.iterationType] - The traversal method.
412
+ * @returns An array of callback results.
413
+ */
414
+ rangeSearch(range, callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
415
+ const searchRange = range instanceof Range ? range : new Range(range[0], range[1]);
416
+ return this.search(searchRange, false, callback, startNode, iterationType);
417
+ }
418
+ /**
419
+ * Adds a new node to the BST based on key comparison.
420
+ * @remarks Time O(log N), where H is tree height. O(N) worst-case (unbalanced tree), O(log N) average. Space O(1).
421
+ *
422
+ * @param keyNodeOrEntry - The key, node, or entry to add.
423
+ * @param [value] - The value, if providing just a key.
424
+ * @returns True if the addition was successful, false otherwise.
251
425
  */
252
426
  add(keyNodeOrEntry, value) {
253
427
  const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
@@ -263,12 +437,14 @@ export class BST extends BinaryTree {
263
437
  let current = this._root;
264
438
  while (current !== undefined) {
265
439
  if (this._compare(current.key, newNode.key) === 0) {
440
+ // Key exists, replace node
266
441
  this._replaceNode(current, newNode);
267
442
  if (this._isMapMode)
268
443
  this._setValue(current.key, newValue);
269
444
  return true;
270
445
  }
271
446
  else if (this._compare(current.key, newNode.key) > 0) {
447
+ // Go left
272
448
  if (current.left === undefined) {
273
449
  current.left = newNode;
274
450
  if (this._isMapMode)
@@ -280,6 +456,7 @@ export class BST extends BinaryTree {
280
456
  current = current.left;
281
457
  }
282
458
  else {
459
+ // Go right
283
460
  if (current.right === undefined) {
284
461
  current.right = newNode;
285
462
  if (this._isMapMode)
@@ -294,49 +471,38 @@ export class BST extends BinaryTree {
294
471
  return false;
295
472
  }
296
473
  /**
297
- * Time Complexity: O(k log n)
298
- * Space Complexity: O(k + log n)
299
- *
300
- * The `addMany` function in TypeScript adds multiple keys or nodes to a data structure and returns
301
- * an array indicating whether each key or node was successfully inserted.
302
- * @param keysNodesEntriesOrRaws - An iterable containing keys, nodes, entries, or raw
303
- * elements to be added to the data structure.
304
- * @param [values] - An optional iterable of values to be associated with the keys or nodes being
305
- * added. If provided, the values will be assigned to the corresponding keys or nodes in the same
306
- * order. If not provided, undefined will be assigned as the value for each key or node.
307
- * @param [isBalanceAdd=true] - A boolean flag indicating whether the tree should be balanced after
308
- * adding the elements. If set to true, the tree will be balanced using a binary search tree
309
- * algorithm. If set to false, the elements will be added without balancing the tree. The default
310
- * value is true.
311
- * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that
312
- * specifies the type of iteration to use when adding multiple keys or nodes to the binary search
313
- * tree. It can have two possible values:
314
- * @returns The function `addMany` returns an array of booleans indicating whether each element was
315
- * successfully inserted into the data structure.
474
+ * Adds multiple items to the tree.
475
+ * @remarks If `isBalanceAdd` is true, sorts the input and builds a balanced tree. Time O(N log N) (due to sort and balanced add).
476
+ * If false, adds items one by one. Time O(N * H), which is O(N^2) worst-case.
477
+ * Space O(N) for sorting and recursion/iteration stack.
478
+ *
479
+ * @param keysNodesEntriesOrRaws - An iterable of items to add.
480
+ * @param [values] - An optional parallel iterable of values.
481
+ * @param [isBalanceAdd=true] - If true, builds a balanced tree from the items.
482
+ * @param [iterationType=this.iterationType] - The traversal method for balanced add (recursive or iterative).
483
+ * @returns An array of booleans indicating the success of each individual `add` operation.
316
484
  */
317
485
  addMany(keysNodesEntriesOrRaws, values, isBalanceAdd = true, iterationType = this.iterationType) {
318
486
  const inserted = [];
319
- let valuesIterator;
320
- if (values) {
321
- valuesIterator = values[Symbol.iterator]();
322
- }
487
+ const valuesIterator = values?.[Symbol.iterator]();
323
488
  if (!isBalanceAdd) {
489
+ // Standard O(N*H) insertion
324
490
  for (let kve of keysNodesEntriesOrRaws) {
325
- const value = valuesIterator?.next().value;
491
+ const val = valuesIterator?.next().value;
326
492
  if (this.isRaw(kve))
327
493
  kve = this._toEntryFn(kve);
328
- inserted.push(this.add(kve, value));
494
+ inserted.push(this.add(kve, val));
329
495
  }
330
496
  return inserted;
331
497
  }
498
+ // Balanced O(N log N) insertion
332
499
  const realBTNExemplars = [];
333
500
  let i = 0;
334
501
  for (const kve of keysNodesEntriesOrRaws) {
335
- realBTNExemplars.push({ key: kve, value: valuesIterator?.next().value, orgIndex: i });
336
- i++;
502
+ realBTNExemplars.push({ key: kve, value: valuesIterator?.next().value, orgIndex: i++ });
337
503
  }
338
- let sorted = [];
339
- sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => {
504
+ // Sort items by key
505
+ const sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => {
340
506
  let keyA, keyB;
341
507
  if (this.isRaw(a))
342
508
  keyA = this._toEntryFn(a)[0];
@@ -344,29 +510,26 @@ export class BST extends BinaryTree {
344
510
  keyA = a[0];
345
511
  else if (this.isRealNode(a))
346
512
  keyA = a.key;
347
- else {
513
+ else
348
514
  keyA = a;
349
- }
350
515
  if (this.isRaw(b))
351
516
  keyB = this._toEntryFn(b)[0];
352
517
  else if (this.isEntry(b))
353
518
  keyB = b[0];
354
519
  else if (this.isRealNode(b))
355
520
  keyB = b.key;
356
- else {
521
+ else
357
522
  keyB = b;
358
- }
359
- if (keyA !== undefined && keyA !== null && keyB !== undefined && keyB !== null) {
523
+ if (keyA != null && keyB != null)
360
524
  return this._compare(keyA, keyB);
361
- }
362
525
  return 0;
363
526
  });
527
+ // Recursive balanced build
364
528
  const _dfs = (arr) => {
365
529
  if (arr.length === 0)
366
530
  return;
367
531
  const mid = Math.floor((arr.length - 1) / 2);
368
- const { key, value } = arr[mid];
369
- const { orgIndex } = arr[mid];
532
+ const { key, value, orgIndex } = arr[mid];
370
533
  if (this.isRaw(key)) {
371
534
  const entry = this._toEntryFn(key);
372
535
  inserted[orgIndex] = this.add(entry);
@@ -377,280 +540,58 @@ export class BST extends BinaryTree {
377
540
  _dfs(arr.slice(0, mid));
378
541
  _dfs(arr.slice(mid + 1));
379
542
  };
543
+ // Iterative balanced build
380
544
  const _iterate = () => {
381
545
  const n = sorted.length;
382
546
  const stack = [[0, n - 1]];
383
547
  while (stack.length > 0) {
384
548
  const popped = stack.pop();
385
- if (popped) {
386
- const [l, r] = popped;
387
- if (l <= r) {
388
- const m = l + Math.floor((r - l) / 2);
389
- const { key, value } = sorted[m];
390
- const { orgIndex } = sorted[m];
391
- if (this.isRaw(key)) {
392
- const entry = this._toEntryFn(key);
393
- inserted[orgIndex] = this.add(entry);
394
- }
395
- else {
396
- inserted[orgIndex] = this.add(key, value);
397
- }
398
- stack.push([m + 1, r]);
399
- stack.push([l, m - 1]);
400
- }
549
+ if (!popped)
550
+ continue;
551
+ const [l, r] = popped;
552
+ if (l > r)
553
+ continue;
554
+ const m = l + Math.floor((r - l) / 2);
555
+ const { key, value, orgIndex } = sorted[m];
556
+ if (this.isRaw(key)) {
557
+ const entry = this._toEntryFn(key);
558
+ inserted[orgIndex] = this.add(entry);
559
+ }
560
+ else {
561
+ inserted[orgIndex] = this.add(key, value);
401
562
  }
563
+ stack.push([m + 1, r]);
564
+ stack.push([l, m - 1]);
402
565
  }
403
566
  };
404
- if (iterationType === 'RECURSIVE') {
567
+ if (iterationType === 'RECURSIVE')
405
568
  _dfs(sorted);
406
- }
407
- else {
569
+ else
408
570
  _iterate();
409
- }
410
571
  return inserted;
411
572
  }
412
573
  /**
413
- * Time Complexity: O(log n)
414
- * Space Complexity: O(k + log n)
415
- *
416
- * The function `search` in TypeScript overrides the search behavior in a binary tree structure based
417
- * on specified criteria.
418
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BSTNode<K, V>>} keyNodeEntryOrPredicate - The
419
- * `keyNodeEntryOrPredicate` parameter in the `override search` method can accept one of the
420
- * following types:
421
- * @param [onlyOne=false] - The `onlyOne` parameter is a boolean flag that determines whether the
422
- * search should stop after finding the first matching node. If `onlyOne` is set to `true`, the
423
- * search will return as soon as a matching node is found. If `onlyOne` is set to `false`, the
424
- * @param {C} callback - The `callback` parameter in the `override search` function is a function
425
- * that will be called on each node that matches the search criteria. It is of type `C`, which
426
- * extends `NodeCallback<BSTNode<K, V> | null>`. The callback function should accept a node of type `BSTNode<K, V>` as its
427
- * argument and
428
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `override search`
429
- * method represents the node from which the search operation will begin. It is the starting point
430
- * for searching within the tree data structure. The method ensures that the `startNode` is a valid
431
- * node before proceeding with the search operation. If the `
432
- * @param {IterationType} iterationType - The `iterationType` parameter in the `override search`
433
- * function determines the type of iteration to be used during the search operation. It can have two
434
- * possible values:
435
- * @returns The `override search` method returns an array of values that match the search criteria
436
- * specified by the input parameters. The method performs a search operation on a binary tree
437
- * structure based on the provided key, predicate, and other options. The search results are
438
- * collected in an array and returned as the output of the method.
439
- */
440
- search(keyNodeEntryOrPredicate, onlyOne = false, callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
441
- if (keyNodeEntryOrPredicate === undefined)
442
- return [];
443
- if (keyNodeEntryOrPredicate === null)
444
- return [];
445
- startNode = this.ensureNode(startNode);
446
- if (!startNode)
447
- return [];
448
- let predicate;
449
- const isRange = this.isRange(keyNodeEntryOrPredicate);
450
- // Set predicate based on parameter type
451
- if (isRange) {
452
- predicate = node => {
453
- if (!node)
454
- return false;
455
- return keyNodeEntryOrPredicate.isInRange(node.key, this._comparator);
456
- };
457
- }
458
- else {
459
- predicate = this._ensurePredicate(keyNodeEntryOrPredicate);
460
- }
461
- const shouldVisitLeft = (cur) => {
462
- if (!cur)
463
- return false;
464
- if (!this.isRealNode(cur.left))
465
- return false;
466
- if (isRange) {
467
- const range = keyNodeEntryOrPredicate;
468
- const leftS = this.isReverse ? range.high : range.low;
469
- const leftI = this.isReverse ? range.includeHigh : range.includeLow;
470
- return (leftI && this._compare(cur.key, leftS) >= 0) || (!leftI && this._compare(cur.key, leftS) > 0);
471
- }
472
- if (!isRange && !this._isPredicate(keyNodeEntryOrPredicate)) {
473
- const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
474
- return benchmarkKey !== null && benchmarkKey !== undefined && this._compare(cur.key, benchmarkKey) > 0;
475
- }
476
- return true;
477
- };
478
- const shouldVisitRight = (cur) => {
479
- if (!cur)
480
- return false;
481
- if (!this.isRealNode(cur.right))
482
- return false;
483
- if (isRange) {
484
- const range = keyNodeEntryOrPredicate;
485
- const rightS = this.isReverse ? range.low : range.high;
486
- const rightI = this.isReverse ? range.includeLow : range.includeLow;
487
- return (rightI && this._compare(cur.key, rightS) <= 0) || (!rightI && this._compare(cur.key, rightS) < 0);
488
- }
489
- if (!isRange && !this._isPredicate(keyNodeEntryOrPredicate)) {
490
- const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
491
- return benchmarkKey !== null && benchmarkKey !== undefined && this._compare(cur.key, benchmarkKey) < 0;
492
- }
493
- return true;
494
- };
495
- return super._dfs(callback, 'IN', onlyOne, startNode, iterationType, false, shouldVisitLeft, shouldVisitRight, () => true, cur => {
496
- if (cur)
497
- return predicate(cur);
498
- return false;
499
- });
500
- }
501
- /**
502
- * Time Complexity: O(log n)
503
- * Space Complexity: O(k + log n)
504
- *
505
- * The `rangeSearch` function searches for nodes within a specified range in a binary search tree.
506
- * @param {Range<K> | [K, K]} range - The `range` parameter in the `rangeSearch` function can be
507
- * either a `Range` object or an array of two elements representing the range boundaries.
508
- * @param {C} callback - The `callback` parameter in the `rangeSearch` function is a callback
509
- * function that is used to process each node that is found within the specified range during the
510
- * search operation. It is of type `NodeCallback<BSTNode<K, V> | null>`, where `BSTNode<K, V>` is the type of nodes in the
511
- * data structure.
512
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `rangeSearch`
513
- * function represents the node from which the search for nodes within the specified range will
514
- * begin. It is the starting point for the range search operation.
515
- * @param {IterationType} iterationType - The `iterationType` parameter in the `rangeSearch` function
516
- * is used to specify the type of iteration to be performed during the search operation. It has a
517
- * default value of `this.iterationType`, which suggests that it is likely a property of the class or
518
- * object that the `rangeSearch`
519
- * @returns The `rangeSearch` function is returning the result of calling the `search` method with
520
- * the specified parameters.
521
- */
522
- rangeSearch(range, callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
523
- const searchRange = range instanceof Range ? range : new Range(range[0], range[1]);
524
- return this.search(searchRange, false, callback, startNode, iterationType);
525
- }
526
- /**
527
- * Time Complexity: O(log n)
528
- * Space Complexity: O(log n)
529
- *
530
- * This function retrieves a node based on a given keyNodeEntryOrPredicate within a binary search tree structure.
531
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BSTNode<K, V>>} keyNodeEntryOrPredicate - The `keyNodeEntryOrPredicate`
532
- * parameter can be of type `K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `, `R`, or `NodePredicate<BSTNode<K, V>>`.
533
- * @param {BSTNOptKeyOrNode<K, BSTNode<K, V>>} startNode - The `startNode` parameter in the `getNode` method
534
- * is used to specify the starting point for searching nodes in the binary search tree. If no
535
- * specific starting point is provided, the default value is set to `this._root`, which is the root
536
- * node of the binary search tree.
537
- * @param {IterationType} iterationType - The `iterationType` parameter in the `getNode` method is a
538
- * parameter that specifies the type of iteration to be used. It has a default value of
539
- * `this.iterationType`, which means it will use the iteration type defined in the class instance if
540
- * no value is provided when calling the method.
541
- * @returns The `getNode` method is returning an optional binary search tree node (`OptNode<BSTNode<K, V>>`).
542
- * It is using the `getNodes` method to find the node based on the provided keyNodeEntryOrPredicate, beginning at
543
- * the specified root node (`startNode`) and using the specified iteration type. The method then
544
- * returns the first node found or `undefined` if no node is found.
545
- */
546
- getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
547
- return this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0] ?? undefined;
548
- }
549
- /**
550
- * Time complexity: O(n)
551
- * Space complexity: O(n)
552
- *
553
- * The function `dfs` in TypeScript overrides the base class method with default parameters and
554
- * returns the result of the super class `dfs` method.
555
- * @param {C} callback - The `callback` parameter is a function that will be called for each node
556
- * visited during the Depth-First Search traversal. It is a generic type `C` that extends the
557
- * `NodeCallback` interface for `BSTNode<K, V>`. The default value for `callback` is `this._
558
- * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `override dfs` method
559
- * specifies the order in which the Depth-First Search (DFS) traversal should be performed on the
560
- * Binary Search Tree (BST). The possible values for the `pattern` parameter are:
561
- * @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `override dfs` method is a
562
- * boolean flag that indicates whether you want to stop the depth-first search traversal after
563
- * finding the first matching node or continue searching for all matching nodes. If `onlyOne` is set
564
- * to `true`, the traversal will stop after finding
565
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} startNode -
566
- * The `startNode` parameter in the `override dfs` method can be one of the following types:
567
- * @param {IterationType} iterationType - The `iterationType` parameter in the `override dfs` method
568
- * specifies the type of iteration to be performed during the Depth-First Search (DFS) traversal of a
569
- * Binary Search Tree (BST). It is used to determine the order in which nodes are visited during the
570
- * traversal. The possible values for `
571
- * @returns The `override` function is returning the result of calling the `dfs` method from the
572
- * superclass, with the provided arguments `callback`, `pattern`, `onlyOne`, `startNode`, and
573
- * `iterationType`. The return type is an array of the return type of the callback function `C`.
574
- */
575
- dfs(callback = this._DEFAULT_NODE_CALLBACK, pattern = 'IN', onlyOne = false, startNode = this._root, iterationType = this.iterationType) {
576
- return super.dfs(callback, pattern, onlyOne, startNode, iterationType);
577
- }
578
- /**
579
- * Time complexity: O(n)
580
- * Space complexity: O(n)
581
- *
582
- * The function overrides the breadth-first search method and returns an array of the return types of
583
- * the callback function.
584
- * @param {C} callback - The `callback` parameter is a function that will be called for each node
585
- * visited during the breadth-first search. It should take a single argument, which is the current
586
- * node being visited, and it can return a value of any type.
587
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting
588
- * point for the breadth-first search. It can be either a root node, a key-value pair, or an entry
589
- * object. If no value is provided, the default value is the root of the tree.
590
- * @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type
591
- * of iteration to be performed during the breadth-first search (BFS) traversal. It can have one of
592
- * the following values:
593
- * @returns an array of the return type of the callback function.
594
- */
595
- bfs(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
596
- return super.bfs(callback, startNode, iterationType, false);
597
- }
598
- /**
599
- * Time complexity: O(n)
600
- * Space complexity: O(n)
574
+ * Traverses the tree and returns nodes that are lesser or greater than a target node.
575
+ * @remarks Time O(N), as it performs a full traversal. Space O(log N) or O(N).
601
576
  *
602
- * The function overrides the listLevels method from the superclass and returns an array of arrays
603
- * containing the results of the callback function applied to each level of the tree.
604
- * @param {C} callback - The `callback` parameter is a generic type `C` that extends
605
- * `NodeCallback<BSTNode<K, V> | null>`. It represents a callback function that will be called for each node in the
606
- * tree during the iteration process.
607
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting
608
- * point for listing the levels of the binary tree. It can be either a root node of the tree, a
609
- * key-value pair representing a node in the tree, or a key representing a node in the tree. If no
610
- * value is provided, the root of
611
- * @param {IterationType} iterationType - The `iterationType` parameter is used to specify the type
612
- * of iteration to be performed on the tree. It can have one of the following values:
613
- * @returns The method is returning a two-dimensional array of the return type of the callback
614
- * function.
615
- */
616
- listLevels(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
617
- return super.listLevels(callback, startNode, iterationType, false);
618
- }
619
- /**
620
- * Time complexity: O(n)
621
- * Space complexity: O(n)
622
- *
623
- * The `lesserOrGreaterTraverse` function traverses a binary tree and applies a callback function to
624
- * each node that meets a certain condition based on a target node and a comparison value.
625
- * @param {C} callback - The `callback` parameter is a function that will be called for each node
626
- * that meets the condition specified by the `lesserOrGreater` parameter. It takes a single argument,
627
- * which is the current node being traversed, and returns a value of any type.
628
- * @param {CP} lesserOrGreater - The `lesserOrGreater` parameter is used to determine whether to
629
- * traverse nodes that are lesser, greater, or both than the `targetNode`. It accepts the values -1,
630
- * 0, or 1, where:
631
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } targetNode - The `targetNode` parameter is the node in
632
- * the binary tree that you want to start traversing from. It can be specified either by providing
633
- * the key of the node, the node itself, or an entry containing the key and value of the node. If no
634
- * `targetNode` is provided,
635
- * @param {IterationType} iterationType - The `iterationType` parameter determines the type of
636
- * traversal to be performed on the binary tree. It can have two possible values:
637
- * @returns The function `lesserOrGreaterTraverse` returns an array of values of type
638
- * `ReturnType<C>`, which is the return type of the callback function passed as an argument.
577
+ * @template C - The type of the callback function.
578
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on matching nodes.
579
+ * @param [lesserOrGreater=-1] - -1 for lesser, 1 for greater, 0 for equal.
580
+ * @param [targetNode=this._root] - The node to compare against.
581
+ * @param [iterationType=this.iterationType] - The traversal method.
582
+ * @returns An array of callback results.
639
583
  */
640
584
  lesserOrGreaterTraverse(callback = this._DEFAULT_NODE_CALLBACK, lesserOrGreater = -1, targetNode = this._root, iterationType = this.iterationType) {
641
585
  const targetNodeEnsured = this.ensureNode(targetNode);
642
586
  const ans = [];
643
- if (!this._root)
644
- return ans;
645
- if (!targetNodeEnsured)
587
+ if (!this._root || !targetNodeEnsured)
646
588
  return ans;
647
589
  const targetKey = targetNodeEnsured.key;
648
590
  if (iterationType === 'RECURSIVE') {
649
591
  const dfs = (cur) => {
650
592
  const compared = this._compare(cur.key, targetKey);
651
- if (Math.sign(compared) === lesserOrGreater)
593
+ if (Math.sign(compared) == lesserOrGreater)
652
594
  ans.push(callback(cur));
653
- // TODO here can be optimized to O(log n)
654
595
  if (this.isRealNode(cur.left))
655
596
  dfs(cur.left);
656
597
  if (this.isRealNode(cur.right))
@@ -665,7 +606,7 @@ export class BST extends BinaryTree {
665
606
  const cur = queue.shift();
666
607
  if (this.isRealNode(cur)) {
667
608
  const compared = this._compare(cur.key, targetKey);
668
- if (Math.sign(compared) === lesserOrGreater)
609
+ if (Math.sign(compared) == lesserOrGreater)
669
610
  ans.push(callback(cur));
670
611
  if (this.isRealNode(cur.left))
671
612
  queue.push(cur.left);
@@ -677,80 +618,54 @@ export class BST extends BinaryTree {
677
618
  }
678
619
  }
679
620
  /**
680
- * Time complexity: O(n)
681
- * Space complexity: O(n)
621
+ * Rebuilds the tree to be perfectly balanced.
622
+ * @remarks Time O(N) (O(N) for DFS, O(N) for sorted build). Space O(N) for node array and recursion stack.
682
623
  *
683
- * The `perfectlyBalance` function takes an optional `iterationType` parameter and returns `true` if
684
- * the binary search tree is perfectly balanced, otherwise it returns `false`.
685
- * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that
686
- * specifies the type of iteration to use when building a balanced binary search tree. It has a
687
- * default value of `this.iterationType`, which means it will use the iteration type specified in the
688
- * current instance of the class.
689
- * @returns The function `perfectlyBalance` returns a boolean value.
624
+ * @param [iterationType=this.iterationType] - The traversal method for the initial node export.
625
+ * @returns True if successful, false if the tree was empty.
690
626
  */
691
627
  perfectlyBalance(iterationType = this.iterationType) {
692
- const sorted = this.dfs(node => node, 'IN'), n = sorted.length;
628
+ const nodes = this.dfs(node => node, 'IN', false, this._root, iterationType);
629
+ const n = nodes.length;
693
630
  this._clearNodes();
694
- if (sorted.length < 1)
631
+ if (n === 0)
695
632
  return false;
696
- if (iterationType === 'RECURSIVE') {
697
- const buildBalanceBST = (l, r) => {
698
- if (l > r)
699
- return;
700
- const m = l + Math.floor((r - l) / 2);
701
- const midNode = sorted[m];
702
- if (this._isMapMode && midNode !== null)
703
- this.add(midNode.key);
704
- else if (midNode !== null)
705
- this.add([midNode.key, midNode.value]);
706
- buildBalanceBST(l, m - 1);
707
- buildBalanceBST(m + 1, r);
708
- };
709
- buildBalanceBST(0, n - 1);
710
- return true;
711
- }
712
- else {
713
- const stack = [[0, n - 1]];
714
- while (stack.length > 0) {
715
- const popped = stack.pop();
716
- if (popped) {
717
- const [l, r] = popped;
718
- if (l <= r) {
719
- const m = l + Math.floor((r - l) / 2);
720
- const midNode = sorted[m];
721
- if (this._isMapMode && midNode !== null)
722
- this.add(midNode.key);
723
- else if (midNode !== null)
724
- this.add([midNode.key, midNode.value]);
725
- stack.push([m + 1, r]);
726
- stack.push([l, m - 1]);
727
- }
728
- }
729
- }
730
- return true;
731
- }
633
+ // Build balanced tree from sorted array
634
+ const build = (l, r, parent) => {
635
+ if (l > r)
636
+ return undefined;
637
+ const m = l + ((r - l) >> 1);
638
+ const root = nodes[m];
639
+ const leftChild = build(l, m - 1, root);
640
+ const rightChild = build(m + 1, r, root);
641
+ root.left = leftChild;
642
+ root.right = rightChild;
643
+ root.parent = parent;
644
+ return root;
645
+ };
646
+ const newRoot = build(0, n - 1, undefined);
647
+ this._setRoot(newRoot);
648
+ this._size = n;
649
+ return true;
732
650
  }
733
651
  /**
734
- * Time Complexity: O(n)
735
- * Space Complexity: O(log n)
652
+ * Checks if the tree meets the AVL balance condition (height difference <= 1).
653
+ * @remarks Time O(N), as it must visit every node to compute height. Space O(log N) for recursion or O(N) for iterative map.
736
654
  *
737
- * The function `isAVLBalanced` checks if a binary tree is AVL balanced using either a recursive or
738
- * iterative approach.
739
- * @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that
740
- * specifies the type of iteration to use when checking if the AVL tree is balanced. It has a default
741
- * value of `this.iterationType`, which means it will use the iteration type specified in the current
742
- * instance of the AVL tree.
743
- * @returns a boolean value.
655
+ * @param [iterationType=this.iterationType] - The traversal method.
656
+ * @returns True if the tree is AVL balanced, false otherwise.
744
657
  */
745
658
  isAVLBalanced(iterationType = this.iterationType) {
746
659
  if (!this._root)
747
660
  return true;
748
661
  let balanced = true;
749
662
  if (iterationType === 'RECURSIVE') {
663
+ // Recursive height check
750
664
  const _height = (cur) => {
751
665
  if (!cur)
752
666
  return 0;
753
- const leftHeight = _height(cur.left), rightHeight = _height(cur.right);
667
+ const leftHeight = _height(cur.left);
668
+ const rightHeight = _height(cur.right);
754
669
  if (Math.abs(leftHeight - rightHeight) > 1)
755
670
  balanced = false;
756
671
  return Math.max(leftHeight, rightHeight) + 1;
@@ -758,6 +673,7 @@ export class BST extends BinaryTree {
758
673
  _height(this._root);
759
674
  }
760
675
  else {
676
+ // Iterative post-order height check
761
677
  const stack = [];
762
678
  let node = this._root, last = undefined;
763
679
  const depths = new Map();
@@ -789,93 +705,197 @@ export class BST extends BinaryTree {
789
705
  return balanced;
790
706
  }
791
707
  /**
792
- * Time complexity: O(n)
793
- * Space complexity: O(n)
794
- *
795
- * The `map` function in TypeScript overrides the default map behavior for a binary search tree by
796
- * applying a callback function to each entry and creating a new tree with the results.
797
- * @param callback - A function that will be called for each entry in the BST. It takes four
798
- * arguments: the key, the value (which can be undefined), the index of the entry, and a reference to
799
- * the BST itself.
800
- * @param [options] - The `options` parameter in the `override map` method is of type `BSTOptions<MK,
801
- * MV, MR>`. It is an optional parameter that allows you to specify additional options for the Binary
802
- * Search Tree (BST) being created in the `map` method. These options could include configuration
803
- * @param {any} [thisArg] - The `thisArg` parameter in the `override map` method is used to specify
804
- * the value of `this` that should be used when executing the `callback` function. It allows you to
805
- * set the context or scope in which the callback function will be called. This can be useful when
806
- * you want
807
- * @returns The `map` method is returning a new Binary Search Tree (`BST`) instance with the entries
808
- * transformed by the provided callback function.
708
+ * Creates a new BST by mapping each [key, value] pair to a new entry.
709
+ * @remarks Time O(N * H), where N is nodes in this tree, and H is height of the new tree during insertion.
710
+ * Space O(N) for the new tree.
711
+ *
712
+ * @template MK - New key type.
713
+ * @template MV - New value type.
714
+ * @template MR - New raw type.
715
+ * @param callback - A function to map each [key, value] pair.
716
+ * @param [options] - Options for the new BST.
717
+ * @param [thisArg] - `this` context for the callback.
718
+ * @returns A new, mapped BST.
809
719
  */
810
720
  map(callback, options, thisArg) {
811
- const newTree = new BST([], options);
721
+ const out = this._createLike([], options);
812
722
  let index = 0;
723
+ // Iterates in-order
813
724
  for (const [key, value] of this) {
814
- newTree.add(callback.call(thisArg, key, value, index++, this));
725
+ out.add(callback.call(thisArg, key, value, index++, this));
815
726
  }
816
- return newTree;
727
+ return out;
817
728
  }
818
729
  /**
819
- * Time complexity: O(n)
820
- * Space complexity: O(n)
730
+ * Deletes the first node found that satisfies the predicate.
731
+ * @remarks Performs an in-order traversal. Time O(N) worst-case (O(log N) to find + O(log N) to delete). Space O(log N) for stack.
821
732
  *
822
- * The function `clone` overrides the default cloning behavior to create a deep copy of a tree
823
- * structure.
824
- * @returns The `cloned` object is being returned.
733
+ * @param predicate - A function to test each [key, value] pair.
734
+ * @returns True if a node was deleted, false otherwise.
825
735
  */
826
- clone() {
827
- const cloned = this.createTree();
828
- this._clone(cloned);
829
- return cloned;
736
+ deleteWhere(predicate) {
737
+ const stack = [];
738
+ let cur = this._root;
739
+ let index = 0;
740
+ // In-order traversal to find the node
741
+ while (stack.length > 0 || cur !== undefined) {
742
+ while (cur !== undefined && cur !== null) {
743
+ stack.push(cur);
744
+ cur = cur.left;
745
+ }
746
+ const node = stack.pop();
747
+ if (!node)
748
+ break;
749
+ const key = node.key;
750
+ const val = node.value;
751
+ if (predicate(key, val, index++, this)) {
752
+ return this._deleteByKey(key); // Found, now delete
753
+ }
754
+ cur = node.right;
755
+ }
756
+ return false;
757
+ }
758
+ /**
759
+ * (Protected) Creates a new, empty instance of the same BST constructor.
760
+ * @remarks Time O(1)
761
+ *
762
+ * @template TK, TV, TR - Generic types for the new instance.
763
+ * @param [options] - Options for the new BST.
764
+ * @returns A new, empty BST.
765
+ */
766
+ _createInstance(options) {
767
+ const Ctor = this.constructor;
768
+ return new Ctor([], { ...this._snapshotOptions(), ...(options ?? {}) });
769
+ }
770
+ /**
771
+ * (Protected) Creates a new instance of the same BST constructor, potentially with different generic types.
772
+ * @remarks Time O(N log N) or O(N^2) (from constructor) due to processing the iterable.
773
+ *
774
+ * @template TK, TV, TR - Generic types for the new instance.
775
+ * @param [iter=[]] - An iterable to populate the new BST.
776
+ * @param [options] - Options for the new BST.
777
+ * @returns A new BST.
778
+ */
779
+ _createLike(iter = [], options) {
780
+ const Ctor = this.constructor;
781
+ return new Ctor(iter, { ...this._snapshotOptions(), ...(options ?? {}) });
782
+ }
783
+ /**
784
+ * (Protected) Snapshots the current BST's configuration options.
785
+ * @remarks Time O(1)
786
+ *
787
+ * @template TK, TV, TR - Generic types for the options.
788
+ * @returns The options object.
789
+ */
790
+ _snapshotOptions() {
791
+ return {
792
+ ...super._snapshotOptions(),
793
+ specifyComparable: this.specifyComparable,
794
+ isReverse: this.isReverse
795
+ };
830
796
  }
831
797
  /**
832
- * Time Complexity: O(1)
833
- * Space Complexity: O(1)
798
+ * (Protected) Converts a key, node, or entry into a standardized [node, value] tuple.
799
+ * @remarks Time O(1)
834
800
  *
835
- * The function overrides a method and converts a key, value pair or entry or raw element to a node.
836
- * @param {K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - A variable that can be of
837
- * type R or K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined . It represents either a key, a node, an entry, or a raw
838
- * element.
839
- * @param {V} [value] - The `value` parameter is an optional value of type `V`. It represents the
840
- * value associated with a key in a key-value pair.
841
- * @returns either a BSTNode<K, V> object or undefined.
801
+ * @param keyNodeOrEntry - The input item.
802
+ * @param [value] - An optional value (used if input is just a key).
803
+ * @returns A tuple of [node, value].
842
804
  */
843
805
  _keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value) {
844
806
  const [node, entryValue] = super._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
845
807
  if (node === null)
846
- return [undefined, undefined];
808
+ return [undefined, undefined]; // BST handles null differently (as undefined)
847
809
  return [node, value ?? entryValue];
848
810
  }
849
811
  /**
850
- * Time Complexity: O(1)
851
- * Space Complexity: O(1)
812
+ * (Protected) Sets the root node and clears its parent reference.
813
+ * @remarks Time O(1)
852
814
  *
853
- * The function sets the root of a tree-like structure and updates the parent property of the new
854
- * root.
855
- * @param {OptNode<BSTNode<K, V>>} v - v is a parameter of type BSTNode<K, V> or undefined.
815
+ * @param v - The node to set as root.
856
816
  */
857
817
  _setRoot(v) {
858
- if (v) {
818
+ if (v)
859
819
  v.parent = undefined;
860
- }
861
820
  this._root = v;
862
821
  }
863
822
  /**
864
- * Time Complexity: O(1)
865
- * Space Complexity: O(1)
823
+ * (Protected) Compares two keys using the tree's comparator and reverse setting.
824
+ * @remarks Time O(1) (or O(C) if `specifyComparable` is used).
866
825
  *
867
- * The _compare function compares two values using a specified comparator function and optionally
868
- * reverses the result.
869
- * @param {K} a - The parameter `a` is of type `K`, which is used as an input for comparison in the
870
- * `_compare` method.
871
- * @param {K} b - The parameter `b` in the `_compare` function is of type `K`.
872
- * @returns The `_compare` method is returning the result of the ternary expression. If `_isReverse`
873
- * is true, it returns the negation of the result of calling the `_comparator` function with
874
- * arguments `a` and `b`. If `_isReverse` is false, it returns the result of calling the
875
- * `_comparator` function with arguments `a` and `b`.
826
+ * @param a - The first key.
827
+ * @param b - The second key.
828
+ * @returns A number (1, -1, or 0) representing the comparison.
876
829
  */
877
830
  _compare(a, b) {
878
831
  return this._isReverse ? -this._comparator(a, b) : this._comparator(a, b);
879
832
  }
833
+ /**
834
+ * (Private) Deletes a node by its key.
835
+ * @remarks Standard BST deletion algorithm. Time O(log N), O(N) worst-case. Space O(1).
836
+ *
837
+ * @param key - The key of the node to delete.
838
+ * @returns True if the node was found and deleted, false otherwise.
839
+ */
840
+ _deleteByKey(key) {
841
+ let node = this._root;
842
+ // 1. Find the node
843
+ while (node) {
844
+ const cmp = this._compare(node.key, key);
845
+ if (cmp === 0)
846
+ break;
847
+ node = cmp > 0 ? node.left : node.right;
848
+ }
849
+ if (!node)
850
+ return false; // Not found
851
+ // Helper to replace node `u` with node `v`
852
+ const transplant = (u, v) => {
853
+ const p = u?.parent;
854
+ if (!p) {
855
+ this._setRoot(v);
856
+ }
857
+ else if (p.left === u) {
858
+ p.left = v;
859
+ }
860
+ else {
861
+ p.right = v;
862
+ }
863
+ if (v)
864
+ v.parent = p;
865
+ };
866
+ // Helper to find the minimum node in a subtree
867
+ const minNode = (x) => {
868
+ if (!x)
869
+ return undefined;
870
+ while (x.left !== undefined && x.left !== null)
871
+ x = x.left;
872
+ return x;
873
+ };
874
+ // 2. Perform deletion
875
+ if (node.left === undefined) {
876
+ // Case 1: No left child
877
+ transplant(node, node.right);
878
+ }
879
+ else if (node.right === undefined) {
880
+ // Case 2: No right child
881
+ transplant(node, node.left);
882
+ }
883
+ else {
884
+ // Case 3: Two children
885
+ const succ = minNode(node.right); // Find successor
886
+ if (succ.parent !== node) {
887
+ transplant(succ, succ.right);
888
+ succ.right = node.right;
889
+ if (succ.right)
890
+ succ.right.parent = succ;
891
+ }
892
+ transplant(node, succ);
893
+ succ.left = node.left;
894
+ if (succ.left)
895
+ succ.left.parent = succ;
896
+ }
897
+ this._size = Math.max(0, (this._size ?? 0) - 1);
898
+ return true;
899
+ }
880
900
  }
881
901
  //# sourceMappingURL=bst.js.map