data-structure-typed 2.0.5 → 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 (260) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/COMMANDS.md +17 -0
  3. package/benchmark/report.html +13 -77
  4. package/benchmark/report.json +145 -177
  5. package/dist/cjs/data-structures/base/iterable-element-base.d.ts +186 -83
  6. package/dist/cjs/data-structures/base/iterable-element-base.js +149 -107
  7. package/dist/cjs/data-structures/base/iterable-element-base.js.map +1 -1
  8. package/dist/cjs/data-structures/base/iterable-entry-base.d.ts +95 -119
  9. package/dist/cjs/data-structures/base/iterable-entry-base.js +59 -116
  10. package/dist/cjs/data-structures/base/iterable-entry-base.js.map +1 -1
  11. package/dist/cjs/data-structures/base/linear-base.d.ts +250 -192
  12. package/dist/cjs/data-structures/base/linear-base.js +137 -274
  13. package/dist/cjs/data-structures/base/linear-base.js.map +1 -1
  14. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
  15. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js +171 -205
  16. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
  17. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
  18. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
  19. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  20. package/dist/cjs/data-structures/binary-tree/avl-tree.d.ts +138 -149
  21. package/dist/cjs/data-structures/binary-tree/avl-tree.js +208 -195
  22. package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
  23. package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +476 -632
  24. package/dist/cjs/data-structures/binary-tree/binary-tree.js +594 -865
  25. package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  26. package/dist/cjs/data-structures/binary-tree/bst.d.ts +258 -306
  27. package/dist/cjs/data-structures/binary-tree/bst.js +505 -481
  28. package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
  29. package/dist/cjs/data-structures/binary-tree/red-black-tree.d.ts +107 -179
  30. package/dist/cjs/data-structures/binary-tree/red-black-tree.js +114 -209
  31. package/dist/cjs/data-structures/binary-tree/red-black-tree.js.map +1 -1
  32. package/dist/cjs/data-structures/binary-tree/tree-counter.d.ts +132 -154
  33. package/dist/cjs/data-structures/binary-tree/tree-counter.js +172 -203
  34. package/dist/cjs/data-structures/binary-tree/tree-counter.js.map +1 -1
  35. package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
  36. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +105 -85
  37. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  38. package/dist/cjs/data-structures/graph/abstract-graph.d.ts +238 -233
  39. package/dist/cjs/data-structures/graph/abstract-graph.js +267 -237
  40. package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
  41. package/dist/cjs/data-structures/graph/directed-graph.d.ts +108 -224
  42. package/dist/cjs/data-structures/graph/directed-graph.js +146 -233
  43. package/dist/cjs/data-structures/graph/directed-graph.js.map +1 -1
  44. package/dist/cjs/data-structures/graph/map-graph.d.ts +49 -55
  45. package/dist/cjs/data-structures/graph/map-graph.js +56 -59
  46. package/dist/cjs/data-structures/graph/map-graph.js.map +1 -1
  47. package/dist/cjs/data-structures/graph/undirected-graph.d.ts +103 -146
  48. package/dist/cjs/data-structures/graph/undirected-graph.js +129 -149
  49. package/dist/cjs/data-structures/graph/undirected-graph.js.map +1 -1
  50. package/dist/cjs/data-structures/hash/hash-map.d.ts +164 -338
  51. package/dist/cjs/data-structures/hash/hash-map.js +270 -457
  52. package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
  53. package/dist/cjs/data-structures/heap/heap.d.ts +214 -289
  54. package/dist/cjs/data-structures/heap/heap.js +340 -349
  55. package/dist/cjs/data-structures/heap/heap.js.map +1 -1
  56. package/dist/cjs/data-structures/heap/max-heap.d.ts +11 -47
  57. package/dist/cjs/data-structures/heap/max-heap.js +11 -66
  58. package/dist/cjs/data-structures/heap/max-heap.js.map +1 -1
  59. package/dist/cjs/data-structures/heap/min-heap.d.ts +12 -47
  60. package/dist/cjs/data-structures/heap/min-heap.js +11 -66
  61. package/dist/cjs/data-structures/heap/min-heap.js.map +1 -1
  62. package/dist/cjs/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
  63. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js +368 -494
  64. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  65. package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +261 -310
  66. package/dist/cjs/data-structures/linked-list/singly-linked-list.js +447 -466
  67. package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
  68. package/dist/cjs/data-structures/linked-list/skip-linked-list.d.ts +0 -107
  69. package/dist/cjs/data-structures/linked-list/skip-linked-list.js +0 -100
  70. package/dist/cjs/data-structures/linked-list/skip-linked-list.js.map +1 -1
  71. package/dist/cjs/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
  72. package/dist/cjs/data-structures/priority-queue/max-priority-queue.js +11 -78
  73. package/dist/cjs/data-structures/priority-queue/max-priority-queue.js.map +1 -1
  74. package/dist/cjs/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
  75. package/dist/cjs/data-structures/priority-queue/min-priority-queue.js +10 -79
  76. package/dist/cjs/data-structures/priority-queue/min-priority-queue.js.map +1 -1
  77. package/dist/cjs/data-structures/priority-queue/priority-queue.d.ts +2 -61
  78. package/dist/cjs/data-structures/priority-queue/priority-queue.js +8 -83
  79. package/dist/cjs/data-structures/priority-queue/priority-queue.js.map +1 -1
  80. package/dist/cjs/data-structures/queue/deque.d.ts +227 -254
  81. package/dist/cjs/data-structures/queue/deque.js +309 -348
  82. package/dist/cjs/data-structures/queue/deque.js.map +1 -1
  83. package/dist/cjs/data-structures/queue/queue.d.ts +180 -201
  84. package/dist/cjs/data-structures/queue/queue.js +265 -248
  85. package/dist/cjs/data-structures/queue/queue.js.map +1 -1
  86. package/dist/cjs/data-structures/stack/stack.d.ts +124 -102
  87. package/dist/cjs/data-structures/stack/stack.js +181 -125
  88. package/dist/cjs/data-structures/stack/stack.js.map +1 -1
  89. package/dist/cjs/data-structures/trie/trie.d.ts +164 -165
  90. package/dist/cjs/data-structures/trie/trie.js +189 -172
  91. package/dist/cjs/data-structures/trie/trie.js.map +1 -1
  92. package/dist/cjs/interfaces/binary-tree.d.ts +56 -6
  93. package/dist/cjs/interfaces/graph.d.ts +16 -0
  94. package/dist/cjs/types/data-structures/base/base.d.ts +1 -1
  95. package/dist/cjs/types/data-structures/graph/abstract-graph.d.ts +4 -0
  96. package/dist/cjs/types/utils/utils.d.ts +1 -0
  97. package/dist/cjs/utils/utils.d.ts +1 -1
  98. package/dist/cjs/utils/utils.js +2 -1
  99. package/dist/cjs/utils/utils.js.map +1 -1
  100. package/dist/esm/data-structures/base/iterable-element-base.d.ts +186 -83
  101. package/dist/esm/data-structures/base/iterable-element-base.js +155 -107
  102. package/dist/esm/data-structures/base/iterable-element-base.js.map +1 -1
  103. package/dist/esm/data-structures/base/iterable-entry-base.d.ts +95 -119
  104. package/dist/esm/data-structures/base/iterable-entry-base.js +59 -116
  105. package/dist/esm/data-structures/base/iterable-entry-base.js.map +1 -1
  106. package/dist/esm/data-structures/base/linear-base.d.ts +250 -192
  107. package/dist/esm/data-structures/base/linear-base.js +137 -274
  108. package/dist/esm/data-structures/base/linear-base.js.map +1 -1
  109. package/dist/esm/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
  110. package/dist/esm/data-structures/binary-tree/avl-tree-counter.js +171 -212
  111. package/dist/esm/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
  112. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
  113. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js +133 -94
  114. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  115. package/dist/esm/data-structures/binary-tree/avl-tree.d.ts +138 -149
  116. package/dist/esm/data-structures/binary-tree/avl-tree.js +206 -200
  117. package/dist/esm/data-structures/binary-tree/avl-tree.js.map +1 -1
  118. package/dist/esm/data-structures/binary-tree/binary-tree.d.ts +476 -632
  119. package/dist/esm/data-structures/binary-tree/binary-tree.js +598 -874
  120. package/dist/esm/data-structures/binary-tree/binary-tree.js.map +1 -1
  121. package/dist/esm/data-structures/binary-tree/bst.d.ts +258 -306
  122. package/dist/esm/data-structures/binary-tree/bst.js +507 -487
  123. package/dist/esm/data-structures/binary-tree/bst.js.map +1 -1
  124. package/dist/esm/data-structures/binary-tree/red-black-tree.d.ts +107 -179
  125. package/dist/esm/data-structures/binary-tree/red-black-tree.js +114 -215
  126. package/dist/esm/data-structures/binary-tree/red-black-tree.js.map +1 -1
  127. package/dist/esm/data-structures/binary-tree/tree-counter.d.ts +132 -154
  128. package/dist/esm/data-structures/binary-tree/tree-counter.js +175 -209
  129. package/dist/esm/data-structures/binary-tree/tree-counter.js.map +1 -1
  130. package/dist/esm/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
  131. package/dist/esm/data-structures/binary-tree/tree-multi-map.js +103 -92
  132. package/dist/esm/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  133. package/dist/esm/data-structures/graph/abstract-graph.d.ts +238 -233
  134. package/dist/esm/data-structures/graph/abstract-graph.js +267 -237
  135. package/dist/esm/data-structures/graph/abstract-graph.js.map +1 -1
  136. package/dist/esm/data-structures/graph/directed-graph.d.ts +108 -224
  137. package/dist/esm/data-structures/graph/directed-graph.js +145 -233
  138. package/dist/esm/data-structures/graph/directed-graph.js.map +1 -1
  139. package/dist/esm/data-structures/graph/map-graph.d.ts +49 -55
  140. package/dist/esm/data-structures/graph/map-graph.js +56 -59
  141. package/dist/esm/data-structures/graph/map-graph.js.map +1 -1
  142. package/dist/esm/data-structures/graph/undirected-graph.d.ts +103 -146
  143. package/dist/esm/data-structures/graph/undirected-graph.js +128 -149
  144. package/dist/esm/data-structures/graph/undirected-graph.js.map +1 -1
  145. package/dist/esm/data-structures/hash/hash-map.d.ts +164 -338
  146. package/dist/esm/data-structures/hash/hash-map.js +270 -457
  147. package/dist/esm/data-structures/hash/hash-map.js.map +1 -1
  148. package/dist/esm/data-structures/heap/heap.d.ts +214 -289
  149. package/dist/esm/data-structures/heap/heap.js +329 -349
  150. package/dist/esm/data-structures/heap/heap.js.map +1 -1
  151. package/dist/esm/data-structures/heap/max-heap.d.ts +11 -47
  152. package/dist/esm/data-structures/heap/max-heap.js +11 -66
  153. package/dist/esm/data-structures/heap/max-heap.js.map +1 -1
  154. package/dist/esm/data-structures/heap/min-heap.d.ts +12 -47
  155. package/dist/esm/data-structures/heap/min-heap.js +11 -66
  156. package/dist/esm/data-structures/heap/min-heap.js.map +1 -1
  157. package/dist/esm/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
  158. package/dist/esm/data-structures/linked-list/doubly-linked-list.js +368 -495
  159. package/dist/esm/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  160. package/dist/esm/data-structures/linked-list/singly-linked-list.d.ts +261 -310
  161. package/dist/esm/data-structures/linked-list/singly-linked-list.js +448 -467
  162. package/dist/esm/data-structures/linked-list/singly-linked-list.js.map +1 -1
  163. package/dist/esm/data-structures/linked-list/skip-linked-list.d.ts +0 -107
  164. package/dist/esm/data-structures/linked-list/skip-linked-list.js +0 -100
  165. package/dist/esm/data-structures/linked-list/skip-linked-list.js.map +1 -1
  166. package/dist/esm/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
  167. package/dist/esm/data-structures/priority-queue/max-priority-queue.js +11 -78
  168. package/dist/esm/data-structures/priority-queue/max-priority-queue.js.map +1 -1
  169. package/dist/esm/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
  170. package/dist/esm/data-structures/priority-queue/min-priority-queue.js +10 -79
  171. package/dist/esm/data-structures/priority-queue/min-priority-queue.js.map +1 -1
  172. package/dist/esm/data-structures/priority-queue/priority-queue.d.ts +2 -61
  173. package/dist/esm/data-structures/priority-queue/priority-queue.js +8 -83
  174. package/dist/esm/data-structures/priority-queue/priority-queue.js.map +1 -1
  175. package/dist/esm/data-structures/queue/deque.d.ts +227 -254
  176. package/dist/esm/data-structures/queue/deque.js +313 -348
  177. package/dist/esm/data-structures/queue/deque.js.map +1 -1
  178. package/dist/esm/data-structures/queue/queue.d.ts +180 -201
  179. package/dist/esm/data-structures/queue/queue.js +263 -248
  180. package/dist/esm/data-structures/queue/queue.js.map +1 -1
  181. package/dist/esm/data-structures/stack/stack.d.ts +124 -102
  182. package/dist/esm/data-structures/stack/stack.js +181 -125
  183. package/dist/esm/data-structures/stack/stack.js.map +1 -1
  184. package/dist/esm/data-structures/trie/trie.d.ts +164 -165
  185. package/dist/esm/data-structures/trie/trie.js +193 -172
  186. package/dist/esm/data-structures/trie/trie.js.map +1 -1
  187. package/dist/esm/interfaces/binary-tree.d.ts +56 -6
  188. package/dist/esm/interfaces/graph.d.ts +16 -0
  189. package/dist/esm/types/data-structures/base/base.d.ts +1 -1
  190. package/dist/esm/types/data-structures/graph/abstract-graph.d.ts +4 -0
  191. package/dist/esm/types/utils/utils.d.ts +1 -0
  192. package/dist/esm/utils/utils.d.ts +1 -1
  193. package/dist/esm/utils/utils.js +2 -1
  194. package/dist/esm/utils/utils.js.map +1 -1
  195. package/dist/umd/data-structure-typed.js +4685 -6477
  196. package/dist/umd/data-structure-typed.min.js +8 -6
  197. package/dist/umd/data-structure-typed.min.js.map +1 -1
  198. package/package.json +3 -4
  199. package/src/data-structures/base/iterable-element-base.ts +238 -115
  200. package/src/data-structures/base/iterable-entry-base.ts +96 -120
  201. package/src/data-structures/base/linear-base.ts +271 -277
  202. package/src/data-structures/binary-tree/avl-tree-counter.ts +198 -216
  203. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +192 -101
  204. package/src/data-structures/binary-tree/avl-tree.ts +239 -206
  205. package/src/data-structures/binary-tree/binary-tree.ts +660 -889
  206. package/src/data-structures/binary-tree/bst.ts +568 -570
  207. package/src/data-structures/binary-tree/red-black-tree.ts +161 -222
  208. package/src/data-structures/binary-tree/tree-counter.ts +199 -218
  209. package/src/data-structures/binary-tree/tree-multi-map.ts +131 -97
  210. package/src/data-structures/graph/abstract-graph.ts +339 -264
  211. package/src/data-structures/graph/directed-graph.ts +146 -236
  212. package/src/data-structures/graph/map-graph.ts +63 -60
  213. package/src/data-structures/graph/undirected-graph.ts +129 -152
  214. package/src/data-structures/hash/hash-map.ts +274 -496
  215. package/src/data-structures/heap/heap.ts +389 -402
  216. package/src/data-structures/heap/max-heap.ts +12 -76
  217. package/src/data-structures/heap/min-heap.ts +13 -76
  218. package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
  219. package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
  220. package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
  221. package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
  222. package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
  223. package/src/data-structures/priority-queue/priority-queue.ts +3 -92
  224. package/src/data-structures/queue/deque.ts +381 -357
  225. package/src/data-structures/queue/queue.ts +310 -264
  226. package/src/data-structures/stack/stack.ts +217 -131
  227. package/src/data-structures/trie/trie.ts +240 -175
  228. package/src/interfaces/binary-tree.ts +240 -6
  229. package/src/interfaces/graph.ts +37 -0
  230. package/src/types/data-structures/base/base.ts +5 -5
  231. package/src/types/data-structures/graph/abstract-graph.ts +5 -0
  232. package/src/types/utils/utils.ts +2 -0
  233. package/src/utils/utils.ts +9 -14
  234. package/test/integration/index.html +1 -1
  235. package/test/performance/benchmark-runner.ts +528 -0
  236. package/test/performance/reportor.mjs +43 -43
  237. package/test/performance/runner-config.json +39 -0
  238. package/test/performance/single-suite-runner.ts +69 -0
  239. package/test/unit/data-structures/binary-tree/avl-tree-counter.test.ts +3 -3
  240. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +5 -5
  241. package/test/unit/data-structures/binary-tree/avl-tree.test.ts +4 -4
  242. package/test/unit/data-structures/binary-tree/binary-tree.test.ts +350 -90
  243. package/test/unit/data-structures/binary-tree/bst.test.ts +12 -9
  244. package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +2 -2
  245. package/test/unit/data-structures/binary-tree/tree-counter.test.ts +25 -24
  246. package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +3 -3
  247. package/test/unit/data-structures/graph/abstract-graph.test.ts +0 -4
  248. package/test/unit/data-structures/graph/directed-graph.test.ts +1 -1
  249. package/test/unit/data-structures/heap/heap.test.ts +14 -21
  250. package/test/unit/data-structures/heap/max-heap.test.ts +5 -9
  251. package/test/unit/data-structures/heap/min-heap.test.ts +1 -4
  252. package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +14 -14
  253. package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +0 -7
  254. package/test/unit/data-structures/priority-queue/max-priority-queue.test.ts +8 -11
  255. package/test/unit/data-structures/priority-queue/min-priority-queue.test.ts +1 -4
  256. package/test/unit/data-structures/priority-queue/priority-queue.test.ts +1 -4
  257. package/test/unit/data-structures/queue/queue.test.ts +4 -5
  258. package/test/unit/utils/utils.test.ts +0 -1
  259. package/test/performance/data-structures/binary-tree/avl-tree.test.mjs +0 -71
  260. package/test/performance/data-structures/binary-tree/red-black-tree.test.mjs +0 -81
@@ -10,30 +10,40 @@ import { Queue } from '../queue';
10
10
  import { IterableEntryBase } from '../base';
11
11
  import { DFSOperation, Range } from '../../common';
12
12
  /**
13
- * Represents a node in a binary tree.
14
- * @template V - The type of data stored in the node.
15
- * @template BinaryTreeNode<K, V> - The type of the family relationship in the binary tree.
13
+ * @template K - The type of the key.
14
+ * @template V - The type of the value.
16
15
  */
17
16
  export class BinaryTreeNode {
18
17
  key;
19
18
  value;
20
19
  parent = undefined;
21
20
  /**
22
- * The constructor function initializes an object with a key and an optional value in TypeScript.
23
- * @param {K} key - The `key` parameter in the constructor function is used to store the key value
24
- * for the key-value pair.
25
- * @param {V} [value] - The `value` parameter in the constructor is optional, meaning it does not
26
- * have to be provided when creating an instance of the class. If a `value` is not provided, it will
27
- * default to `undefined`.
21
+ * Creates an instance of BinaryTreeNode.
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.
28
26
  */
29
27
  constructor(key, value) {
30
28
  this.key = key;
31
29
  this.value = value;
32
30
  }
33
31
  _left = undefined;
32
+ /**
33
+ * Gets the left child of the node.
34
+ * @remarks Time O(1), Space O(1)
35
+ *
36
+ * @returns The left child.
37
+ */
34
38
  get left() {
35
39
  return this._left;
36
40
  }
41
+ /**
42
+ * Sets the left child of the node and updates its parent reference.
43
+ * @remarks Time O(1), Space O(1)
44
+ *
45
+ * @param v - The node to set as the left child.
46
+ */
37
47
  set left(v) {
38
48
  if (v) {
39
49
  v.parent = this;
@@ -41,9 +51,21 @@ export class BinaryTreeNode {
41
51
  this._left = v;
42
52
  }
43
53
  _right = undefined;
54
+ /**
55
+ * Gets the right child of the node.
56
+ * @remarks Time O(1), Space O(1)
57
+ *
58
+ * @returns The right child.
59
+ */
44
60
  get right() {
45
61
  return this._right;
46
62
  }
63
+ /**
64
+ * Sets the right child of the node and updates its parent reference.
65
+ * @remarks Time O(1), Space O(1)
66
+ *
67
+ * @param v - The node to set as the right child.
68
+ */
47
69
  set right(v) {
48
70
  if (v) {
49
71
  v.parent = this;
@@ -51,26 +73,68 @@ export class BinaryTreeNode {
51
73
  this._right = v;
52
74
  }
53
75
  _height = 0;
76
+ /**
77
+ * Gets the height of the node (used in self-balancing trees).
78
+ * @remarks Time O(1), Space O(1)
79
+ *
80
+ * @returns The height.
81
+ */
54
82
  get height() {
55
83
  return this._height;
56
84
  }
85
+ /**
86
+ * Sets the height of the node.
87
+ * @remarks Time O(1), Space O(1)
88
+ *
89
+ * @param value - The new height.
90
+ */
57
91
  set height(value) {
58
92
  this._height = value;
59
93
  }
60
94
  _color = 'BLACK';
95
+ /**
96
+ * Gets the color of the node (used in Red-Black trees).
97
+ * @remarks Time O(1), Space O(1)
98
+ *
99
+ * @returns The node's color.
100
+ */
61
101
  get color() {
62
102
  return this._color;
63
103
  }
104
+ /**
105
+ * Sets the color of the node.
106
+ * @remarks Time O(1), Space O(1)
107
+ *
108
+ * @param value - The new color.
109
+ */
64
110
  set color(value) {
65
111
  this._color = value;
66
112
  }
67
113
  _count = 1;
114
+ /**
115
+ * Gets the count of nodes in the subtree rooted at this node (used in order-statistic trees).
116
+ * @remarks Time O(1), Space O(1)
117
+ *
118
+ * @returns The subtree node count.
119
+ */
68
120
  get count() {
69
121
  return this._count;
70
122
  }
123
+ /**
124
+ * Sets the count of nodes in the subtree.
125
+ * @remarks Time O(1), Space O(1)
126
+ *
127
+ * @param value - The new count.
128
+ */
71
129
  set count(value) {
72
130
  this._count = value;
73
131
  }
132
+ /**
133
+ * Gets the position of the node relative to its parent.
134
+ * @remarks Time O(1), Space O(1)
135
+ *
136
+ * @returns The family position (e.g., 'ROOT', 'LEFT', 'RIGHT').
137
+ */
74
138
  get familyPosition() {
75
139
  if (!this.parent) {
76
140
  return this.left || this.right ? 'ROOT' : 'ISOLATED';
@@ -85,6 +149,15 @@ export class BinaryTreeNode {
85
149
  }
86
150
  }
87
151
  /**
152
+ * A general Binary Tree implementation.
153
+ *
154
+ * @remarks
155
+ * This class implements a basic Binary Tree, not a Binary Search Tree.
156
+ * The `add` operation inserts nodes level-by-level (BFS) into the first available slot.
157
+ *
158
+ * @template K - The type of the key.
159
+ * @template V - The type of the value.
160
+ * @template R - The type of the raw data object (if using `toEntryFn`).
88
161
  * 1. Two Children Maximum: Each node has at most two children.
89
162
  * 2. Left and Right Children: Nodes have distinct left and right children.
90
163
  * 3. Depth and Height: Depth is the number of edges from the root to a node; height is the maximum depth in the tree.
@@ -156,13 +229,11 @@ export class BinaryTreeNode {
156
229
  export class BinaryTree extends IterableEntryBase {
157
230
  iterationType = 'ITERATIVE';
158
231
  /**
159
- * This TypeScript constructor function initializes a binary tree with optional options and adds
160
- * elements based on the provided input.
161
- * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the constructor is an
162
- * iterable that can contain either objects of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It
163
- * is used to initialize the binary tree with keys, nodes, entries, or raw data.
164
- * @param [options] - The `options` parameter in the constructor is an optional object that can
165
- * contain the following properties:
232
+ * Creates an instance of BinaryTree.
233
+ * @remarks Time O(N * M), where N is the number of items in `keysNodesEntriesOrRaws` and M is the tree size at insertion time (due to O(M) `add` operation). Space O(N) for storing the nodes.
234
+ *
235
+ * @param [keysNodesEntriesOrRaws=[]] - An iterable of items to add.
236
+ * @param [options] - Configuration options for the tree.
166
237
  */
167
238
  constructor(keysNodesEntriesOrRaws = [], options) {
168
239
  super();
@@ -183,81 +254,103 @@ export class BinaryTree extends IterableEntryBase {
183
254
  this.addMany(keysNodesEntriesOrRaws);
184
255
  }
185
256
  _isMapMode = true;
257
+ /**
258
+ * Gets whether the tree is in Map mode.
259
+ * @remarks In Map mode (default), values are stored in an external Map, and nodes only hold keys. If false, values are stored directly on the nodes. Time O(1)
260
+ *
261
+ * @returns True if in Map mode, false otherwise.
262
+ */
186
263
  get isMapMode() {
187
264
  return this._isMapMode;
188
265
  }
189
266
  _isDuplicate = false;
267
+ /**
268
+ * Gets whether the tree allows duplicate keys.
269
+ * @remarks Time O(1)
270
+ *
271
+ * @returns True if duplicates are allowed, false otherwise.
272
+ */
190
273
  get isDuplicate() {
191
274
  return this._isDuplicate;
192
275
  }
193
276
  _store = new Map();
277
+ /**
278
+ * Gets the external value store (used in Map mode).
279
+ * @remarks Time O(1)
280
+ *
281
+ * @returns The map storing key-value pairs.
282
+ */
194
283
  get store() {
195
284
  return this._store;
196
285
  }
197
286
  _root;
287
+ /**
288
+ * Gets the root node of the tree.
289
+ * @remarks Time O(1)
290
+ *
291
+ * @returns The root node.
292
+ */
198
293
  get root() {
199
294
  return this._root;
200
295
  }
201
296
  _size = 0;
297
+ /**
298
+ * Gets the number of nodes in the tree.
299
+ * @remarks Time O(1)
300
+ *
301
+ * @returns The size of the tree.
302
+ */
202
303
  get size() {
203
304
  return this._size;
204
305
  }
205
306
  _NIL = new BinaryTreeNode(NaN);
307
+ /**
308
+ * Gets the sentinel NIL node (used in self-balancing trees like Red-Black Tree).
309
+ * @remarks Time O(1)
310
+ *
311
+ * @returns The NIL node.
312
+ */
206
313
  get NIL() {
207
314
  return this._NIL;
208
315
  }
209
316
  _toEntryFn;
317
+ /**
318
+ * Gets the function used to convert raw data objects (R) into [key, value] entries.
319
+ * @remarks Time O(1)
320
+ *
321
+ * @returns The conversion function.
322
+ */
210
323
  get toEntryFn() {
211
324
  return this._toEntryFn;
212
325
  }
213
326
  /**
214
- * Time Complexity: O(1)
215
- * Space Complexity: O(1)
327
+ * (Protected) Creates a new node.
328
+ * @remarks Time O(1), Space O(1)
216
329
  *
217
- * The function creates a new binary tree node with a specified key and optional value.
218
- * @param {K} key - The `key` parameter is the key of the node being created in the binary tree.
219
- * @param {V} [value] - The `value` parameter in the `createNode` function is optional, meaning it is
220
- * not required to be provided when calling the function. If a `value` is provided, it should be of
221
- * type `V`, which is the type of the value associated with the node.
222
- * @returns A new BinaryTreeNode instance with the provided key and value is being returned, casted
223
- * as BinaryTreeNode<K, V>.
330
+ * @param key - The key for the new node.
331
+ * @param [value] - The value for the new node (used if not in Map mode).
332
+ * @returns The newly created node.
224
333
  */
225
- createNode(key, value) {
334
+ _createNode(key, value) {
226
335
  return new BinaryTreeNode(key, this._isMapMode ? undefined : value);
227
336
  }
228
337
  /**
229
- * Time Complexity: O(1)
230
- * Space Complexity: O(1)
338
+ * Creates a new, empty tree of the same type and configuration.
339
+ * @remarks Time O(1) (excluding options cloning), Space O(1)
231
340
  *
232
- * The function creates a binary tree with the specified options.
233
- * @param [options] - The `options` parameter in the `createTree` function is an optional parameter
234
- * that allows you to provide partial configuration options for creating a binary tree. It is of type
235
- * `Partial<BinaryTreeOptions<K, V, R>>`, which means you can pass in an object containing a subset
236
- * of properties
237
- * @returns A new instance of a binary tree with the specified options is being returned.
341
+ * @param [options] - Optional overrides for the new tree's options.
342
+ * @returns A new, empty tree instance.
238
343
  */
239
344
  createTree(options) {
240
- return new BinaryTree([], {
241
- iterationType: this.iterationType,
242
- isMapMode: this._isMapMode,
243
- toEntryFn: this._toEntryFn,
244
- ...options
245
- });
246
- }
247
- /**
248
- * Time Complexity: O(n)
249
- * Space Complexity: O(log n)
250
- *
251
- * The function `ensureNode` in TypeScript checks if a given input is a node, entry, key, or raw
252
- * value and returns the corresponding node or null.
253
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
254
- * parameter in the `ensureNode` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It
255
- * is used to determine whether the input is a key, node, entry, or raw data. The
256
- * @param {IterationType} iterationType - The `iterationType` parameter in the `ensureNode` function
257
- * is used to specify the type of iteration to be performed. It has a default value of
258
- * `this.iterationType` if not explicitly provided.
259
- * @returns The `ensureNode` function returns either a node, `null`, or `undefined` based on the
260
- * conditions specified in the code snippet.
345
+ return this._createInstance(options);
346
+ }
347
+ /**
348
+ * Ensures the input is a node. If it's a key or entry, it searches for the node.
349
+ * @remarks Time O(1) if a node is passed. O(N) if a key or entry is passed (due to `getNode` performing a full search). Space O(1) if iterative search, O(H) if recursive (where H is height, O(N) worst-case).
350
+ *
351
+ * @param keyNodeOrEntry - The item to resolve to a node.
352
+ * @param [iterationType=this.iterationType] - The traversal method to use if searching.
353
+ * @returns The resolved node, or null/undefined if not found or input is null/undefined.
261
354
  */
262
355
  ensureNode(keyNodeOrEntry, iterationType = this.iterationType) {
263
356
  if (keyNodeOrEntry === null)
@@ -279,47 +372,31 @@ export class BinaryTree extends IterableEntryBase {
279
372
  return this.getNode(keyNodeOrEntry, this._root, iterationType);
280
373
  }
281
374
  /**
282
- * Time Complexity: O(1)
283
- * Space Complexity: O(1)
375
+ * Checks if the given item is a `BinaryTreeNode` instance.
376
+ * @remarks Time O(1), Space O(1)
284
377
  *
285
- * The function isNode checks if the input is an instance of BinaryTreeNode.
286
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
287
- * `keyNodeOrEntry` can be either a key, a node, an entry, or raw data. The function is
288
- * checking if the input is an instance of a `BinaryTreeNode` and returning a boolean value
289
- * accordingly.
290
- * @returns The function `isNode` is checking if the input `keyNodeOrEntry` is an instance of
291
- * `BinaryTreeNode`. If it is, the function returns `true`, indicating that the input is a node. If
292
- * it is not an instance of `BinaryTreeNode`, the function returns `false`, indicating that the input
293
- * is not a node.
378
+ * @param keyNodeOrEntry - The item to check.
379
+ * @returns True if it's a node, false otherwise.
294
380
  */
295
381
  isNode(keyNodeOrEntry) {
296
382
  return keyNodeOrEntry instanceof BinaryTreeNode;
297
383
  }
298
384
  /**
299
- * Time Complexity: O(1)
300
- * Space Complexity: O(1)
385
+ * Checks if the given item is a raw data object (R) that needs conversion via `toEntryFn`.
386
+ * @remarks Time O(1), Space O(1)
301
387
  *
302
- * The function `isRaw` checks if the input parameter is of type `R` by verifying if it is an object.
303
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R} keyNodeEntryOrRaw - K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
304
- * @returns The function `isRaw` is checking if the `keyNodeEntryOrRaw` parameter is of type `R` by
305
- * checking if it is an object. If the parameter is an object, the function will return `true`,
306
- * indicating that it is of type `R`.
388
+ * @param keyNodeEntryOrRaw - The item to check.
389
+ * @returns True if it's a raw object, false otherwise.
307
390
  */
308
391
  isRaw(keyNodeEntryOrRaw) {
309
392
  return this._toEntryFn !== undefined && typeof keyNodeEntryOrRaw === 'object';
310
393
  }
311
394
  /**
312
- * Time Complexity: O(1)
313
- * Space Complexity: O(1)
395
+ * Checks if the given item is a "real" node (i.e., not null, undefined, or NIL).
396
+ * @remarks Time O(1), Space O(1)
314
397
  *
315
- * The function `isRealNode` checks if a given input is a valid node in a binary tree.
316
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
317
- * parameter in the `isRealNode` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`.
318
- * The function checks if the input parameter is a `BinaryTreeNode<K, V>` type by verifying if it is not equal
319
- * @returns The function `isRealNode` is checking if the input `keyNodeOrEntry` is a valid
320
- * node by comparing it to `this._NIL`, `null`, and `undefined`. If the input is not one of these
321
- * values, it then calls the `isNode` method to further determine if the input is a node. The
322
- * function will return a boolean value indicating whether the
398
+ * @param keyNodeOrEntry - The item to check.
399
+ * @returns True if it's a real node, false otherwise.
323
400
  */
324
401
  isRealNode(keyNodeOrEntry) {
325
402
  if (keyNodeOrEntry === this._NIL || keyNodeOrEntry === null || keyNodeOrEntry === undefined)
@@ -327,97 +404,66 @@ export class BinaryTree extends IterableEntryBase {
327
404
  return this.isNode(keyNodeOrEntry);
328
405
  }
329
406
  /**
330
- * Time Complexity: O(1)
331
- * Space Complexity: O(1)
407
+ * Checks if the given item is either a "real" node or null.
408
+ * @remarks Time O(1), Space O(1)
332
409
  *
333
- * The function checks if a given input is a valid node or null.
334
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
335
- * `keyNodeOrEntry` in the `isRealNodeOrNull` function can be of type `BTNRep<K,
336
- * V, BinaryTreeNode<K, V>>` or `R`. It is a union type that can either be a key, a node, an entry, or
337
- * @returns The function `isRealNodeOrNull` is returning a boolean value. It checks if the input
338
- * `keyNodeOrEntry` is either `null` or a real node, and returns `true` if it is a node or
339
- * `null`, and `false` otherwise.
410
+ * @param keyNodeOrEntry - The item to check.
411
+ * @returns True if it's a real node or null, false otherwise.
340
412
  */
341
413
  isRealNodeOrNull(keyNodeOrEntry) {
342
414
  return keyNodeOrEntry === null || this.isRealNode(keyNodeOrEntry);
343
415
  }
344
416
  /**
345
- * Time Complexity: O(1)
346
- * Space Complexity: O(1)
417
+ * Checks if the given item is the sentinel NIL node.
418
+ * @remarks Time O(1), Space O(1)
347
419
  *
348
- * The function isNIL checks if a given key, node, entry, or raw value is equal to the _NIL value.
349
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - BTNRep<K, V,
350
- * BinaryTreeNode<K, V>>
351
- * @returns The function is checking if the `keyNodeOrEntry` parameter is equal to the `_NIL`
352
- * property of the current object and returning a boolean value based on that comparison.
420
+ * @param keyNodeOrEntry - The item to check.
421
+ * @returns True if it's the NIL node, false otherwise.
353
422
  */
354
423
  isNIL(keyNodeOrEntry) {
355
424
  return keyNodeOrEntry === this._NIL;
356
425
  }
357
426
  /**
358
- * Time Complexity: O(1)
359
- * Space Complexity: O(1)
427
+ * Checks if the given item is a `Range` object.
428
+ * @remarks Time O(1), Space O(1)
360
429
  *
361
- * The function `isRange` checks if the input parameter is an instance of the `Range` class.
362
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>> | Range<K>} keyNodeEntryOrPredicate
363
- * - The `keyNodeEntryOrPredicate` parameter in the `isRange` function can be
364
- * of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `, `NodePredicate<BinaryTreeNode<K, V>>`, or
365
- * `Range<K>`. The function checks if the `keyNodeEntry
366
- * @returns The `isRange` function is checking if the `keyNodeEntryOrPredicate` parameter is an
367
- * instance of the `Range` class. If it is an instance of `Range`, the function will return `true`,
368
- * indicating that the parameter is a `Range<K>`. If it is not an instance of `Range`, the function
369
- * will return `false`.
430
+ * @param keyNodeEntryOrPredicate - The item to check.
431
+ * @returns True if it's a Range, false otherwise.
370
432
  */
371
433
  isRange(keyNodeEntryOrPredicate) {
372
434
  return keyNodeEntryOrPredicate instanceof Range;
373
435
  }
374
436
  /**
375
- * Time Complexity: O(1)
376
- * Space Complexity: O(1)
437
+ * Checks if a node is a leaf (has no real children).
438
+ * @remarks Time O(N) if a key/entry is passed (due to `ensureNode`). O(1) if a node is passed. Space O(1) or O(H) (from `ensureNode`).
377
439
  *
378
- * The function determines whether a given key, node, entry, or raw data is a leaf node in a binary
379
- * tree.
380
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The parameter
381
- * `keyNodeOrEntry` can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. It represents a
382
- * key, node, entry, or raw data in a binary tree structure. The function `isLeaf` checks whether the
383
- * provided
384
- * @returns The function `isLeaf` returns a boolean value indicating whether the input
385
- * `keyNodeOrEntry` is a leaf node in a binary tree.
440
+ * @param keyNodeOrEntry - The node to check.
441
+ * @returns True if the node is a leaf, false otherwise.
386
442
  */
387
443
  isLeaf(keyNodeOrEntry) {
388
444
  keyNodeOrEntry = this.ensureNode(keyNodeOrEntry);
389
445
  if (keyNodeOrEntry === undefined)
390
446
  return false;
391
447
  if (keyNodeOrEntry === null)
392
- return true;
448
+ return true; // A null spot is considered a leaf
393
449
  return !this.isRealNode(keyNodeOrEntry.left) && !this.isRealNode(keyNodeOrEntry.right);
394
450
  }
395
451
  /**
396
- * Time Complexity: O(1)
397
- * Space Complexity: O(1)
452
+ * Checks if the given item is a [key, value] entry pair.
453
+ * @remarks Time O(1), Space O(1)
398
454
  *
399
- * The function `isEntry` checks if the input is a BTNEntry object by verifying if it is an array
400
- * with a length of 2.
401
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `keyNodeOrEntry`
402
- * parameter in the `isEntry` function can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or type `R`.
403
- * The function checks if the provided `keyNodeOrEntry` is of type `BTN
404
- * @returns The `isEntry` function is checking if the `keyNodeOrEntry` parameter is an array
405
- * with a length of 2. If it is, then it returns `true`, indicating that the parameter is of type
406
- * `BTNEntry<K, V>`. If the condition is not met, it returns `false`.
455
+ * @param keyNodeOrEntry - The item to check.
456
+ * @returns True if it's an entry, false otherwise.
407
457
  */
408
458
  isEntry(keyNodeOrEntry) {
409
459
  return Array.isArray(keyNodeOrEntry) && keyNodeOrEntry.length === 2;
410
460
  }
411
461
  /**
412
- * Time Complexity O(1)
413
- * Space Complexity O(1)
462
+ * Checks if the given key is valid (comparable or null).
463
+ * @remarks Time O(1), Space O(1)
414
464
  *
415
- * The function `isValidKey` checks if a given key is comparable.
416
- * @param {any} key - The `key` parameter is of type `any`, which means it can be any data type in
417
- * TypeScript.
418
- * @returns The function `isValidKey` is checking if the `key` parameter is `null` or if it is comparable.
419
- * If the `key` is `null`, the function returns `true`. Otherwise, it returns the result of the
420
- * `isComparable` function, which is not provided in the code snippet.
465
+ * @param key - The key to validate.
466
+ * @returns True if the key is valid, false otherwise.
421
467
  */
422
468
  isValidKey(key) {
423
469
  if (key === null)
@@ -425,27 +471,17 @@ export class BinaryTree extends IterableEntryBase {
425
471
  return isComparable(key);
426
472
  }
427
473
  /**
428
- * Time Complexity O(n)
429
- * Space Complexity O(1)
474
+ * Adds a new node to the tree.
475
+ * @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). This implementation adds the node at the first available position in a level-order (BFS) traversal. This is NOT a Binary Search Tree insertion. Time O(N), where N is the number of nodes. It must traverse level-by-level to find an empty slot. Space O(N) in the worst case for the BFS queue (e.g., a full last level).
430
476
  *
431
- * The `add` function in TypeScript adds a new node to a binary tree while handling duplicate keys
432
- * and finding the correct insertion position.
433
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `add` method you provided
434
- * seems to be for adding a new node to a binary tree structure. The `keyNodeOrEntry`
435
- * parameter in the method can accept different types of values:
436
- * @param {V} [value] - The `value` parameter in the `add` method represents the value associated
437
- * with the key that you want to add to the binary tree. When adding a key-value pair to the binary
438
- * tree, you provide the key and its corresponding value. The `add` method then creates a new node
439
- * with this
440
- * @returns The `add` method returns a boolean value. It returns `true` if the insertion of the new
441
- * node was successful, and `false` if the insertion position could not be found or if a duplicate
442
- * key was found and the node was replaced instead of inserted.
477
+ * @param keyNodeOrEntry - The key, node, or entry to add.
478
+ * @param [value] - The value, if providing just a key.
479
+ * @returns True if the addition was successful, false otherwise.
443
480
  */
444
481
  add(keyNodeOrEntry, value) {
445
482
  const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
446
483
  if (newNode === undefined)
447
484
  return false;
448
- // If the tree is empty, directly set the new node as the root node
449
485
  if (!this._root) {
450
486
  this._setRoot(newNode);
451
487
  if (this._isMapMode)
@@ -454,25 +490,22 @@ export class BinaryTree extends IterableEntryBase {
454
490
  return true;
455
491
  }
456
492
  const queue = new Queue([this._root]);
457
- let potentialParent; // Record the parent node of the potential insertion location
493
+ let potentialParent;
458
494
  while (queue.length > 0) {
459
495
  const cur = queue.shift();
460
496
  if (!cur)
461
497
  continue;
462
498
  if (!this._isDuplicate) {
463
- // Check for duplicate keys when newNode is not null
464
499
  if (newNode !== null && cur.key === newNode.key) {
465
500
  this._replaceNode(cur, newNode);
466
501
  if (this._isMapMode)
467
502
  this._setValue(cur.key, newValue);
468
- return true; // If duplicate keys are found, no insertion is performed
503
+ return true; // Replaced existing node
469
504
  }
470
505
  }
471
- // Record the first possible insertion location found
472
506
  if (potentialParent === undefined && (cur.left === undefined || cur.right === undefined)) {
473
507
  potentialParent = cur;
474
508
  }
475
- // Continue traversing the left and right subtrees
476
509
  if (cur.left !== null) {
477
510
  if (cur.left)
478
511
  queue.push(cur.left);
@@ -482,7 +515,6 @@ export class BinaryTree extends IterableEntryBase {
482
515
  queue.push(cur.right);
483
516
  }
484
517
  }
485
- // At the end of the traversal, if the insertion position is found, insert
486
518
  if (potentialParent) {
487
519
  if (potentialParent.left === undefined) {
488
520
  potentialParent.left = newNode;
@@ -495,28 +527,17 @@ export class BinaryTree extends IterableEntryBase {
495
527
  this._size++;
496
528
  return true;
497
529
  }
498
- return false; // If the insertion position cannot be found, return undefined
499
- }
500
- /**
501
- * Time Complexity: O(k * n)
502
- * Space Complexity: O(k)
503
- *
504
- * The `addMany` function takes in multiple keys or nodes or entries or raw values along with
505
- * optional values, and adds them to a data structure while returning an array indicating whether
506
- * each insertion was successful.
507
- * @param keysNodesEntriesOrRaws - `keysNodesEntriesOrRaws` is an iterable that can contain a
508
- * mix of keys, nodes, entries, or raw values. Each element in this iterable can be of type
509
- * `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`.
510
- * @param [values] - The `values` parameter in the `addMany` function is an optional parameter that
511
- * accepts an iterable of values. These values correspond to the keys or nodes being added in the
512
- * `keysNodesEntriesOrRaws` parameter. If provided, the function will iterate over the values and
513
- * assign them
514
- * @returns The `addMany` method returns an array of boolean values indicating whether each key,
515
- * node, entry, or raw value was successfully added to the data structure. Each boolean value
516
- * corresponds to the success of adding the corresponding key or value in the input iterable.
530
+ return false; // Should not happen if tree is not full?
531
+ }
532
+ /**
533
+ * Adds multiple items to the tree.
534
+ * @remarks Time O(N * M), where N is the number of items to add and M is the size of the tree at insertion (due to O(M) `add` operation). Space O(M) (from `add`) + O(N) (for the `inserted` array).
535
+ *
536
+ * @param keysNodesEntriesOrRaws - An iterable of items to add.
537
+ * @param [values] - An optional parallel iterable of values.
538
+ * @returns An array of booleans indicating the success of each individual `add` operation.
517
539
  */
518
540
  addMany(keysNodesEntriesOrRaws, values) {
519
- // TODO not sure addMany not be run multi times
520
541
  const inserted = [];
521
542
  let valuesIterator;
522
543
  if (values) {
@@ -537,46 +558,31 @@ export class BinaryTree extends IterableEntryBase {
537
558
  return inserted;
538
559
  }
539
560
  /**
540
- * Time Complexity: O(k * n)
541
- * Space Complexity: O(1)
561
+ * Merges another tree into this one by adding all its nodes.
562
+ * @remarks Time O(N * M), same as `addMany`, where N is the size of `anotherTree` and M is the size of this tree. Space O(M) (from `add`).
542
563
  *
543
- * The `merge` function in TypeScript merges another binary tree into the current tree by adding all
544
- * elements from the other tree.
545
- * @param anotherTree - BinaryTree<K, V, R, MK, MV, MR>
564
+ * @param anotherTree - The tree to merge.
546
565
  */
547
566
  merge(anotherTree) {
548
567
  this.addMany(anotherTree, []);
549
568
  }
550
569
  /**
551
- * Time Complexity: O(k * n)
552
- * Space Complexity: O(1)
570
+ * Clears the tree and refills it with new items.
571
+ * @remarks Time O(N) (for `clear`) + O(N * M) (for `addMany`) = O(N * M). Space O(M) (from `addMany`).
553
572
  *
554
- * The `refill` function clears the existing data structure and then adds new key-value pairs based
555
- * on the provided input.
556
- * @param keysNodesEntriesOrRaws - The `keysNodesEntriesOrRaws` parameter in the `refill`
557
- * method can accept an iterable containing a mix of `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` objects or `R`
558
- * objects.
559
- * @param [values] - The `values` parameter in the `refill` method is an optional parameter that
560
- * accepts an iterable of values of type `V` or `undefined`.
573
+ * @param keysNodesEntriesOrRaws - An iterable of items to add.
574
+ * @param [values] - An optional parallel iterable of values.
561
575
  */
562
576
  refill(keysNodesEntriesOrRaws, values) {
563
577
  this.clear();
564
578
  this.addMany(keysNodesEntriesOrRaws, values);
565
579
  }
566
580
  /**
567
- * Time Complexity: O(n)
568
- * Space Complexity: O(1)
581
+ * Deletes a node from the tree.
582
+ * @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). This implementation finds the node, and if it has two children, swaps it with the rightmost node of its left subtree (in-order predecessor) before deleting. Time O(N) in the worst case. O(N) to find the node (`getNode`) and O(H) (which is O(N) worst-case) to find the rightmost node. Space O(1) (if `getNode` is iterative, which it is).
569
583
  *
570
- * The function `delete` in TypeScript implements the deletion of a node in a binary tree and returns
571
- * the deleted node along with information for tree balancing.
572
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry
573
- * - The `delete` method you provided is used to delete a node from a binary tree based on the key,
574
- * node, entry or raw data. The method returns an array of
575
- * `BinaryTreeDeleteResult` objects containing information about the deleted node and whether
576
- * balancing is needed.
577
- * @returns The `delete` method returns an array of `BinaryTreeDeleteResult` objects. Each object in
578
- * the array contains information about the node that was deleted (`deleted`) and the node that may
579
- * need to be balanced (`needBalanced`).
584
+ * @param keyNodeOrEntry - The node to delete.
585
+ * @returns An array containing deletion results (for compatibility with self-balancing trees).
580
586
  */
581
587
  delete(keyNodeOrEntry) {
582
588
  const deletedResult = [];
@@ -589,14 +595,20 @@ export class BinaryTree extends IterableEntryBase {
589
595
  let needBalanced;
590
596
  let orgCurrent = curr;
591
597
  if (!curr.left && !curr.right && !parent) {
598
+ // Deleting the root with no children
592
599
  this._setRoot(undefined);
593
600
  }
594
601
  else if (curr.left) {
602
+ // Node has a left child (or two children)
603
+ // Find the rightmost node in the left subtree
595
604
  const leftSubTreeRightMost = this.getRightMost(node => node, curr.left);
596
605
  if (leftSubTreeRightMost) {
597
606
  const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
607
+ // Swap properties
598
608
  orgCurrent = this._swapProperties(curr, leftSubTreeRightMost);
609
+ // `orgCurrent` is now the node to be physically deleted (which was the rightmost)
599
610
  if (parentOfLeftSubTreeMax) {
611
+ // Unlink the rightmost node
600
612
  if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)
601
613
  parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
602
614
  else
@@ -606,6 +618,8 @@ export class BinaryTree extends IterableEntryBase {
606
618
  }
607
619
  }
608
620
  else if (parent) {
621
+ // Node has no left child, but has a parent
622
+ // Promote the right child (which could be null)
609
623
  const { familyPosition: fp } = curr;
610
624
  if (fp === 'LEFT' || fp === 'ROOT_LEFT') {
611
625
  parent.left = curr.right;
@@ -616,6 +630,8 @@ export class BinaryTree extends IterableEntryBase {
616
630
  needBalanced = parent;
617
631
  }
618
632
  else {
633
+ // Deleting the root, which has no left child
634
+ // Promote the right child as the new root
619
635
  this._setRoot(curr.right);
620
636
  curr.right = undefined;
621
637
  }
@@ -626,28 +642,16 @@ export class BinaryTree extends IterableEntryBase {
626
642
  return deletedResult;
627
643
  }
628
644
  /**
629
- * Time Complexity: O(n)
630
- * Space Complexity: O(k + log n)
631
- *
632
- * The `search` function in TypeScript performs a depth-first or breadth-first search on a tree
633
- * structure based on a given predicate or key, with options to return multiple results or just one.
634
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The
635
- * `keyNodeEntryOrPredicate` parameter in the `search` function can accept three types of values:
636
- * @param [onlyOne=false] - The `onlyOne` parameter in the `search` function is a boolean flag that
637
- * determines whether the search should stop after finding the first matching node. If `onlyOne` is
638
- * set to `true`, the search will return as soon as a matching node is found. If `onlyOne` is
639
- * @param {C} callback - The `callback` parameter in the `search` function is a callback function
640
- * that will be called on each node that matches the search criteria. It is of type `C`, which
641
- * extends `NodeCallback<BinaryTreeNode<K, V> | null>`. The default value for `callback` is `this._DEFAULT_NODE_CALLBACK` if
642
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `search` function is
643
- * used to specify the node from which the search operation should begin. It represents the starting
644
- * point in the binary tree where the search will be performed. If no specific `startNode` is
645
- * provided, the search operation will start from the root
646
- * @param {IterationType} iterationType - The `iterationType` parameter in the `search` function
647
- * specifies the type of iteration to be used when searching for nodes in a binary tree. It can have
648
- * two possible values:
649
- * @returns The `search` function returns an array of values that match the provided criteria based
650
- * on the search algorithm implemented within the function.
645
+ * Searches the tree for nodes matching a predicate.
646
+ * @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). Performs a full DFS (pre-order) scan of the tree. Time O(N), as it may visit every node. Space O(H) for the call stack (recursive) or explicit stack (iterative), where H is the tree height (O(N) worst-case).
647
+ *
648
+ * @template C - The type of the callback function.
649
+ * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
650
+ * @param [onlyOne=false] - If true, stops after finding the first match.
651
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on matching nodes.
652
+ * @param [startNode=this._root] - The node to start the search from.
653
+ * @param [iterationType=this.iterationType] - Whether to use 'RECURSIVE' or 'ITERATIVE' search.
654
+ * @returns An array of results from the callback function for each matching node.
651
655
  */
652
656
  search(keyNodeEntryOrPredicate, onlyOne = false, callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
653
657
  if (keyNodeEntryOrPredicate === undefined)
@@ -694,74 +698,29 @@ export class BinaryTree extends IterableEntryBase {
694
698
  }
695
699
  return ans;
696
700
  }
697
- /**
698
- * Time Complexity: O(n)
699
- * Space Complexity: O(k + log n)
700
- *
701
- * The function `getNodes` retrieves nodes from a binary tree based on a key, node, entry, raw data,
702
- * or predicate, with options for recursive or iterative traversal.
703
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
704
- * - The `getNodes` function you provided takes several parameters:
705
- * @param [onlyOne=false] - The `onlyOne` parameter in the `getNodes` function is a boolean flag that
706
- * determines whether to return only the first node that matches the criteria specified by the
707
- * `keyNodeEntryOrPredicate` parameter. If `onlyOne` is set to `true`, the function will
708
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
709
- * `getNodes` function is used to specify the starting point for traversing the binary tree. It
710
- * represents the root node of the binary tree or the node from which the traversal should begin. If
711
- * not provided, the default value is set to `this._root
712
- * @param {IterationType} iterationType - The `iterationType` parameter in the `getNodes` function
713
- * determines the type of iteration to be performed when traversing the nodes of a binary tree. It
714
- * can have two possible values:
715
- * @returns The `getNodes` function returns an array of nodes that satisfy the provided condition
716
- * based on the input parameters and the iteration type specified.
717
- */
718
701
  getNodes(keyNodeEntryOrPredicate, onlyOne = false, startNode = this._root, iterationType = this.iterationType) {
719
702
  return this.search(keyNodeEntryOrPredicate, onlyOne, node => node, startNode, iterationType);
720
703
  }
721
704
  /**
722
- * Time Complexity: O(n)
723
- * Space Complexity: O(log n)
724
- *
725
- * The `getNode` function retrieves a node based on the provided key, node, entry, raw data, or
726
- * predicate.
727
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
728
- * - The `keyNodeEntryOrPredicate` parameter in the `getNode` function can accept a key,
729
- * node, entry, raw data, or a predicate function.
730
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
731
- * `getNode` function is used to specify the starting point for searching for a node in a binary
732
- * tree. If no specific starting point is provided, the default value is set to `this._root`, which
733
- * is typically the root node of the binary tree.
734
- * @param {IterationType} iterationType - The `iterationType` parameter in the `getNode` method is
735
- * used to specify the type of iteration to be performed when searching for a node. It has a default
736
- * value of `this.iterationType`, which means it will use the iteration type defined in the current
737
- * context if no specific value is provided
738
- * @returns The `getNode` function is returning the first node that matches the specified criteria,
739
- * or `null` if no matching node is found.
705
+ * Gets the first node matching a predicate.
706
+ * @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). Time O(N) in the worst case (via `search`). Space O(H) or O(N) (via `search`).
707
+ *
708
+ * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
709
+ * @param [startNode=this._root] - The node to start the search from.
710
+ * @param [iterationType=this.iterationType] - The traversal method.
711
+ * @returns The first matching node, or undefined if not found.
740
712
  */
741
713
  getNode(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
742
714
  return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType)[0];
743
715
  }
744
716
  /**
745
- * Time Complexity: O(n)
746
- * Space Complexity: O(log n)
747
- *
748
- * This function overrides the `get` method to retrieve the value associated with a specified key,
749
- * node, entry, raw data, or predicate in a data structure.
750
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
751
- * - The `keyNodeEntryOrPredicate` parameter in the `get` method can accept one of the
752
- * following types:
753
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `get`
754
- * method is used to specify the starting point for searching for a key or node in the binary tree.
755
- * If no specific starting point is provided, the default starting point is the root of the binary
756
- * tree (`this._root`).
757
- * @param {IterationType} iterationType - The `iterationType` parameter in the `get` method is used
758
- * to specify the type of iteration to be performed when searching for a key in the binary tree. It
759
- * is an optional parameter with a default value of `this.iterationType`, which means it will use the
760
- * iteration type defined in the
761
- * @returns The `get` method is returning the value associated with the specified key, node, entry,
762
- * raw data, or predicate in the binary tree map. If the specified key or node is found in the tree,
763
- * the method returns the corresponding value. If the key or node is not found, it returns
764
- * `undefined`.
717
+ * Gets the value associated with a key.
718
+ * @remarks Time O(log N), For BST, Red-Black Tree, and AVL Tree subclasses, the worst-case time is O(log N). Time O(1) if in Map mode. O(N) if not in Map mode (uses `getNode`). Space O(1) if in Map mode. O(H) or O(N) otherwise.
719
+ *
720
+ * @param keyNodeEntryOrPredicate - The key, node, or entry to get the value for.
721
+ * @param [startNode=this._root] - The node to start searching from (if not in Map mode).
722
+ * @param [iterationType=this.iterationType] - The traversal method (if not in Map mode).
723
+ * @returns The associated value, or undefined.
765
724
  */
766
725
  get(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
767
726
  if (this._isMapMode) {
@@ -772,35 +731,12 @@ export class BinaryTree extends IterableEntryBase {
772
731
  }
773
732
  return this.getNode(keyNodeEntryOrPredicate, startNode, iterationType)?.value;
774
733
  }
775
- /**
776
- * Time Complexity: O(n)
777
- * Space Complexity: O(log n)
778
- *
779
- * The `has` function in TypeScript checks if a specified key, node, entry, raw data, or predicate
780
- * exists in the data structure.
781
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate
782
- * - The `keyNodeEntryOrPredicate` parameter in the `override has` method can accept one of
783
- * the following types:
784
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
785
- * `override` method is used to specify the starting point for the search operation within the data
786
- * structure. It defaults to `this._root` if not provided explicitly.
787
- * @param {IterationType} iterationType - The `iterationType` parameter in the `override has` method
788
- * is used to specify the type of iteration to be performed. It has a default value of
789
- * `this.iterationType`, which means it will use the iteration type defined in the current context if
790
- * no value is provided when calling the method.
791
- * @returns The `override has` method is returning a boolean value. It checks if there are any nodes
792
- * that match the provided key, node, entry, raw data, or predicate in the tree structure. If there
793
- * are matching nodes, it returns `true`, indicating that the tree contains the specified element.
794
- * Otherwise, it returns `false`.
795
- */
796
734
  has(keyNodeEntryOrPredicate, startNode = this._root, iterationType = this.iterationType) {
797
735
  return this.search(keyNodeEntryOrPredicate, true, node => node, startNode, iterationType).length > 0;
798
736
  }
799
737
  /**
800
- * Time Complexity: O(1)
801
- * Space Complexity: O(1)
802
- *
803
- * The clear function removes nodes and values in map mode.
738
+ * Clears the tree of all nodes and values.
739
+ * @remarks Time O(N) if in Map mode (due to `_store.clear()`), O(1) otherwise. Space O(1)
804
740
  */
805
741
  clear() {
806
742
  this._clearNodes();
@@ -808,55 +744,33 @@ export class BinaryTree extends IterableEntryBase {
808
744
  this._clearValues();
809
745
  }
810
746
  /**
811
- * Time Complexity: O(1)
812
- * Space Complexity: O(1)
747
+ * Checks if the tree is empty.
748
+ * @remarks Time O(1), Space O(1)
813
749
  *
814
- * The `isEmpty` function in TypeScript checks if a data structure has no elements and returns a
815
- * boolean value.
816
- * @returns The `isEmpty()` method is returning a boolean value, specifically `true` if the `_size`
817
- * property is equal to 0, indicating that the data structure is empty, and `false` otherwise.
750
+ * @returns True if the tree has no nodes, false otherwise.
818
751
  */
819
752
  isEmpty() {
820
753
  return this._size === 0;
821
754
  }
822
755
  /**
823
- * Time Complexity: O(n)
824
- * Space Complexity: O(log n)
756
+ * Checks if the tree is perfectly balanced.
757
+ * @remarks A tree is perfectly balanced if the difference between min and max height is at most 1. Time O(N), as it requires two full traversals (`getMinHeight` and `getHeight`). Space O(H) or O(N) (from height calculation).
825
758
  *
826
- * The function checks if a binary tree is perfectly balanced by comparing its minimum height with
827
- * its height.
828
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting
829
- * point for checking if the binary tree is perfectly balanced. It represents the root node of the
830
- * binary tree or a specific node from which the balance check should begin.
831
- * @returns The method `isPerfectlyBalanced` is returning a boolean value, which indicates whether
832
- * the tree starting from the `startNode` node is perfectly balanced or not. The return value is
833
- * determined by comparing the minimum height of the tree with the height of the tree. If the minimum
834
- * height plus 1 is greater than or equal to the height of the tree, then it is considered perfectly
835
- * balanced and
759
+ * @param [startNode=this._root] - The node to start checking from.
760
+ * @returns True if perfectly balanced, false otherwise.
836
761
  */
837
762
  isPerfectlyBalanced(startNode = this._root) {
838
763
  return this.getMinHeight(startNode) + 1 >= this.getHeight(startNode);
839
764
  }
840
765
  /**
841
- * Time Complexity: O(n)
842
- * Space Complexity: O(log n)
766
+ * Checks if the tree is a valid Binary Search Tree (BST).
767
+ * @remarks Time O(N), as it must visit every node. Space O(H) for the call stack (recursive) or explicit stack (iterative), where H is the tree height (O(N) worst-case).
843
768
  *
844
- * The function `isBST` in TypeScript checks if a binary search tree is valid using either recursive
845
- * or iterative methods.
846
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `isBST`
847
- * function represents the starting point for checking whether a binary search tree (BST) is valid.
848
- * It can be a node in the BST or a reference to the root of the BST. If no specific node is
849
- * provided, the function will default to
850
- * @param {IterationType} iterationType - The `iterationType` parameter in the `isBST` function
851
- * determines whether the function should use a recursive approach or an iterative approach to check
852
- * if the binary search tree (BST) is valid.
853
- * @returns The `isBST` method is returning a boolean value, which indicates whether the binary
854
- * search tree (BST) represented by the given root node is a valid BST or not. The method checks if
855
- * the tree satisfies the BST property, where for every node, all nodes in its left subtree have keys
856
- * less than the node's key, and all nodes in its right subtree have keys greater than the node's
769
+ * @param [startNode=this._root] - The node to start checking from.
770
+ * @param [iterationType=this.iterationType] - The traversal method.
771
+ * @returns True if it's a valid BST, false otherwise.
857
772
  */
858
773
  isBST(startNode = this._root, iterationType = this.iterationType) {
859
- // TODO there is a bug
860
774
  startNode = this.ensureNode(startNode);
861
775
  if (!startNode)
862
776
  return true;
@@ -870,14 +784,14 @@ export class BinaryTree extends IterableEntryBase {
870
784
  return dfs(cur.left, min, numKey) && dfs(cur.right, numKey, max);
871
785
  };
872
786
  const isStandardBST = dfs(startNode, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
873
- const isInverseBST = dfs(startNode, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);
787
+ const isInverseBST = dfs(startNode, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER); // Check for reverse BST
874
788
  return isStandardBST || isInverseBST;
875
789
  }
876
790
  else {
791
+ // Iterative in-order traversal check
877
792
  const checkBST = (checkMax = false) => {
878
793
  const stack = [];
879
794
  let prev = checkMax ? Number.MAX_SAFE_INTEGER : Number.MIN_SAFE_INTEGER;
880
- // @ts-ignore
881
795
  let curr = startNode;
882
796
  while (this.isRealNode(curr) || stack.length > 0) {
883
797
  while (this.isRealNode(curr)) {
@@ -893,25 +807,18 @@ export class BinaryTree extends IterableEntryBase {
893
807
  }
894
808
  return true;
895
809
  };
896
- const isStandardBST = checkBST(false), isInverseBST = checkBST(true);
810
+ const isStandardBST = checkBST(false);
811
+ const isInverseBST = checkBST(true);
897
812
  return isStandardBST || isInverseBST;
898
813
  }
899
814
  }
900
815
  /**
901
- * Time Complexity: O(n)
902
- * Space Complexity: O(log n)
816
+ * Gets the depth of a node (distance from `startNode`).
817
+ * @remarks Time O(H), where H is the depth of the `dist` node relative to `startNode`. O(N) worst-case. Space O(1).
903
818
  *
904
- * The `getDepth` function calculates the depth between two nodes in a binary tree.
905
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } dist - The `dist` parameter in the `getDepth`
906
- * function represents the node or entry in a binary tree map, or a reference to a node in the tree.
907
- * It is the target node for which you want to calculate the depth from the `startNode` node.
908
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
909
- * `getDepth` function represents the starting point from which you want to calculate the depth of a
910
- * given node or entry in a binary tree. If no specific starting point is provided, the default value
911
- * for `startNode` is set to the root of the binary
912
- * @returns The `getDepth` method returns the depth of a given node `dist` relative to the
913
- * `startNode` node in a binary tree. If the `dist` node is not found in the path to the `startNode`
914
- * node, it returns the depth of the `dist` node from the root of the tree.
819
+ * @param dist - The node to find the depth of.
820
+ * @param [startNode=this._root] - The node to measure depth from (defaults to root).
821
+ * @returns The depth (0 if `dist` is `startNode`).
915
822
  */
916
823
  getDepth(dist, startNode = this._root) {
917
824
  let distEnsured = this.ensureNode(dist);
@@ -927,21 +834,12 @@ export class BinaryTree extends IterableEntryBase {
927
834
  return depth;
928
835
  }
929
836
  /**
930
- * Time Complexity: O(n)
931
- * Space Complexity: O(log n)
837
+ * Gets the maximum height of the tree (longest path from startNode to a leaf).
838
+ * @remarks Time O(N), as it must visit every node. Space O(H) for recursive stack (O(N) worst-case) or O(N) for iterative stack (storing node + depth).
932
839
  *
933
- * The `getHeight` function calculates the maximum height of a binary tree using either a recursive
934
- * or iterative approach in TypeScript.
935
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter is the starting
936
- * point from which the height of the binary tree will be calculated. It can be a node in the binary
937
- * tree or a reference to the root of the tree. If not provided, it defaults to the root of the
938
- * binary tree data structure.
939
- * @param {IterationType} iterationType - The `iterationType` parameter is used to determine the type
940
- * of iteration to be performed while calculating the height of the binary tree. It can have two
941
- * possible values:
942
- * @returns The `getHeight` method returns the height of the binary tree starting from the specified
943
- * root node. The height is calculated based on the maximum depth of the tree, considering either a
944
- * recursive approach or an iterative approach depending on the `iterationType` parameter.
840
+ * @param [startNode=this._root] - The node to start measuring from.
841
+ * @param [iterationType=this.iterationType] - The traversal method.
842
+ * @returns The height ( -1 for an empty tree, 0 for a single-node tree).
945
843
  */
946
844
  getHeight(startNode = this._root, iterationType = this.iterationType) {
947
845
  startNode = this.ensureNode(startNode);
@@ -958,6 +856,7 @@ export class BinaryTree extends IterableEntryBase {
958
856
  return _getMaxHeight(startNode);
959
857
  }
960
858
  else {
859
+ // Iterative (using DFS)
961
860
  const stack = [{ node: startNode, depth: 0 }];
962
861
  let maxHeight = 0;
963
862
  while (stack.length > 0) {
@@ -972,22 +871,12 @@ export class BinaryTree extends IterableEntryBase {
972
871
  }
973
872
  }
974
873
  /**
975
- * Time Complexity: O(n)
976
- * Space Complexity: O(log n)
874
+ * Gets the minimum height of the tree (shortest path from startNode to a leaf).
875
+ * @remarks Time O(N), as it must visit every node. Space O(H) for recursive stack (O(N) worst-case) or O(N) for iterative (due to `depths` Map).
977
876
  *
978
- * The `getMinHeight` function calculates the minimum height of a binary tree using either a
979
- * recursive or iterative approach in TypeScript.
980
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
981
- * `getMinHeight` function represents the starting node from which the minimum height of the binary
982
- * tree will be calculated. It is either a node in the binary tree or a reference to the root of the
983
- * tree. If not provided, the default value is the root
984
- * @param {IterationType} iterationType - The `iterationType` parameter in the `getMinHeight` method
985
- * specifies the type of iteration to use when calculating the minimum height of a binary tree. It
986
- * can have two possible values:
987
- * @returns The `getMinHeight` method returns the minimum height of the binary tree starting from the
988
- * specified root node. The height is calculated based on the shortest path from the root node to a
989
- * leaf node in the tree. The method uses either a recursive approach or an iterative approach (using
990
- * a stack) based on the `iterationType` parameter.
877
+ * @param [startNode=this._root] - The node to start measuring from.
878
+ * @param [iterationType=this.iterationType] - The traversal method.
879
+ * @returns The minimum height (-1 for empty, 0 for single node).
991
880
  */
992
881
  getMinHeight(startNode = this._root, iterationType = this.iterationType) {
993
882
  startNode = this.ensureNode(startNode);
@@ -998,7 +887,7 @@ export class BinaryTree extends IterableEntryBase {
998
887
  if (!this.isRealNode(cur))
999
888
  return 0;
1000
889
  if (!this.isRealNode(cur.left) && !this.isRealNode(cur.right))
1001
- return 0;
890
+ return 0; // Leaf node
1002
891
  const leftMinHeight = _getMinHeight(cur.left);
1003
892
  const rightMinHeight = _getMinHeight(cur.right);
1004
893
  return Math.min(leftMinHeight, rightMinHeight) + 1;
@@ -1006,6 +895,7 @@ export class BinaryTree extends IterableEntryBase {
1006
895
  return _getMinHeight(startNode);
1007
896
  }
1008
897
  else {
898
+ // Iterative (using post-order DFS)
1009
899
  const stack = [];
1010
900
  let node = startNode, last = null;
1011
901
  const depths = new Map();
@@ -1034,24 +924,14 @@ export class BinaryTree extends IterableEntryBase {
1034
924
  }
1035
925
  }
1036
926
  /**
1037
- * Time Complexity: O(log n)
1038
- * Space Complexity: O(log n)
1039
- *
1040
- * The function `getPathToRoot` in TypeScript retrieves the path from a given node to the root of a
1041
- * tree structure, applying a specified callback function along the way.
1042
- * @param {C} callback - The `callback` parameter is a function that is used to process each node in
1043
- * the path to the root. It is expected to be a function that takes a node as an argument and returns
1044
- * a value based on that node. The return type of the callback function is determined by the generic
1045
- * type `C
1046
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } beginNode - The `beginNode` parameter in the
1047
- * `getPathToRoot` function can be either a key, a node, an entry, or any other value of type `R`.
1048
- * @param [isReverse=true] - The `isReverse` parameter in the `getPathToRoot` function determines
1049
- * whether the resulting path from the given `beginNode` to the root should be in reverse order or
1050
- * not. If `isReverse` is set to `true`, the path will be reversed before being returned. If `is
1051
- * @returns The function `getPathToRoot` returns an array of the return values of the callback
1052
- * function `callback` applied to each node in the path from the `beginNode` to the root node. The
1053
- * array is either in reverse order or in the original order based on the value of the `isReverse`
1054
- * parameter.
927
+ * Gets the path from a given node up to the root.
928
+ * @remarks Time O(H), where H is the depth of the `beginNode`. O(N) worst-case. Space O(H) for the result array.
929
+ *
930
+ * @template C - The type of the callback function.
931
+ * @param beginNode - The node to start the path from.
932
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on each node in the path.
933
+ * @param [isReverse=false] - If true, returns the path from root-to-node.
934
+ * @returns An array of callback results.
1055
935
  */
1056
936
  getPathToRoot(beginNode, callback = this._DEFAULT_NODE_CALLBACK, isReverse = false) {
1057
937
  const result = [];
@@ -1059,40 +939,28 @@ export class BinaryTree extends IterableEntryBase {
1059
939
  if (!beginNodeEnsured)
1060
940
  return result;
1061
941
  while (beginNodeEnsured.parent) {
1062
- // Array.push + Array.reverse is more efficient than Array.unshift
1063
942
  result.push(callback(beginNodeEnsured));
1064
943
  beginNodeEnsured = beginNodeEnsured.parent;
1065
944
  }
1066
- result.push(callback(beginNodeEnsured));
945
+ result.push(callback(beginNodeEnsured)); // Add the root
1067
946
  return isReverse ? result.reverse() : result;
1068
947
  }
1069
948
  /**
1070
- * Time Complexity: O(log n)
1071
- * Space Complexity: O(log n)
1072
- *
1073
- * The function `getLeftMost` retrieves the leftmost node in a binary tree using either recursive or
1074
- * tail-recursive iteration.
1075
- * @param {C} callback - The `callback` parameter is a function that will be called with the leftmost
1076
- * node of a binary tree or with `undefined` if the tree is empty. It is provided with a default
1077
- * value of `_DEFAULT_NODE_CALLBACK` if not specified.
1078
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1079
- * `getLeftMost` function represents the starting point for finding the leftmost node in a binary
1080
- * tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
1081
- * starting point is provided, the function will default
1082
- * @param {IterationType} iterationType - The `iterationType` parameter in the `getLeftMost` function
1083
- * specifies the type of iteration to be used when traversing the binary tree nodes. It can have two
1084
- * possible values:
1085
- * @returns The `getLeftMost` function returns the result of the callback function `C` applied to the
1086
- * leftmost node in the binary tree starting from the `startNode` node. If the `startNode` node is
1087
- * `NIL`, it returns the result of the callback function applied to `undefined`. If the `startNode`
1088
- * node is not a real node, it returns the result of the callback
949
+ * Finds the leftmost node in a subtree (the node with the smallest key in a BST).
950
+ * @remarks Time O(H), where H is the height of the left spine. O(N) worst-case. Space O(H) for recursive/trampoline stack.
951
+ *
952
+ * @template C - The type of the callback function.
953
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on the leftmost node.
954
+ * @param [startNode=this._root] - The subtree root to search from.
955
+ * @param [iterationType=this.iterationType] - The traversal method.
956
+ * @returns The callback result for the leftmost node.
1089
957
  */
1090
958
  getLeftMost(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
1091
959
  if (this.isNIL(startNode))
1092
960
  return callback(undefined);
1093
961
  startNode = this.ensureNode(startNode);
1094
962
  if (!this.isRealNode(startNode))
1095
- return callback(startNode);
963
+ return callback(undefined);
1096
964
  if (iterationType === 'RECURSIVE') {
1097
965
  const dfs = (cur) => {
1098
966
  const { left } = cur;
@@ -1103,7 +971,7 @@ export class BinaryTree extends IterableEntryBase {
1103
971
  return callback(dfs(startNode));
1104
972
  }
1105
973
  else {
1106
- // Indirect implementation of iteration using tail recursion optimization
974
+ // Iterative (trampolined to prevent stack overflow, though 'ITERATIVE' usually means a loop)
1107
975
  const dfs = makeTrampoline((cur) => {
1108
976
  const { left } = cur;
1109
977
  if (!this.isRealNode(left))
@@ -1114,33 +982,21 @@ export class BinaryTree extends IterableEntryBase {
1114
982
  }
1115
983
  }
1116
984
  /**
1117
- * Time Complexity: O(log n)
1118
- * Space Complexity: O(log n)
1119
- *
1120
- * The function `getRightMost` retrieves the rightmost node in a binary tree using either recursive
1121
- * or iterative traversal methods.
1122
- * @param {C} callback - The `callback` parameter is a function that will be called with the result
1123
- * of finding the rightmost node in a binary tree. It is of type `NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>`,
1124
- * which means it is a callback function that can accept either an optional binary tree node or null
1125
- * as
1126
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1127
- * `getRightMost` function represents the starting point for finding the rightmost node in a binary
1128
- * tree. It can be either a key, a node, or an entry in the binary tree structure. If no specific
1129
- * starting point is provided, the function will default
1130
- * @param {IterationType} iterationType - The `iterationType` parameter in the `getRightMost`
1131
- * function specifies the type of iteration to be used when traversing the binary tree nodes. It can
1132
- * have two possible values:
1133
- * @returns The `getRightMost` function returns the result of the callback function `C`, which is
1134
- * passed as a parameter to the function. The callback function is called with the rightmost node in
1135
- * the binary tree structure, determined based on the specified iteration type ('RECURSIVE' or
1136
- * other).
985
+ * Finds the rightmost node in a subtree (the node with the largest key in a BST).
986
+ * @remarks Time O(H), where H is the height of the right spine. O(N) worst-case. Space O(H) for recursive/trampoline stack.
987
+ *
988
+ * @template C - The type of the callback function.
989
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on the rightmost node.
990
+ * @param [startNode=this._root] - The subtree root to search from.
991
+ * @param [iterationType=this.iterationType] - The traversal method.
992
+ * @returns The callback result for the rightmost node.
1137
993
  */
1138
994
  getRightMost(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
1139
995
  if (this.isNIL(startNode))
1140
996
  return callback(undefined);
1141
997
  startNode = this.ensureNode(startNode);
1142
998
  if (!startNode)
1143
- return callback(startNode);
999
+ return callback(undefined);
1144
1000
  if (iterationType === 'RECURSIVE') {
1145
1001
  const dfs = (cur) => {
1146
1002
  const { right } = cur;
@@ -1151,7 +1007,6 @@ export class BinaryTree extends IterableEntryBase {
1151
1007
  return callback(dfs(startNode));
1152
1008
  }
1153
1009
  else {
1154
- // Indirect implementation of iteration using tail recursion optimization
1155
1010
  const dfs = makeTrampoline((cur) => {
1156
1011
  const { right } = cur;
1157
1012
  if (!this.isRealNode(right))
@@ -1162,17 +1017,11 @@ export class BinaryTree extends IterableEntryBase {
1162
1017
  }
1163
1018
  }
1164
1019
  /**
1165
- * Time Complexity: O(log n)
1166
- * Space Complexity: O(log n)
1020
+ * Gets the Morris traversal predecessor (rightmost node in the left subtree, or node itself).
1021
+ * @remarks This is primarily a helper for Morris traversal. Time O(H), where H is the height of the left subtree. O(N) worst-case. Space O(1).
1167
1022
  *
1168
- * The function `getPredecessor` in TypeScript returns the predecessor node of a given node in a
1169
- * binary tree.
1170
- * @param {BinaryTreeNode<K, V>} node - The `getPredecessor` function you provided seems to be attempting to find the
1171
- * predecessor of a given node in a binary tree. However, there seems to be a logical issue in the
1172
- * while loop condition that might cause an infinite loop.
1173
- * @returns The `getPredecessor` function returns the predecessor node of the input `BinaryTreeNode<K, V>` parameter.
1174
- * If the left child of the input node exists, it traverses to the rightmost node of the left subtree
1175
- * to find the predecessor. If the left child does not exist, it returns the input node itself.
1023
+ * @param node - The node to find the predecessor for.
1024
+ * @returns The Morris predecessor.
1176
1025
  */
1177
1026
  getPredecessor(node) {
1178
1027
  if (this.isRealNode(node.left)) {
@@ -1189,17 +1038,11 @@ export class BinaryTree extends IterableEntryBase {
1189
1038
  }
1190
1039
  }
1191
1040
  /**
1192
- * Time Complexity: O(log n)
1193
- * Space Complexity: O(log n)
1041
+ * Gets the in-order successor of a node in a BST.
1042
+ * @remarks Time O(H), where H is the tree height. O(N) worst-case. Space O(H) (due to `getLeftMost` stack).
1194
1043
  *
1195
- * The function `getSuccessor` in TypeScript returns the next node in an in-order traversal of a
1196
- * binary tree.
1197
- * @param {K | BinaryTreeNode<K, V> | null} [x] - The `getSuccessor` function takes a parameter `x`, which can be of
1198
- * type `K`, `BinaryTreeNode<K, V>`, or `null`.
1199
- * @returns The `getSuccessor` function returns the successor node of the input node `x`. If `x` has
1200
- * a right child, the function returns the leftmost node in the right subtree of `x`. If `x` does not
1201
- * have a right child, the function traverses up the parent nodes until it finds a node that is not
1202
- * the right child of its parent, and returns that node
1044
+ * @param [x] - The node to find the successor of.
1045
+ * @returns The successor node, or null/undefined if none exists.
1203
1046
  */
1204
1047
  getSuccessor(x) {
1205
1048
  x = this.ensureNode(x);
@@ -1216,32 +1059,17 @@ export class BinaryTree extends IterableEntryBase {
1216
1059
  return y;
1217
1060
  }
1218
1061
  /**
1219
- * Time complexity: O(n)
1220
- * Space complexity: O(n)
1221
- *
1222
- * The function performs a depth-first search on a binary tree structure based on the specified
1223
- * parameters.
1224
- * @param {C} callback - The `callback` parameter is a function that will be called for each node
1225
- * visited during the depth-first search. It should accept a `BinaryTreeNode` as an argument and
1226
- * return an optional node or null. The default value for this parameter is `_DEFAULT_NODE_CALLBACK`.
1227
- * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `dfs` function specifies
1228
- * the order in which the nodes are visited during a depth-first search traversal. The possible
1229
- * values for the `pattern` parameter are:
1230
- * @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `dfs` function is a boolean flag
1231
- * that determines whether the depth-first search should stop after finding the first matching node
1232
- * or continue searching for all matching nodes. If `onlyOne` is set to `true`, the search will stop
1233
- * after finding the first matching node
1234
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined}
1235
- * startNode - The `startNode` parameter in the `dfs` function can be one of the following types:
1236
- * @param {IterationType} iterationType - The `iterationType` parameter in the `dfs` function
1237
- * specifies the type of iteration to be performed during the Depth-First Search traversal. It is
1238
- * used to determine the order in which nodes are visited during the traversal. The possible values
1239
- * for `iterationType` are typically defined as an enum or a
1240
- * @param [includeNull=false] - The `includeNull` parameter in the `dfs` function determines whether
1241
- * null nodes should be included in the depth-first search traversal. If `includeNull` is set to
1242
- * `true`, null nodes will be included in the traversal process. If it is set to `false`, null nodes
1243
- * will be skipped
1244
- * @returns The `dfs` method is returning an array of the return type of the callback function `C`.
1062
+ * Performs a Depth-First Search (DFS) traversal.
1063
+ * @remarks Time O(N), visits every node. Space O(H) for the call/explicit stack. O(N) worst-case.
1064
+ *
1065
+ * @template C - The type of the callback function.
1066
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
1067
+ * @param [pattern='IN'] - The traversal order ('IN', 'PRE', 'POST').
1068
+ * @param [onlyOne=false] - If true, stops after the first callback.
1069
+ * @param [startNode=this._root] - The node to start from.
1070
+ * @param [iterationType=this.iterationType] - The traversal method.
1071
+ * @param [includeNull=false] - If true, includes null nodes in the traversal.
1072
+ * @returns An array of callback results.
1245
1073
  */
1246
1074
  dfs(callback = this._DEFAULT_NODE_CALLBACK, pattern = 'IN', onlyOne = false, startNode = this._root, iterationType = this.iterationType, includeNull = false) {
1247
1075
  startNode = this.ensureNode(startNode);
@@ -1250,27 +1078,15 @@ export class BinaryTree extends IterableEntryBase {
1250
1078
  return this._dfs(callback, pattern, onlyOne, startNode, iterationType, includeNull);
1251
1079
  }
1252
1080
  /**
1253
- * Time complexity: O(n)
1254
- * Space complexity: O(n)
1255
- *
1256
- * The `bfs` function performs a breadth-first search traversal on a binary tree or binary search
1257
- * tree, executing a specified callback function on each node visited.
1258
- * @param {C} callback - The `callback` parameter in the `bfs` function is a function that will be
1259
- * called on each node visited during the breadth-first search traversal. It is a generic type `C`
1260
- * that extends the `NodeCallback` type, which takes a parameter of type `BinaryTreeNode<K, V>` or `null`.
1261
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `bfs`
1262
- * function represents the starting point for the breadth-first search traversal in a binary tree. It
1263
- * can be specified as a key, node, or entry in the binary tree structure. If not provided, the
1264
- * default value is the root node of the binary
1265
- * @param {IterationType} iterationType - The `iterationType` parameter in the `bfs` function
1266
- * determines the type of iteration to be performed on the binary tree nodes. It can have two
1267
- * possible values:
1268
- * @param [includeNull=false] - The `includeNull` parameter in the `bfs` function determines whether
1269
- * to include `null` values in the breadth-first search traversal of a binary tree. If `includeNull`
1270
- * is set to `true`, the traversal will include `null` values for nodes that do not have children
1271
- * (left
1272
- * @returns The `bfs` function returns an array of values that are the result of applying the
1273
- * provided callback function to each node in the binary tree in a breadth-first search manner.
1081
+ * Performs a Breadth-First Search (BFS) or Level-Order traversal.
1082
+ * @remarks Time O(N), visits every node. Space O(N) in the worst case for the queue (e.g., a full last level).
1083
+ *
1084
+ * @template C - The type of the callback function.
1085
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
1086
+ * @param [startNode=this._root] - The node to start from.
1087
+ * @param [iterationType=this.iterationType] - The traversal method ('RECURSIVE' BFS is less common but supported here).
1088
+ * @param [includeNull=false] - If true, includes null nodes in the traversal.
1089
+ * @returns An array of callback results.
1274
1090
  */
1275
1091
  bfs(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType, includeNull = false) {
1276
1092
  startNode = this.ensureNode(startNode);
@@ -1278,6 +1094,7 @@ export class BinaryTree extends IterableEntryBase {
1278
1094
  return [];
1279
1095
  const ans = [];
1280
1096
  if (iterationType === 'RECURSIVE') {
1097
+ // This is a "recursive" BFS, which is atypical. It uses a queue but calls itself.
1281
1098
  const queue = new Queue([
1282
1099
  startNode
1283
1100
  ]);
@@ -1303,9 +1120,10 @@ export class BinaryTree extends IterableEntryBase {
1303
1120
  dfs(0);
1304
1121
  }
1305
1122
  else {
1123
+ // Standard iterative BFS
1306
1124
  const queue = new Queue([startNode]);
1307
1125
  while (queue.length > 0) {
1308
- const levelSize = queue.length;
1126
+ const levelSize = queue.length; // Not strictly needed here, but good for level-by-level
1309
1127
  for (let i = 0; i < levelSize; i++) {
1310
1128
  const current = queue.shift();
1311
1129
  ans.push(callback(current));
@@ -1327,22 +1145,14 @@ export class BinaryTree extends IterableEntryBase {
1327
1145
  return ans;
1328
1146
  }
1329
1147
  /**
1330
- * Time complexity: O(n)
1331
- * Space complexity: O(n)
1148
+ * Finds all leaf nodes in the tree.
1149
+ * @remarks Time O(N), visits every node. Space O(H) for recursive stack or O(N) for iterative queue.
1332
1150
  *
1333
- * The `leaves` function in TypeScript returns an array of values from leaf nodes in a binary tree
1334
- * structure based on a specified callback and iteration type.
1335
- * @param {C} callback - The `callback` parameter is a function that will be called on each leaf node
1336
- * in the binary tree. It is optional and defaults to a default callback function if not provided.
1337
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `leaves`
1338
- * method is used to specify the starting point for finding and processing the leaves of a binary
1339
- * tree. It can be provided as either a key, a node, or an entry in the binary tree structure. If not
1340
- * explicitly provided, the default value
1341
- * @param {IterationType} iterationType - The `iterationType` parameter in the `leaves` method
1342
- * specifies the type of iteration to be performed when collecting the leaves of a binary tree. It
1343
- * can have two possible values:
1344
- * @returns The `leaves` method returns an array of values that are the result of applying the
1345
- * provided callback function to each leaf node in the binary tree.
1151
+ * @template C - The type of the callback function.
1152
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
1153
+ * @param [startNode=this._root] - The node to start from.
1154
+ * @param [iterationType=this.iterationType] - The traversal method.
1155
+ * @returns An array of callback results.
1346
1156
  */
1347
1157
  leaves(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType) {
1348
1158
  startNode = this.ensureNode(startNode);
@@ -1350,6 +1160,7 @@ export class BinaryTree extends IterableEntryBase {
1350
1160
  if (!this.isRealNode(startNode))
1351
1161
  return [];
1352
1162
  if (iterationType === 'RECURSIVE') {
1163
+ // DFS-based
1353
1164
  const dfs = (cur) => {
1354
1165
  if (this.isLeaf(cur)) {
1355
1166
  leaves.push(callback(cur));
@@ -1364,6 +1175,7 @@ export class BinaryTree extends IterableEntryBase {
1364
1175
  dfs(startNode);
1365
1176
  }
1366
1177
  else {
1178
+ // BFS-based
1367
1179
  const queue = new Queue([startNode]);
1368
1180
  while (queue.length > 0) {
1369
1181
  const cur = queue.shift();
@@ -1381,28 +1193,15 @@ export class BinaryTree extends IterableEntryBase {
1381
1193
  return leaves;
1382
1194
  }
1383
1195
  /**
1384
- * Time complexity: O(n)
1385
- * Space complexity: O(n)
1386
- *
1387
- * The `listLevels` function in TypeScript generates a list of nodes at each level of a binary tree,
1388
- * using either recursive or iterative traversal based on the specified iteration type.
1389
- * @param {C} callback - The `callback` parameter is a function that will be applied to each node in
1390
- * the binary tree during the traversal. It is used to process each node and determine what
1391
- * information to include in the output for each level of the tree.
1392
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1393
- * `listLevels` function represents the starting point for traversing the binary tree. It can be
1394
- * either a key, a node, or an entry in the binary tree. If not provided, the default value is the
1395
- * root of the binary tree.
1396
- * @param {IterationType} iterationType - The `iterationType` parameter in the `listLevels` function
1397
- * determines the type of iteration to be performed on the binary tree nodes. It can have two
1398
- * possible values:
1399
- * @param [includeNull=false] - The `includeNull` parameter in the `listLevels` method determines
1400
- * whether or not to include null nodes in the traversal of the binary tree. If `includeNull` is set
1401
- * to `true`, the traversal will include null nodes in the levels of the tree. If set to `false`,
1402
- * null
1403
- * @returns The `listLevels` method returns an array of arrays, where each inner array represents a
1404
- * level in a binary tree. Each inner array contains the return value of the provided callback
1405
- * function applied to the nodes at that level.
1196
+ * Returns a 2D array of nodes, grouped by level.
1197
+ * @remarks Time O(N), visits every node. Space O(N) for the result array and the queue/stack.
1198
+ *
1199
+ * @template C - The type of the callback function.
1200
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
1201
+ * @param [startNode=this._root] - The node to start from.
1202
+ * @param [iterationType=this.iterationType] - The traversal method.
1203
+ * @param [includeNull=false] - If true, includes null nodes.
1204
+ * @returns A 2D array of callback results.
1406
1205
  */
1407
1206
  listLevels(callback = this._DEFAULT_NODE_CALLBACK, startNode = this._root, iterationType = this.iterationType, includeNull = false) {
1408
1207
  startNode = this.ensureNode(startNode);
@@ -1410,6 +1209,7 @@ export class BinaryTree extends IterableEntryBase {
1410
1209
  if (!startNode)
1411
1210
  return levelsNodes;
1412
1211
  if (iterationType === 'RECURSIVE') {
1212
+ // Pre-order DFS based level listing
1413
1213
  const _recursive = (node, level) => {
1414
1214
  if (!levelsNodes[level])
1415
1215
  levelsNodes[level] = [];
@@ -1430,6 +1230,7 @@ export class BinaryTree extends IterableEntryBase {
1430
1230
  _recursive(startNode, 0);
1431
1231
  }
1432
1232
  else {
1233
+ // Iterative DFS based level listing
1433
1234
  const stack = [[startNode, 0]];
1434
1235
  while (stack.length > 0) {
1435
1236
  const head = stack.pop();
@@ -1454,24 +1255,14 @@ export class BinaryTree extends IterableEntryBase {
1454
1255
  return levelsNodes;
1455
1256
  }
1456
1257
  /**
1457
- * Time complexity: O(n)
1458
- * Space complexity: O(n)
1459
- *
1460
- * The `morris` function in TypeScript performs a Depth-First Search traversal on a binary tree using
1461
- * Morris Traversal algorithm with different order patterns.
1462
- * @param {C} callback - The `callback` parameter in the `morris` function is a function that will be
1463
- * called on each node in the binary tree during the traversal. It is of type `C`, which extends the
1464
- * `NodeCallback<BinaryTreeNode<K, V> | null>` type. The default value for `callback` is `this._DEFAULT
1465
- * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `morris` function specifies
1466
- * the type of Depth-First Search (DFS) order pattern to traverse the binary tree. The possible
1467
- * values for the `pattern` parameter are:
1468
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the `morris`
1469
- * function is the starting point for the Morris traversal algorithm. It represents the root node of
1470
- * the binary tree or the node from which the traversal should begin. It can be provided as either a
1471
- * key, a node, an entry, or a reference
1472
- * @returns The `morris` function is returning an array of values that are the result of applying the
1473
- * provided callback function to each node in the binary tree in the specified order pattern (IN,
1474
- * PRE, or POST).
1258
+ * Performs a Morris (threaded) traversal.
1259
+ * @remarks This traversal uses O(1) extra space (excluding the result array) by temporarily modifying the tree's right child pointers. Time O(N), as each node is visited a constant number of times. Space O(1) (excluding the `ans` array).
1260
+ *
1261
+ * @template C - The type of the callback function.
1262
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
1263
+ * @param [pattern='IN'] - The traversal order ('IN', 'PRE', 'POST').
1264
+ * @param [startNode=this._root] - The node to start from.
1265
+ * @returns An array of callback results.
1475
1266
  */
1476
1267
  morris(callback = this._DEFAULT_NODE_CALLBACK, pattern = 'IN', startNode = this._root) {
1477
1268
  startNode = this.ensureNode(startNode);
@@ -1479,6 +1270,7 @@ export class BinaryTree extends IterableEntryBase {
1479
1270
  return [];
1480
1271
  const ans = [];
1481
1272
  let cur = startNode;
1273
+ // Helper to reverse a linked list (formed by right pointers)
1482
1274
  const _reverseEdge = (node) => {
1483
1275
  let pre = null;
1484
1276
  let next = null;
@@ -1490,6 +1282,7 @@ export class BinaryTree extends IterableEntryBase {
1490
1282
  }
1491
1283
  return pre;
1492
1284
  };
1285
+ // Helper to print the reversed edge (for post-order)
1493
1286
  const _printEdge = (node) => {
1494
1287
  const tail = _reverseEdge(node);
1495
1288
  let cur = tail;
@@ -1497,7 +1290,7 @@ export class BinaryTree extends IterableEntryBase {
1497
1290
  ans.push(callback(cur));
1498
1291
  cur = cur.right;
1499
1292
  }
1500
- _reverseEdge(tail);
1293
+ _reverseEdge(tail); // Restore the edge
1501
1294
  };
1502
1295
  switch (pattern) {
1503
1296
  case 'IN':
@@ -1505,11 +1298,13 @@ export class BinaryTree extends IterableEntryBase {
1505
1298
  if (cur.left) {
1506
1299
  const predecessor = this.getPredecessor(cur);
1507
1300
  if (!predecessor.right) {
1301
+ // Create thread
1508
1302
  predecessor.right = cur;
1509
1303
  cur = cur.left;
1510
1304
  continue;
1511
1305
  }
1512
1306
  else {
1307
+ // Remove thread
1513
1308
  predecessor.right = null;
1514
1309
  }
1515
1310
  }
@@ -1522,12 +1317,14 @@ export class BinaryTree extends IterableEntryBase {
1522
1317
  if (cur.left) {
1523
1318
  const predecessor = this.getPredecessor(cur);
1524
1319
  if (!predecessor.right) {
1320
+ // Create thread and visit
1525
1321
  predecessor.right = cur;
1526
1322
  ans.push(callback(cur));
1527
1323
  cur = cur.left;
1528
1324
  continue;
1529
1325
  }
1530
1326
  else {
1327
+ // Remove thread
1531
1328
  predecessor.right = null;
1532
1329
  }
1533
1330
  }
@@ -1542,108 +1339,77 @@ export class BinaryTree extends IterableEntryBase {
1542
1339
  if (cur.left) {
1543
1340
  const predecessor = this.getPredecessor(cur);
1544
1341
  if (predecessor.right === null) {
1342
+ // Create thread
1545
1343
  predecessor.right = cur;
1546
1344
  cur = cur.left;
1547
1345
  continue;
1548
1346
  }
1549
1347
  else {
1348
+ // Remove thread and print right spine of left child
1550
1349
  predecessor.right = null;
1551
1350
  _printEdge(cur.left);
1552
1351
  }
1553
1352
  }
1554
1353
  cur = cur.right;
1555
1354
  }
1556
- _printEdge(startNode);
1355
+ _printEdge(startNode); // Print the right spine of the root
1557
1356
  break;
1558
1357
  }
1559
1358
  return ans;
1560
1359
  }
1561
1360
  /**
1562
- * Time complexity: O(n)
1563
- * Space complexity: O(n)
1361
+ * Clones the tree.
1362
+ * @remarks Time O(N * M), where N is the number of nodes and M is the tree size during insertion (due to `bfs` + `add`, and `add` is O(M)). Space O(N) for the new tree and the BFS queue.
1564
1363
  *
1565
- * The `clone` function creates a deep copy of a tree structure by traversing it using breadth-first
1566
- * search.
1567
- * @returns The `clone()` method is returning a cloned copy of the tree with the same structure and
1568
- * values as the original tree. The method creates a new tree, iterates over the nodes of the
1569
- * original tree using breadth-first search (bfs), and adds the nodes to the new tree. If a node in
1570
- * the original tree is null, a null node is added to the cloned tree. If a node
1364
+ * @returns A new, cloned instance of the tree.
1571
1365
  */
1572
1366
  clone() {
1573
- const cloned = this.createTree();
1574
- this._clone(cloned);
1575
- return cloned;
1576
- }
1577
- /**
1578
- * Time Complexity: O(n)
1579
- * Space Complexity: O(n)
1580
- *
1581
- * The `filter` function iterates over key-value pairs in a tree data structure and creates a new
1582
- * tree with elements that satisfy a given predicate.
1583
- * @param predicate - The `predicate` parameter in the `filter` method is a function that will be
1584
- * called with four arguments: the `value` of the current entry, the `key` of the current entry, the
1585
- * `index` of the current entry in the iteration, and the reference to the tree itself (`
1586
- * @param {any} [thisArg] - The `thisArg` parameter in the `filter` method allows you to specify the
1587
- * value of `this` that should be used when executing the `predicate` function. This is useful when
1588
- * the `predicate` function relies on the context of a specific object or value. By providing a
1589
- * `thisArg
1590
- * @returns The `filter` method is returning a new tree that contains entries that pass the provided
1591
- * predicate function.
1367
+ const out = this._createInstance();
1368
+ this._clone(out);
1369
+ return out;
1370
+ }
1371
+ /**
1372
+ * Creates a new tree containing only the entries that satisfy the predicate.
1373
+ * @remarks Time O(N * M), where N is nodes in this tree, and M is size of the new tree during insertion (O(N) iteration + O(M) `add` for each item). Space O(N) for the new tree.
1374
+ *
1375
+ * @param predicate - A function to test each [key, value] pair.
1376
+ * @param [thisArg] - `this` context for the predicate.
1377
+ * @returns A new, filtered tree.
1592
1378
  */
1593
1379
  filter(predicate, thisArg) {
1594
- const newTree = this.createTree();
1595
- let index = 0;
1596
- for (const [key, value] of this) {
1597
- if (predicate.call(thisArg, key, value, index++, this)) {
1598
- newTree.add([key, value]);
1599
- }
1600
- }
1601
- return newTree;
1602
- }
1603
- /**
1604
- * Time Complexity: O(n)
1605
- * Space Complexity: O(n)
1606
- *
1607
- * The `map` function in TypeScript creates a new BinaryTree by applying a callback function to each
1608
- * entry in the original BinaryTree.
1609
- * @param callback - A function that will be called for each entry in the current binary tree. It
1610
- * takes the key, value (which can be undefined), and an array containing the mapped key and value as
1611
- * arguments.
1612
- * @param [options] - The `options` parameter in the `map` method is of type `BinaryTreeOptions<MK,
1613
- * MV, MR>`. It is an optional parameter that allows you to specify additional options for the binary
1614
- * tree being created during the mapping process. These options could include things like custom
1615
- * comparators, initial
1616
- * @param {any} [thisArg] - The `thisArg` parameter in the `map` method is used to specify the value
1617
- * of `this` when executing the `callback` function. It allows you to set the context (value of
1618
- * `this`) within the callback function. If `thisArg` is provided, it will be passed
1619
- * @returns The `map` function is returning a new `BinaryTree` instance filled with entries that are
1620
- * the result of applying the provided `callback` function to each entry in the original tree.
1621
- */
1622
- map(callback, options, thisArg) {
1623
- const newTree = new BinaryTree([], options);
1624
- let index = 0;
1625
- for (const [key, value] of this) {
1626
- newTree.add(callback.call(thisArg, key, value, index++, this));
1627
- }
1628
- return newTree;
1629
- }
1630
- /**
1631
- * Time Complexity: O(n)
1632
- * Space Complexity: O(n)
1633
- *
1634
- * The function `toVisual` in TypeScript overrides the visual representation of a binary tree with
1635
- * customizable options for displaying undefined, null, and sentinel nodes.
1636
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1637
- * `toVisual` method is used to specify the starting point for visualizing the binary tree structure.
1638
- * It can be a node, key, entry, or the root of the tree. If no specific starting point is provided,
1639
- * the default is set to the root
1640
- * @param {BinaryTreePrintOptions} [options] - The `options` parameter in the `toVisual` method is an
1641
- * object that contains the following properties:
1642
- * @returns The `override toVisual` method returns a string that represents the visual display of the
1643
- * binary tree based on the provided options for showing undefined, null, and Red-Black NIL nodes.
1644
- * The method constructs the visual representation by calling the `_displayAux` method and appending
1645
- * the lines to the output string. The final output string contains the visual representation of the
1646
- * binary tree with the specified options.
1380
+ const out = this._createInstance();
1381
+ let i = 0;
1382
+ for (const [k, v] of this)
1383
+ if (predicate.call(thisArg, k, v, i++, this))
1384
+ out.add([k, v]);
1385
+ return out;
1386
+ }
1387
+ /**
1388
+ * Creates a new tree by mapping each [key, value] pair to a new entry.
1389
+ * @remarks Time O(N * M), where N is nodes in this tree, and M is size of the new tree during insertion. Space O(N) for the new tree.
1390
+ *
1391
+ * @template MK - New key type.
1392
+ * @template MV - New value type.
1393
+ * @template MR - New raw type.
1394
+ * @param cb - A function to map each [key, value] pair.
1395
+ * @param [options] - Options for the new tree.
1396
+ * @param [thisArg] - `this` context for the callback.
1397
+ * @returns A new, mapped tree.
1398
+ */
1399
+ map(cb, options, thisArg) {
1400
+ const out = this._createLike([], options);
1401
+ let i = 0;
1402
+ for (const [k, v] of this)
1403
+ out.add(cb.call(thisArg, k, v, i++, this));
1404
+ return out;
1405
+ }
1406
+ /**
1407
+ * Generates a string representation of the tree for visualization.
1408
+ * @remarks Time O(N), visits every node. Space O(N*H) or O(N^2) in the worst case, as the string width can grow significantly.
1409
+ *
1410
+ * @param [startNode=this._root] - The node to start printing from.
1411
+ * @param [options] - Options to control the output (e.g., show nulls).
1412
+ * @returns The string representation of the tree.
1647
1413
  */
1648
1414
  toVisual(startNode = this._root, options) {
1649
1415
  const opts = { isShowUndefined: false, isShowNull: true, isShowRedBlackNIL: false, ...options };
@@ -1669,117 +1435,31 @@ export class BinaryTree extends IterableEntryBase {
1669
1435
  return output;
1670
1436
  }
1671
1437
  /**
1672
- * Time Complexity: O(n)
1673
- * Space Complexity: O(n)
1438
+ * Prints a visual representation of the tree to the console.
1439
+ * @remarks Time O(N) (via `toVisual`). Space O(N*H) or O(N^2) (via `toVisual`).
1674
1440
  *
1675
- * The function `print` in TypeScript overrides the default print behavior to log a visual
1676
- * representation of the binary tree to the console.
1677
- * @param {BinaryTreePrintOptions} [options] - The `options` parameter is used to specify the
1678
- * printing options for the binary tree. It is an optional parameter that allows you to customize how
1679
- * the binary tree is printed, such as choosing between different traversal orders or formatting
1680
- * options.
1681
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } startNode - The `startNode` parameter in the
1682
- * `override print` method is used to specify the starting point for printing the binary tree. It can
1683
- * be either a key, a node, an entry, or the root of the tree. If no specific starting point is
1684
- * provided, the default value is set to
1441
+ * @param [options] - Options to control the output.
1442
+ * @param [startNode=this._root] - The node to start printing from.
1685
1443
  */
1686
1444
  print(options, startNode = this._root) {
1687
1445
  console.log(this.toVisual(startNode, options));
1688
1446
  }
1689
- _clone(cloned) {
1690
- this.bfs(node => {
1691
- if (node === null)
1692
- cloned.add(null);
1693
- else {
1694
- if (this._isMapMode)
1695
- cloned.add([node.key, this._store.get(node.key)]);
1696
- else
1697
- cloned.add([node.key, node.value]);
1698
- }
1699
- }, this._root, this.iterationType, true);
1700
- if (this._isMapMode)
1701
- cloned._store = this._store;
1702
- }
1703
1447
  /**
1704
- * Time Complexity: O(1)
1705
- * Space Complexity: O(1)
1448
+ * (Protected) Core DFS implementation.
1449
+ * @remarks Time O(N), visits every node satisfying predicates. Space O(H) for call/explicit stack. O(N) worst-case.
1706
1450
  *
1707
- * The function `keyValueNodeEntryRawToNodeAndValue` converts various input types into a node object
1708
- * or returns null.
1709
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The
1710
- * `keyValueNodeEntryRawToNodeAndValue` function takes in a parameter `keyNodeOrEntry`, which
1711
- * can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. This parameter represents either a key, a
1712
- * node, an entry
1713
- * @param {V} [value] - The `value` parameter in the `keyValueNodeEntryRawToNodeAndValue` function is
1714
- * an optional parameter of type `V`. It represents the value associated with the key in the node
1715
- * being created. If a `value` is provided, it will be used when creating the node. If
1716
- * @returns The `keyValueNodeEntryRawToNodeAndValue` function returns an optional node
1717
- * (`BinaryTreeNode<K, V> | null | undefined`) based on the input parameters provided. The function checks the type of the
1718
- * input parameter (`keyNodeOrEntry`) and processes it accordingly to return a node or null
1719
- * value.
1720
- */
1721
- _keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value) {
1722
- if (keyNodeOrEntry === undefined)
1723
- return [undefined, undefined];
1724
- if (keyNodeOrEntry === null)
1725
- return [null, undefined];
1726
- if (this.isNode(keyNodeOrEntry))
1727
- return [keyNodeOrEntry, value];
1728
- if (this.isEntry(keyNodeOrEntry)) {
1729
- const [key, entryValue] = keyNodeOrEntry;
1730
- if (key === undefined)
1731
- return [undefined, undefined];
1732
- else if (key === null)
1733
- return [null, undefined];
1734
- const finalValue = value ?? entryValue;
1735
- return [this.createNode(key, finalValue), finalValue];
1736
- }
1737
- return [this.createNode(keyNodeOrEntry, value), value];
1738
- }
1739
- /**
1740
- * Time complexity: O(n)
1741
- * Space complexity: O(n)
1742
- *
1743
- * The `_dfs` function performs a depth-first search traversal on a binary tree, with customizable
1744
- * options for traversal order and node processing.
1745
- * @param {C} callback - The `callback` parameter in the `_dfs` method is a function that will be
1746
- * called on each node visited during the depth-first search traversal. It is a generic type `C` that
1747
- * extends `NodeCallback<BinaryTreeNode<K, V> | null>`. The default value for `callback`
1748
- * @param {DFSOrderPattern} [pattern=IN] - The `pattern` parameter in the `_dfs` method specifies the
1749
- * order in which the nodes are visited during a depth-first search traversal. It can have one of the
1750
- * following values:
1751
- * @param {boolean} [onlyOne=false] - The `onlyOne` parameter in the `_dfs` method is a boolean flag
1752
- * that determines whether the traversal should stop after processing a single node. If `onlyOne` is
1753
- * set to `true`, the traversal will return as soon as a single node is processed. If it is set to
1754
- * `false
1755
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined}
1756
- * startNode - The `startNode` parameter in the `_dfs` method is used to specify the starting node
1757
- * for the depth-first search traversal. It can be provided in different forms:
1758
- * @param {IterationType} iterationType - The `iterationType` parameter in the `_dfs` method
1759
- * specifies whether the traversal should be done recursively or iteratively. It can have two
1760
- * possible values:
1761
- * @param [includeNull=false] - The `includeNull` parameter in the `_dfs` method determines whether
1762
- * null nodes should be included in the traversal process. If `includeNull` is set to `true`, the
1763
- * method will consider null nodes as valid nodes to visit or process. If `includeNull` is set to
1764
- * `false`,
1765
- * @param shouldVisitLeft - The `shouldVisitLeft` parameter in the `_dfs` method is a function that
1766
- * determines whether the left child of a node should be visited during the Depth-First Search
1767
- * traversal. By default, it checks if the node is not null or undefined before visiting the left
1768
- * child. You can customize this behavior
1769
- * @param shouldVisitRight - The `shouldVisitRight` parameter in the `_dfs` method is a function that
1770
- * determines whether to visit the right child node of the current node during a depth-first search
1771
- * traversal. The default implementation of this function checks if the node is not null or undefined
1772
- * before deciding to visit it.
1773
- * @param shouldVisitRoot - The `shouldVisitRoot` parameter in the `_dfs` method is a function that
1774
- * determines whether a given node should be visited during the depth-first search traversal. The
1775
- * function takes a node as an argument and returns a boolean value indicating whether the node
1776
- * should be visited.
1777
- * @param shouldProcessRoot - The `shouldProcessRoot` parameter in the `_dfs` method is a function
1778
- * that determines whether the root node should be processed during the Depth-First Search traversal.
1779
- * It takes a node (BinaryTreeNode<K, V> | null | undefined) as input and returns a boolean value. If
1780
- * the function
1781
- * @returns The `_dfs` method returns an array of the return type of the provided callback function
1782
- * `C`.
1451
+ * @template C - Callback type.
1452
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on nodes.
1453
+ * @param [pattern='IN'] - Traversal order.
1454
+ * @param [onlyOne=false] - Stop after first match.
1455
+ * @param [startNode=this._root] - Starting node.
1456
+ * @param [iterationType=this.iterationType] - Traversal method.
1457
+ * @param [includeNull=false] - Include nulls.
1458
+ * @param [shouldVisitLeft] - Predicate to traverse left.
1459
+ * @param [shouldVisitRight] - Predicate to traverse right.
1460
+ * @param [shouldVisitRoot] - Predicate to visit root.
1461
+ * @param [shouldProcessRoot] - Predicate to process root.
1462
+ * @returns Array of callback results.
1783
1463
  */
1784
1464
  _dfs(callback = this._DEFAULT_NODE_CALLBACK, pattern = 'IN', onlyOne = false, startNode = this._root, iterationType = this.iterationType, includeNull = false, shouldVisitLeft = node => !!node, shouldVisitRight = node => !!node, shouldVisitRoot = node => {
1785
1465
  if (includeNull)
@@ -1835,6 +1515,7 @@ export class BinaryTree extends IterableEntryBase {
1835
1515
  dfs(startNode);
1836
1516
  }
1837
1517
  else {
1518
+ // Iterative
1838
1519
  const stack = [{ opt: DFSOperation.VISIT, node: startNode }];
1839
1520
  const pushLeft = (cur) => {
1840
1521
  if (shouldVisitLeft(cur.node))
@@ -1862,6 +1543,7 @@ export class BinaryTree extends IterableEntryBase {
1862
1543
  }
1863
1544
  }
1864
1545
  else {
1546
+ // VISIT
1865
1547
  switch (pattern) {
1866
1548
  case 'IN':
1867
1549
  pushRight(cur);
@@ -1885,19 +1567,11 @@ export class BinaryTree extends IterableEntryBase {
1885
1567
  return ans;
1886
1568
  }
1887
1569
  /**
1888
- * Time Complexity: O(1)
1889
- * Space Complexity: O(1)
1570
+ * (Protected) Gets the iterator for the tree (default in-order).
1571
+ * @remarks Time O(N) for full iteration. O(H) to get the first element. Space O(H) for the iterative stack. O(H) for recursive stack.
1890
1572
  *
1891
- * The function `_getIterator` returns an iterable iterator for a binary tree data structure, either
1892
- * using an iterative approach or a recursive approach based on the specified iteration type.
1893
- * @param node - The `node` parameter in the `_getIterator` method represents the current node being
1894
- * processed during iteration. It is initially set to the root node of the data structure (or the
1895
- * node passed as an argument), and then it is traversed through the data structure based on the
1896
- * iteration type specified (`ITER
1897
- * @returns The `_getIterator` method returns an IterableIterator containing key-value pairs of nodes
1898
- * in a binary tree structure. The method uses an iterative approach to traverse the tree based on
1899
- * the `iterationType` property. If the `iterationType` is set to 'ITERATIVE', the method uses a
1900
- * stack to perform an in-order traversal of the tree. If the `iterationType` is not 'ITERATIVE
1573
+ * @param [node=this._root] - The node to start iteration from.
1574
+ * @returns An iterator for [key, value] pairs.
1901
1575
  */
1902
1576
  *_getIterator(node = this._root) {
1903
1577
  if (!node)
@@ -1906,21 +1580,25 @@ export class BinaryTree extends IterableEntryBase {
1906
1580
  const stack = [];
1907
1581
  let current = node;
1908
1582
  while (current || stack.length > 0) {
1583
+ // Go to the leftmost node
1909
1584
  while (this.isRealNode(current)) {
1910
1585
  stack.push(current);
1911
1586
  current = current.left;
1912
1587
  }
1588
+ // Visit the node
1913
1589
  current = stack.pop();
1914
1590
  if (this.isRealNode(current)) {
1915
1591
  if (this._isMapMode)
1916
1592
  yield [current.key, this._store.get(current.key)];
1917
1593
  else
1918
1594
  yield [current.key, current.value];
1595
+ // Move to the right subtree
1919
1596
  current = current.right;
1920
1597
  }
1921
1598
  }
1922
1599
  }
1923
1600
  else {
1601
+ // Recursive in-order traversal
1924
1602
  if (node.left && this.isRealNode(node)) {
1925
1603
  yield* this[Symbol.iterator](node.left);
1926
1604
  }
@@ -1934,24 +1612,112 @@ export class BinaryTree extends IterableEntryBase {
1934
1612
  }
1935
1613
  }
1936
1614
  /**
1937
- * Time Complexity: O(n)
1938
- * Space Complexity: O(n)
1615
+ * (Protected) Default callback function, returns the node's key.
1616
+ * @remarks Time O(1)
1617
+ *
1618
+ * @param node - The node.
1619
+ * @returns The node's key or undefined.
1620
+ */
1621
+ _DEFAULT_NODE_CALLBACK = (node) => (node ? node.key : undefined);
1622
+ /**
1623
+ * (Protected) Snapshots the current tree's configuration options.
1624
+ * @remarks Time O(1)
1625
+ *
1626
+ * @template TK, TV, TR - Generic types for the options.
1627
+ * @returns The options object.
1628
+ */
1629
+ _snapshotOptions() {
1630
+ return {
1631
+ iterationType: this.iterationType,
1632
+ toEntryFn: this.toEntryFn,
1633
+ isMapMode: this.isMapMode,
1634
+ isDuplicate: this.isDuplicate
1635
+ };
1636
+ }
1637
+ /**
1638
+ * (Protected) Creates a new, empty instance of the same tree constructor.
1639
+ * @remarks Time O(1)
1640
+ *
1641
+ * @template TK, TV, TR - Generic types for the new instance.
1642
+ * @param [options] - Options for the new tree.
1643
+ * @returns A new, empty tree.
1644
+ */
1645
+ _createInstance(options) {
1646
+ const Ctor = this.constructor;
1647
+ return new Ctor([], { ...this._snapshotOptions(), ...(options ?? {}) });
1648
+ }
1649
+ /**
1650
+ * (Protected) Creates a new instance of the same tree constructor, potentially with different generic types.
1651
+ * @remarks Time O(N) (or as per constructor) due to processing the iterable.
1939
1652
  *
1940
- * The function `_displayAux` in TypeScript is responsible for generating the display layout of nodes
1941
- * in a binary tree based on specified options.
1942
- * @param node - The `node` parameter in the `_displayAux` function represents a node in a binary
1943
- * tree. It can be either a valid node containing a key or a special type of node like null,
1944
- * undefined, or a Red-Black tree NIL node. The function checks the type of the node and its
1945
- * @param {BinaryTreePrintOptions} options - The `options` parameter in the `_displayAux` function
1946
- * contains the following properties:
1947
- * @returns The `_displayAux` function returns a `NodeDisplayLayout`, which is an array containing
1948
- * information about how to display a node in a binary tree. The `NodeDisplayLayout` consists of four
1949
- * elements:
1653
+ * @template TK, TV, TR - Generic types for the new instance.
1654
+ * @param [iter=[]] - An iterable to populate the new tree.
1655
+ * @param [options] - Options for the new tree.
1656
+ * @returns A new tree.
1657
+ */
1658
+ _createLike(iter = [], options) {
1659
+ const Ctor = this.constructor;
1660
+ return new Ctor(iter, { ...this._snapshotOptions(), ...(options ?? {}) });
1661
+ }
1662
+ /**
1663
+ * (Protected) Converts a key, node, or entry into a standardized [node, value] tuple.
1664
+ * @remarks Time O(1)
1665
+ *
1666
+ * @param keyNodeOrEntry - The input item.
1667
+ * @param [value] - An optional value (used if input is just a key).
1668
+ * @returns A tuple of [node, value].
1669
+ */
1670
+ _keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value) {
1671
+ if (keyNodeOrEntry === undefined)
1672
+ return [undefined, undefined];
1673
+ if (keyNodeOrEntry === null)
1674
+ return [null, undefined];
1675
+ if (this.isNode(keyNodeOrEntry))
1676
+ return [keyNodeOrEntry, value];
1677
+ if (this.isEntry(keyNodeOrEntry)) {
1678
+ const [key, entryValue] = keyNodeOrEntry;
1679
+ if (key === undefined)
1680
+ return [undefined, undefined];
1681
+ else if (key === null)
1682
+ return [null, undefined];
1683
+ const finalValue = value ?? entryValue;
1684
+ return [this._createNode(key, finalValue), finalValue];
1685
+ }
1686
+ return [this._createNode(keyNodeOrEntry, value), value];
1687
+ }
1688
+ /**
1689
+ * (Protected) Helper for cloning. Performs a BFS and adds all nodes to the new tree.
1690
+ * @remarks Time O(N * M) (O(N) BFS + O(M) `add` for each node).
1691
+ *
1692
+ * @param cloned - The new, empty tree instance to populate.
1693
+ */
1694
+ _clone(cloned) {
1695
+ // Use BFS with nulls to preserve the tree structure
1696
+ this.bfs(node => {
1697
+ if (node === null)
1698
+ cloned.add(null);
1699
+ else {
1700
+ if (this._isMapMode)
1701
+ cloned.add([node.key, this._store.get(node.key)]);
1702
+ else
1703
+ cloned.add([node.key, node.value]);
1704
+ }
1705
+ }, this._root, this.iterationType, true // Include nulls
1706
+ );
1707
+ if (this._isMapMode)
1708
+ cloned._store = this._store;
1709
+ }
1710
+ /**
1711
+ * (Protected) Recursive helper for `toVisual`.
1712
+ * @remarks Time O(N), Space O(N*H) or O(N^2)
1713
+ *
1714
+ * @param node - The current node.
1715
+ * @param options - Print options.
1716
+ * @returns Layout information for this subtree.
1950
1717
  */
1951
1718
  _displayAux(node, options) {
1952
1719
  const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
1953
- const emptyDisplayLayout = [['─'], 1, 0, 0];
1954
- // Check if node is null or undefined or key is NaN
1720
+ const emptyDisplayLayout = [['─'], 1, 0, 0]; // Represents an empty spot
1955
1721
  if (node === null && !isShowNull) {
1956
1722
  return emptyDisplayLayout;
1957
1723
  }
@@ -1962,15 +1728,20 @@ export class BinaryTree extends IterableEntryBase {
1962
1728
  return emptyDisplayLayout;
1963
1729
  }
1964
1730
  else if (node !== null && node !== undefined) {
1965
- // Display logic of normal nodes
1731
+ // Real node
1966
1732
  const key = node.key, line = this.isNIL(node) ? 'S' : String(key), width = line.length;
1967
1733
  return _buildNodeDisplay(line, width, this._displayAux(node.left, options), this._displayAux(node.right, options));
1968
1734
  }
1969
1735
  else {
1970
- // For cases where none of the conditions are met, null, undefined, and NaN nodes are not displayed
1736
+ // Null or Undefined
1971
1737
  const line = node === undefined ? 'U' : 'N', width = line.length;
1738
+ // Treat as a leaf
1972
1739
  return _buildNodeDisplay(line, width, [[''], 1, 0, 0], [[''], 1, 0, 0]);
1973
1740
  }
1741
+ /**
1742
+ * (Inner) Builds the display lines for a node.
1743
+ * @remarks Time/Space: Proportional to the width and height of the subtrees.
1744
+ */
1974
1745
  function _buildNodeDisplay(line, width, left, right) {
1975
1746
  const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
1976
1747
  const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
@@ -2000,32 +1771,26 @@ export class BinaryTree extends IterableEntryBase {
2000
1771
  ];
2001
1772
  }
2002
1773
  }
2003
- _DEFAULT_NODE_CALLBACK = (node) => (node ? node.key : undefined);
2004
1774
  /**
2005
- * Time Complexity: O(1)
2006
- * Space Complexity: O(1)
1775
+ * (Protected) Swaps the key/value properties of two nodes.
1776
+ * @remarks Time O(1)
2007
1777
  *
2008
- * The _swapProperties function swaps key and value properties between two nodes in a binary tree.
2009
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } srcNode - The `srcNode` parameter in the
2010
- * `_swapProperties` method can be either a BTNRep object containing key and value
2011
- * properties, or it can be of type R.
2012
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } destNode - The `destNode` parameter in the
2013
- * `_swapProperties` method represents the node or entry where the properties will be swapped with
2014
- * the `srcNode`. It can be of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined ` or `R`. The method ensures that
2015
- * both `srcNode
2016
- * @returns The `_swapProperties` method returns either the `destNode` with its key and value swapped
2017
- * with the `srcNode`, or `undefined` if either `srcNode` or `destNode` is falsy.
1778
+ * @param srcNode - The source node.
1779
+ * @param destNode - The destination node.
1780
+ * @returns The `destNode` (now holding `srcNode`'s properties).
2018
1781
  */
2019
1782
  _swapProperties(srcNode, destNode) {
2020
1783
  srcNode = this.ensureNode(srcNode);
2021
1784
  destNode = this.ensureNode(destNode);
2022
1785
  if (srcNode && destNode) {
2023
1786
  const { key, value } = destNode;
2024
- const tempNode = this.createNode(key, value);
1787
+ const tempNode = this._createNode(key, value); // Use a temp node to hold dest properties
2025
1788
  if (tempNode) {
1789
+ // Copy src to dest
2026
1790
  destNode.key = srcNode.key;
2027
1791
  if (!this._isMapMode)
2028
1792
  destNode.value = srcNode.value;
1793
+ // Copy temp (original dest) to src
2029
1794
  srcNode.key = tempNode.key;
2030
1795
  if (!this._isMapMode)
2031
1796
  srcNode.value = tempNode.value;
@@ -2035,18 +1800,12 @@ export class BinaryTree extends IterableEntryBase {
2035
1800
  return undefined;
2036
1801
  }
2037
1802
  /**
2038
- * Time Complexity: O(1)
2039
- * Space Complexity: O(1)
1803
+ * (Protected) Replaces a node in the tree with a new node, maintaining children and parent links.
1804
+ * @remarks Time O(1)
2040
1805
  *
2041
- * The _replaceNode function replaces an old node with a new node in a binary tree structure.
2042
- * @param {BinaryTreeNode<K, V>} oldNode - The `oldNode` parameter represents the node that you want to replace in a
2043
- * tree data structure.
2044
- * @param {BinaryTreeNode<K, V>} newNode - The `newNode` parameter in the `_replaceNode` function represents the node
2045
- * that will replace the `oldNode` in a tree data structure. This function is responsible for
2046
- * updating the parent, left child, right child, and root (if necessary) references when replacing a
2047
- * node in the tree.
2048
- * @returns The method `_replaceNode` is returning the `newNode` that was passed as a parameter after
2049
- * replacing the `oldNode` with it in the binary tree structure.
1806
+ * @param oldNode - The node to be replaced.
1807
+ * @param newNode - The node to insert.
1808
+ * @returns The `newNode`.
2050
1809
  */
2051
1810
  _replaceNode(oldNode, newNode) {
2052
1811
  if (oldNode.parent) {
@@ -2066,13 +1825,10 @@ export class BinaryTree extends IterableEntryBase {
2066
1825
  return newNode;
2067
1826
  }
2068
1827
  /**
2069
- * Time Complexity: O(1)
2070
- * Space Complexity: O(1)
1828
+ * (Protected) Sets the root node and clears its parent reference.
1829
+ * @remarks Time O(1)
2071
1830
  *
2072
- * The function _setRoot sets the root node of a data structure while updating the parent reference
2073
- * of the previous root node.
2074
- * @param v - The parameter `v` in the `_setRoot` method is of type `BinaryTreeNode<K, V> | null | undefined`, which means
2075
- * it can either be an optional `BinaryTreeNode<K, V>` type or `null`.
1831
+ * @param v - The node to set as root.
2076
1832
  */
2077
1833
  _setRoot(v) {
2078
1834
  if (v) {
@@ -2080,18 +1836,6 @@ export class BinaryTree extends IterableEntryBase {
2080
1836
  }
2081
1837
  this._root = v;
2082
1838
  }
2083
- /**
2084
- * Time Complexity: O(1)
2085
- * Space Complexity: O(1)
2086
- *
2087
- * The function `_ensurePredicate` in TypeScript ensures that the input is converted into a valid
2088
- * predicate function for a binary tree node.
2089
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | NodePredicate<BinaryTreeNode<K, V>>} keyNodeEntryOrPredicate - The
2090
- * `_ensurePredicate` method in the provided code snippet is responsible for ensuring that the input
2091
- * parameter `keyNodeEntryOrPredicate` is transformed into a valid predicate function that can be
2092
- * used for filtering nodes in a binary tree.
2093
- * @returns A NodePredicate<BinaryTreeNode<K, V>> function is being returned.
2094
- */
2095
1839
  _ensurePredicate(keyNodeEntryOrPredicate) {
2096
1840
  if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined)
2097
1841
  return (node) => (node ? false : false);
@@ -2107,6 +1851,7 @@ export class BinaryTree extends IterableEntryBase {
2107
1851
  return node.key === key;
2108
1852
  };
2109
1853
  }
1854
+ // Assume it's a key
2110
1855
  return (node) => {
2111
1856
  if (!node)
2112
1857
  return false;
@@ -2114,32 +1859,21 @@ export class BinaryTree extends IterableEntryBase {
2114
1859
  };
2115
1860
  }
2116
1861
  /**
2117
- * Time Complexity: O(1)
2118
- * Space Complexity: O(1)
1862
+ * (Protected) Checks if an item is a predicate function.
1863
+ * @remarks Time O(1)
2119
1864
  *
2120
- * The function `_isPredicate` checks if a given parameter is a function.
2121
- * @param {any} p - The parameter `p` is a variable of type `any`, which means it can hold any type
2122
- * of value. In this context, the function `_isPredicate` is checking if `p` is a function that
2123
- * satisfies the type `NodePredicate<BinaryTreeNode<K, V>>`.
2124
- * @returns The function is checking if the input `p` is a function and returning a boolean value
2125
- * based on that check. If `p` is a function, it will return `true`, indicating that `p` is a
2126
- * predicate function for a binary tree node. If `p` is not a function, it will return `false`.
1865
+ * @param p - The item to check.
1866
+ * @returns True if it's a function.
2127
1867
  */
2128
1868
  _isPredicate(p) {
2129
1869
  return typeof p === 'function';
2130
1870
  }
2131
1871
  /**
2132
- * Time Complexity: O(1)
2133
- * Space Complexity: O(1)
1872
+ * (Protected) Extracts the key from a key, node, or entry.
1873
+ * @remarks Time O(1)
2134
1874
  *
2135
- * The function `_extractKey` in TypeScript returns the key from a given input, which can be a node,
2136
- * entry, raw data, or null/undefined.
2137
- * @param {K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined } keyNodeOrEntry - The `_extractKey` method you provided is a
2138
- * TypeScript method that takes in a parameter `keyNodeOrEntry` of type `K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined `,
2139
- * where `BTNRep` is a generic type with keys `K`, `V`, and `BinaryTreeNode<K, V>`, and `
2140
- * @returns The `_extractKey` method returns the key value extracted from the `keyNodeOrEntry`
2141
- * parameter. The return value can be a key value of type `K`, `null`, or `undefined`, depending on
2142
- * the conditions checked in the method.
1875
+ * @param keyNodeOrEntry - The item.
1876
+ * @returns The extracted key.
2143
1877
  */
2144
1878
  _extractKey(keyNodeOrEntry) {
2145
1879
  if (keyNodeOrEntry === null)
@@ -2155,41 +1889,31 @@ export class BinaryTree extends IterableEntryBase {
2155
1889
  return keyNodeOrEntry;
2156
1890
  }
2157
1891
  /**
2158
- * Time Complexity: O(1)
2159
- * Space Complexity: O(1)
1892
+ * (Protected) Sets a value in the external store (Map mode).
1893
+ * @remarks Time O(1) (average for Map.set).
2160
1894
  *
2161
- * The function `_setValue` sets a value in a store based on a key, handling cases where the key or
2162
- * value is null or undefined.
2163
- * @param {K | null | undefined} key - The `key` parameter can be of type `K`, `null`, or
2164
- * `undefined`.
2165
- * @param {V | undefined} value - The `value` parameter in the `_setValue` method can be of type `V`
2166
- * or `undefined`.
2167
- * @returns The method `_setValue` returns `false` if either the `key` is `null` or `undefined`, or
2168
- * if the `value` is `undefined`. Otherwise, it returns the result of calling the `set` method on the
2169
- * `_store` object with the `key` and `value` arguments.
1895
+ * @param key - The key.
1896
+ * @param value - The value.
1897
+ * @returns True if successful.
2170
1898
  */
2171
1899
  _setValue(key, value) {
2172
1900
  if (key === null || key === undefined)
2173
1901
  return false;
2174
1902
  if (value === undefined)
2175
- return false;
1903
+ return false; // Or allow setting undefined?
2176
1904
  return this._store.set(key, value);
2177
1905
  }
2178
1906
  /**
2179
- * Time Complexity: O(1)
2180
- * Space Complexity: O(1)
2181
- *
2182
- * The _clearNodes function sets the root node to undefined and resets the size to 0.
1907
+ * (Protected) Clears all nodes from the tree.
1908
+ * @remarks Time O(1)
2183
1909
  */
2184
1910
  _clearNodes() {
2185
1911
  this._setRoot(undefined);
2186
1912
  this._size = 0;
2187
1913
  }
2188
1914
  /**
2189
- * Time Complexity: O(1)
2190
- * Space Complexity: O(1)
2191
- *
2192
- * The _clearValues function clears all values stored in the _store object.
1915
+ * (Protected) Clears all values from the external store.
1916
+ * @remarks Time O(N)
2193
1917
  */
2194
1918
  _clearValues() {
2195
1919
  this._store.clear();