data-structure-typed 2.0.4 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/CHANGELOG.md +3 -1
  2. package/COMMANDS.md +17 -0
  3. package/README.md +11 -11
  4. package/benchmark/report.html +13 -77
  5. package/benchmark/report.json +158 -190
  6. package/dist/cjs/data-structures/base/iterable-element-base.d.ts +186 -83
  7. package/dist/cjs/data-structures/base/iterable-element-base.js +149 -107
  8. package/dist/cjs/data-structures/base/iterable-element-base.js.map +1 -1
  9. package/dist/cjs/data-structures/base/iterable-entry-base.d.ts +95 -119
  10. package/dist/cjs/data-structures/base/iterable-entry-base.js +59 -116
  11. package/dist/cjs/data-structures/base/iterable-entry-base.js.map +1 -1
  12. package/dist/cjs/data-structures/base/linear-base.d.ts +250 -192
  13. package/dist/cjs/data-structures/base/linear-base.js +137 -274
  14. package/dist/cjs/data-structures/base/linear-base.js.map +1 -1
  15. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
  16. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js +171 -205
  17. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
  18. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
  19. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +135 -87
  20. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  21. package/dist/cjs/data-structures/binary-tree/avl-tree.d.ts +138 -149
  22. package/dist/cjs/data-structures/binary-tree/avl-tree.js +208 -195
  23. package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
  24. package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +476 -632
  25. package/dist/cjs/data-structures/binary-tree/binary-tree.js +608 -875
  26. package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  27. package/dist/cjs/data-structures/binary-tree/bst.d.ts +258 -306
  28. package/dist/cjs/data-structures/binary-tree/bst.js +505 -481
  29. package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
  30. package/dist/cjs/data-structures/binary-tree/red-black-tree.d.ts +107 -179
  31. package/dist/cjs/data-structures/binary-tree/red-black-tree.js +114 -209
  32. package/dist/cjs/data-structures/binary-tree/red-black-tree.js.map +1 -1
  33. package/dist/cjs/data-structures/binary-tree/tree-counter.d.ts +132 -154
  34. package/dist/cjs/data-structures/binary-tree/tree-counter.js +172 -203
  35. package/dist/cjs/data-structures/binary-tree/tree-counter.js.map +1 -1
  36. package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
  37. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +105 -85
  38. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  39. package/dist/cjs/data-structures/graph/abstract-graph.d.ts +238 -233
  40. package/dist/cjs/data-structures/graph/abstract-graph.js +267 -237
  41. package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
  42. package/dist/cjs/data-structures/graph/directed-graph.d.ts +108 -224
  43. package/dist/cjs/data-structures/graph/directed-graph.js +146 -233
  44. package/dist/cjs/data-structures/graph/directed-graph.js.map +1 -1
  45. package/dist/cjs/data-structures/graph/map-graph.d.ts +49 -55
  46. package/dist/cjs/data-structures/graph/map-graph.js +56 -59
  47. package/dist/cjs/data-structures/graph/map-graph.js.map +1 -1
  48. package/dist/cjs/data-structures/graph/undirected-graph.d.ts +103 -146
  49. package/dist/cjs/data-structures/graph/undirected-graph.js +129 -149
  50. package/dist/cjs/data-structures/graph/undirected-graph.js.map +1 -1
  51. package/dist/cjs/data-structures/hash/hash-map.d.ts +164 -338
  52. package/dist/cjs/data-structures/hash/hash-map.js +270 -457
  53. package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
  54. package/dist/cjs/data-structures/heap/heap.d.ts +214 -289
  55. package/dist/cjs/data-structures/heap/heap.js +340 -349
  56. package/dist/cjs/data-structures/heap/heap.js.map +1 -1
  57. package/dist/cjs/data-structures/heap/max-heap.d.ts +11 -47
  58. package/dist/cjs/data-structures/heap/max-heap.js +11 -66
  59. package/dist/cjs/data-structures/heap/max-heap.js.map +1 -1
  60. package/dist/cjs/data-structures/heap/min-heap.d.ts +12 -47
  61. package/dist/cjs/data-structures/heap/min-heap.js +11 -66
  62. package/dist/cjs/data-structures/heap/min-heap.js.map +1 -1
  63. package/dist/cjs/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
  64. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js +368 -494
  65. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  66. package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +261 -310
  67. package/dist/cjs/data-structures/linked-list/singly-linked-list.js +447 -466
  68. package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
  69. package/dist/cjs/data-structures/linked-list/skip-linked-list.d.ts +0 -107
  70. package/dist/cjs/data-structures/linked-list/skip-linked-list.js +0 -100
  71. package/dist/cjs/data-structures/linked-list/skip-linked-list.js.map +1 -1
  72. package/dist/cjs/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
  73. package/dist/cjs/data-structures/priority-queue/max-priority-queue.js +11 -78
  74. package/dist/cjs/data-structures/priority-queue/max-priority-queue.js.map +1 -1
  75. package/dist/cjs/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
  76. package/dist/cjs/data-structures/priority-queue/min-priority-queue.js +10 -79
  77. package/dist/cjs/data-structures/priority-queue/min-priority-queue.js.map +1 -1
  78. package/dist/cjs/data-structures/priority-queue/priority-queue.d.ts +2 -61
  79. package/dist/cjs/data-structures/priority-queue/priority-queue.js +8 -83
  80. package/dist/cjs/data-structures/priority-queue/priority-queue.js.map +1 -1
  81. package/dist/cjs/data-structures/queue/deque.d.ts +227 -254
  82. package/dist/cjs/data-structures/queue/deque.js +309 -348
  83. package/dist/cjs/data-structures/queue/deque.js.map +1 -1
  84. package/dist/cjs/data-structures/queue/queue.d.ts +180 -201
  85. package/dist/cjs/data-structures/queue/queue.js +265 -248
  86. package/dist/cjs/data-structures/queue/queue.js.map +1 -1
  87. package/dist/cjs/data-structures/stack/stack.d.ts +124 -102
  88. package/dist/cjs/data-structures/stack/stack.js +181 -125
  89. package/dist/cjs/data-structures/stack/stack.js.map +1 -1
  90. package/dist/cjs/data-structures/trie/trie.d.ts +164 -165
  91. package/dist/cjs/data-structures/trie/trie.js +189 -172
  92. package/dist/cjs/data-structures/trie/trie.js.map +1 -1
  93. package/dist/cjs/interfaces/binary-tree.d.ts +56 -6
  94. package/dist/cjs/interfaces/graph.d.ts +16 -0
  95. package/dist/cjs/types/data-structures/base/base.d.ts +1 -1
  96. package/dist/cjs/types/data-structures/graph/abstract-graph.d.ts +4 -0
  97. package/dist/cjs/types/utils/utils.d.ts +6 -6
  98. package/dist/cjs/utils/utils.d.ts +110 -49
  99. package/dist/cjs/utils/utils.js +148 -73
  100. package/dist/cjs/utils/utils.js.map +1 -1
  101. package/dist/esm/data-structures/base/iterable-element-base.d.ts +186 -83
  102. package/dist/esm/data-structures/base/iterable-element-base.js +155 -107
  103. package/dist/esm/data-structures/base/iterable-element-base.js.map +1 -1
  104. package/dist/esm/data-structures/base/iterable-entry-base.d.ts +95 -119
  105. package/dist/esm/data-structures/base/iterable-entry-base.js +59 -116
  106. package/dist/esm/data-structures/base/iterable-entry-base.js.map +1 -1
  107. package/dist/esm/data-structures/base/linear-base.d.ts +250 -192
  108. package/dist/esm/data-structures/base/linear-base.js +137 -274
  109. package/dist/esm/data-structures/base/linear-base.js.map +1 -1
  110. package/dist/esm/data-structures/binary-tree/avl-tree-counter.d.ts +126 -158
  111. package/dist/esm/data-structures/binary-tree/avl-tree-counter.js +171 -212
  112. package/dist/esm/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
  113. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.d.ts +100 -69
  114. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js +133 -94
  115. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  116. package/dist/esm/data-structures/binary-tree/avl-tree.d.ts +138 -149
  117. package/dist/esm/data-structures/binary-tree/avl-tree.js +206 -200
  118. package/dist/esm/data-structures/binary-tree/avl-tree.js.map +1 -1
  119. package/dist/esm/data-structures/binary-tree/binary-tree.d.ts +476 -632
  120. package/dist/esm/data-structures/binary-tree/binary-tree.js +613 -885
  121. package/dist/esm/data-structures/binary-tree/binary-tree.js.map +1 -1
  122. package/dist/esm/data-structures/binary-tree/bst.d.ts +258 -306
  123. package/dist/esm/data-structures/binary-tree/bst.js +507 -487
  124. package/dist/esm/data-structures/binary-tree/bst.js.map +1 -1
  125. package/dist/esm/data-structures/binary-tree/red-black-tree.d.ts +107 -179
  126. package/dist/esm/data-structures/binary-tree/red-black-tree.js +114 -215
  127. package/dist/esm/data-structures/binary-tree/red-black-tree.js.map +1 -1
  128. package/dist/esm/data-structures/binary-tree/tree-counter.d.ts +132 -154
  129. package/dist/esm/data-structures/binary-tree/tree-counter.js +175 -209
  130. package/dist/esm/data-structures/binary-tree/tree-counter.js.map +1 -1
  131. package/dist/esm/data-structures/binary-tree/tree-multi-map.d.ts +72 -69
  132. package/dist/esm/data-structures/binary-tree/tree-multi-map.js +103 -92
  133. package/dist/esm/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  134. package/dist/esm/data-structures/graph/abstract-graph.d.ts +238 -233
  135. package/dist/esm/data-structures/graph/abstract-graph.js +267 -237
  136. package/dist/esm/data-structures/graph/abstract-graph.js.map +1 -1
  137. package/dist/esm/data-structures/graph/directed-graph.d.ts +108 -224
  138. package/dist/esm/data-structures/graph/directed-graph.js +145 -233
  139. package/dist/esm/data-structures/graph/directed-graph.js.map +1 -1
  140. package/dist/esm/data-structures/graph/map-graph.d.ts +49 -55
  141. package/dist/esm/data-structures/graph/map-graph.js +56 -59
  142. package/dist/esm/data-structures/graph/map-graph.js.map +1 -1
  143. package/dist/esm/data-structures/graph/undirected-graph.d.ts +103 -146
  144. package/dist/esm/data-structures/graph/undirected-graph.js +128 -149
  145. package/dist/esm/data-structures/graph/undirected-graph.js.map +1 -1
  146. package/dist/esm/data-structures/hash/hash-map.d.ts +164 -338
  147. package/dist/esm/data-structures/hash/hash-map.js +270 -457
  148. package/dist/esm/data-structures/hash/hash-map.js.map +1 -1
  149. package/dist/esm/data-structures/heap/heap.d.ts +214 -289
  150. package/dist/esm/data-structures/heap/heap.js +329 -349
  151. package/dist/esm/data-structures/heap/heap.js.map +1 -1
  152. package/dist/esm/data-structures/heap/max-heap.d.ts +11 -47
  153. package/dist/esm/data-structures/heap/max-heap.js +11 -66
  154. package/dist/esm/data-structures/heap/max-heap.js.map +1 -1
  155. package/dist/esm/data-structures/heap/min-heap.d.ts +12 -47
  156. package/dist/esm/data-structures/heap/min-heap.js +11 -66
  157. package/dist/esm/data-structures/heap/min-heap.js.map +1 -1
  158. package/dist/esm/data-structures/linked-list/doubly-linked-list.d.ts +231 -347
  159. package/dist/esm/data-structures/linked-list/doubly-linked-list.js +368 -495
  160. package/dist/esm/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  161. package/dist/esm/data-structures/linked-list/singly-linked-list.d.ts +261 -310
  162. package/dist/esm/data-structures/linked-list/singly-linked-list.js +448 -467
  163. package/dist/esm/data-structures/linked-list/singly-linked-list.js.map +1 -1
  164. package/dist/esm/data-structures/linked-list/skip-linked-list.d.ts +0 -107
  165. package/dist/esm/data-structures/linked-list/skip-linked-list.js +0 -100
  166. package/dist/esm/data-structures/linked-list/skip-linked-list.js.map +1 -1
  167. package/dist/esm/data-structures/priority-queue/max-priority-queue.d.ts +12 -56
  168. package/dist/esm/data-structures/priority-queue/max-priority-queue.js +11 -78
  169. package/dist/esm/data-structures/priority-queue/max-priority-queue.js.map +1 -1
  170. package/dist/esm/data-structures/priority-queue/min-priority-queue.d.ts +11 -57
  171. package/dist/esm/data-structures/priority-queue/min-priority-queue.js +10 -79
  172. package/dist/esm/data-structures/priority-queue/min-priority-queue.js.map +1 -1
  173. package/dist/esm/data-structures/priority-queue/priority-queue.d.ts +2 -61
  174. package/dist/esm/data-structures/priority-queue/priority-queue.js +8 -83
  175. package/dist/esm/data-structures/priority-queue/priority-queue.js.map +1 -1
  176. package/dist/esm/data-structures/queue/deque.d.ts +227 -254
  177. package/dist/esm/data-structures/queue/deque.js +313 -348
  178. package/dist/esm/data-structures/queue/deque.js.map +1 -1
  179. package/dist/esm/data-structures/queue/queue.d.ts +180 -201
  180. package/dist/esm/data-structures/queue/queue.js +263 -248
  181. package/dist/esm/data-structures/queue/queue.js.map +1 -1
  182. package/dist/esm/data-structures/stack/stack.d.ts +124 -102
  183. package/dist/esm/data-structures/stack/stack.js +181 -125
  184. package/dist/esm/data-structures/stack/stack.js.map +1 -1
  185. package/dist/esm/data-structures/trie/trie.d.ts +164 -165
  186. package/dist/esm/data-structures/trie/trie.js +193 -172
  187. package/dist/esm/data-structures/trie/trie.js.map +1 -1
  188. package/dist/esm/interfaces/binary-tree.d.ts +56 -6
  189. package/dist/esm/interfaces/graph.d.ts +16 -0
  190. package/dist/esm/types/data-structures/base/base.d.ts +1 -1
  191. package/dist/esm/types/data-structures/graph/abstract-graph.d.ts +4 -0
  192. package/dist/esm/types/utils/utils.d.ts +6 -6
  193. package/dist/esm/utils/utils.d.ts +110 -49
  194. package/dist/esm/utils/utils.js +139 -68
  195. package/dist/esm/utils/utils.js.map +1 -1
  196. package/dist/umd/data-structure-typed.js +4737 -6525
  197. package/dist/umd/data-structure-typed.min.js +8 -6
  198. package/dist/umd/data-structure-typed.min.js.map +1 -1
  199. package/package.json +3 -4
  200. package/src/data-structures/base/iterable-element-base.ts +238 -115
  201. package/src/data-structures/base/iterable-entry-base.ts +96 -120
  202. package/src/data-structures/base/linear-base.ts +271 -277
  203. package/src/data-structures/binary-tree/avl-tree-counter.ts +198 -216
  204. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +192 -101
  205. package/src/data-structures/binary-tree/avl-tree.ts +239 -206
  206. package/src/data-structures/binary-tree/binary-tree.ts +677 -901
  207. package/src/data-structures/binary-tree/bst.ts +568 -570
  208. package/src/data-structures/binary-tree/red-black-tree.ts +161 -222
  209. package/src/data-structures/binary-tree/tree-counter.ts +199 -218
  210. package/src/data-structures/binary-tree/tree-multi-map.ts +131 -97
  211. package/src/data-structures/graph/abstract-graph.ts +339 -264
  212. package/src/data-structures/graph/directed-graph.ts +146 -236
  213. package/src/data-structures/graph/map-graph.ts +63 -60
  214. package/src/data-structures/graph/undirected-graph.ts +129 -152
  215. package/src/data-structures/hash/hash-map.ts +274 -496
  216. package/src/data-structures/heap/heap.ts +389 -402
  217. package/src/data-structures/heap/max-heap.ts +12 -76
  218. package/src/data-structures/heap/min-heap.ts +13 -76
  219. package/src/data-structures/linked-list/doubly-linked-list.ts +426 -530
  220. package/src/data-structures/linked-list/singly-linked-list.ts +495 -517
  221. package/src/data-structures/linked-list/skip-linked-list.ts +1 -108
  222. package/src/data-structures/priority-queue/max-priority-queue.ts +12 -87
  223. package/src/data-structures/priority-queue/min-priority-queue.ts +11 -88
  224. package/src/data-structures/priority-queue/priority-queue.ts +3 -92
  225. package/src/data-structures/queue/deque.ts +381 -357
  226. package/src/data-structures/queue/queue.ts +310 -264
  227. package/src/data-structures/stack/stack.ts +217 -131
  228. package/src/data-structures/trie/trie.ts +240 -175
  229. package/src/interfaces/binary-tree.ts +240 -6
  230. package/src/interfaces/graph.ts +37 -0
  231. package/src/types/data-structures/base/base.ts +5 -5
  232. package/src/types/data-structures/graph/abstract-graph.ts +5 -0
  233. package/src/types/utils/utils.ts +9 -5
  234. package/src/utils/utils.ts +152 -86
  235. package/test/integration/index.html +1 -1
  236. package/test/performance/benchmark-runner.ts +528 -0
  237. package/test/performance/reportor.mjs +43 -43
  238. package/test/performance/runner-config.json +39 -0
  239. package/test/performance/single-suite-runner.ts +69 -0
  240. package/test/unit/data-structures/binary-tree/avl-tree-counter.test.ts +3 -3
  241. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +5 -5
  242. package/test/unit/data-structures/binary-tree/avl-tree.test.ts +4 -4
  243. package/test/unit/data-structures/binary-tree/binary-tree.test.ts +350 -90
  244. package/test/unit/data-structures/binary-tree/bst.test.ts +84 -5
  245. package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +2 -2
  246. package/test/unit/data-structures/binary-tree/tree-counter.test.ts +25 -24
  247. package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +3 -3
  248. package/test/unit/data-structures/graph/abstract-graph.test.ts +0 -4
  249. package/test/unit/data-structures/graph/directed-graph.test.ts +1 -1
  250. package/test/unit/data-structures/heap/heap.test.ts +14 -21
  251. package/test/unit/data-structures/heap/max-heap.test.ts +5 -9
  252. package/test/unit/data-structures/heap/min-heap.test.ts +1 -4
  253. package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +14 -14
  254. package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +0 -7
  255. package/test/unit/data-structures/priority-queue/max-priority-queue.test.ts +8 -11
  256. package/test/unit/data-structures/priority-queue/min-priority-queue.test.ts +1 -4
  257. package/test/unit/data-structures/priority-queue/priority-queue.test.ts +1 -4
  258. package/test/unit/data-structures/queue/queue.test.ts +4 -5
  259. package/test/unit/utils/utils.test.ts +0 -1
  260. package/test/performance/data-structures/binary-tree/avl-tree.test.mjs +0 -71
  261. package/test/performance/data-structures/binary-tree/red-black-tree.test.mjs +0 -81
@@ -1,16 +1,250 @@
1
1
  import { BinaryTreeNode } from '../data-structures';
2
- import type { BinaryTreeDeleteResult, BinaryTreeOptions, BTNRep, NodePredicate } from '../types';
2
+ import type {
3
+ BinaryTreeDeleteResult,
4
+ BinaryTreeOptions,
5
+ BTNRep,
6
+ DFSOrderPattern,
7
+ EntryCallback,
8
+ IterationType,
9
+ NodeCallback,
10
+ NodePredicate,
11
+ OptNodeOrNull,
12
+ ReduceEntryCallback,
13
+ ToEntryFn
14
+ } from '../types';
3
15
 
4
- export interface IBinaryTree<K = any, V = any, R = object, MK = any, MV = any, MR = object> {
5
- createNode(key: K, value?: BinaryTreeNode['value']): BinaryTreeNode;
16
+ /**
17
+ * Public, implementation-agnostic binary tree API.
18
+ * K = key, V = value, R = raw/record used with toEntryFn (optional).
19
+ * Transforming methods like `map` use method-level generics MK/MV/MR.
20
+ */
21
+ export interface IBinaryTree<K = any, V = any, R extends object = object> {
22
+ // ---- state ----
23
+ readonly size: number;
24
+ readonly root: BinaryTreeNode<K, V> | null | undefined;
25
+ readonly isMapMode: boolean;
26
+ // NOTE: iterationType is mutable on the class; remove readonly here to match
27
+ iterationType: IterationType;
28
+ // Extra public state/getters implemented by BinaryTree (useful to callers)
29
+ readonly NIL: BinaryTreeNode<K, V>;
30
+ readonly store: Map<K, V | undefined>;
31
+ readonly toEntryFn?: ToEntryFn<K, V, R>;
32
+ readonly isDuplicate: boolean;
6
33
 
7
- createTree(options?: Partial<BinaryTreeOptions<K, V, R>>): IBinaryTree<K, V, R, MK, MV, MR>;
34
+ // ---- construction / mutation ----
35
+ _createNode(key: K, value?: BinaryTreeNode<K, V>['value']): BinaryTreeNode<K, V>;
36
+
37
+ createTree(options?: Partial<BinaryTreeOptions<K, V, R>>): IBinaryTree<K, V, R>;
8
38
 
9
39
  add(keyOrNodeOrEntryOrRawElement: BTNRep<K, V, BinaryTreeNode<K, V>>, value?: V, count?: number): boolean;
10
40
 
11
- addMany(nodes: Iterable<BTNRep<K, V, BinaryTreeNode<K, V>>>, values?: Iterable<V | undefined>): boolean[];
41
+ // Accept raw R as well (when toEntryFn is configured)
42
+ addMany(
43
+ keysNodesEntriesOrRaws: Iterable<
44
+ K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R
45
+ >,
46
+ values?: Iterable<V | undefined>
47
+ ): boolean[];
12
48
 
49
+ // Accept BTNRep, predicate, or raw R for deletion
13
50
  delete(
14
- predicate: R | BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V>>
51
+ keyNodeEntryRawOrPredicate: R | BTNRep<K, V, BinaryTreeNode<K, V>> | NodePredicate<BinaryTreeNode<K, V> | null>
15
52
  ): BinaryTreeDeleteResult<BinaryTreeNode<K, V>>[];
53
+
54
+ clear(): void;
55
+
56
+ isEmpty(): boolean;
57
+
58
+ // ---- query / read ----
59
+
60
+ // Widen `get` to support entry and optional traversal context (matches impl)
61
+ get(
62
+ keyNodeEntryOrPredicate: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
63
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
64
+ iterationType?: IterationType
65
+ ): V | undefined;
66
+
67
+ // `has` also supports node/entry/predicate and optional traversal context
68
+ has(
69
+ keyNodeEntryOrPredicate?:
70
+ | K
71
+ | BinaryTreeNode<K, V>
72
+ | [K | null | undefined, V | undefined]
73
+ | null
74
+ | undefined
75
+ | NodePredicate<BinaryTreeNode<K, V> | null>,
76
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
77
+ iterationType?: IterationType
78
+ ): boolean;
79
+
80
+ hasValue(value: V): boolean;
81
+
82
+ find(predicate: EntryCallback<K, V | undefined, boolean>, thisArg?: unknown): [K, V | undefined] | undefined;
83
+
84
+ // ---- iteration ----
85
+ [Symbol.iterator](): IterableIterator<[K, V | undefined]>;
86
+
87
+ entries(): IterableIterator<[K, V | undefined]>;
88
+
89
+ keys(): IterableIterator<K>;
90
+
91
+ values(): IterableIterator<V | undefined>;
92
+
93
+ forEach(callbackfn: EntryCallback<K, V | undefined, void>, thisArg?: unknown): void;
94
+
95
+ every(callbackfn: EntryCallback<K, V | undefined, boolean>, thisArg?: unknown): boolean;
96
+
97
+ some(callbackfn: EntryCallback<K, V | undefined, boolean>, thisArg?: unknown): boolean;
98
+
99
+ reduce<U>(reducer: ReduceEntryCallback<K, V | undefined, U>, initialValue: U): U;
100
+
101
+ // ---- node access / extremes ----
102
+ getNode(
103
+ keyNodeEntryOrPredicate:
104
+ | K
105
+ | BinaryTreeNode<K, V>
106
+ | [K | null | undefined, V | undefined]
107
+ | null
108
+ | undefined
109
+ | NodePredicate<BinaryTreeNode<K, V> | null>,
110
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
111
+ iterationType?: IterationType
112
+ ): OptNodeOrNull<BinaryTreeNode<K, V>>;
113
+
114
+ getLeftMost<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
115
+ callback?: C,
116
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
117
+ iterationType?: IterationType
118
+ ): ReturnType<C>;
119
+
120
+ getRightMost<C extends NodeCallback<BinaryTreeNode<K, V> | undefined>>(
121
+ callback?: C,
122
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
123
+ iterationType?: IterationType
124
+ ): ReturnType<C>;
125
+
126
+ // ---- traversal ----
127
+ dfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
128
+ callback?: C,
129
+ pattern?: DFSOrderPattern,
130
+ onlyOne?: boolean,
131
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
132
+ iterationType?: IterationType
133
+ ): ReturnType<C>[];
134
+
135
+ dfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
136
+ callback?: C,
137
+ pattern?: DFSOrderPattern,
138
+ onlyOne?: boolean,
139
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
140
+ iterationType?: IterationType,
141
+ includeNull?: boolean
142
+ ): ReturnType<C>[];
143
+
144
+ bfs<C extends NodeCallback<BinaryTreeNode<K, V>>>(
145
+ callback?: C,
146
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
147
+ iterationType?: IterationType,
148
+ includeNull?: false
149
+ ): ReturnType<C>[];
150
+
151
+ bfs<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
152
+ callback?: C,
153
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
154
+ iterationType?: IterationType,
155
+ includeNull?: true
156
+ ): ReturnType<C>[];
157
+
158
+ morris<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
159
+ callback?: C,
160
+ pattern?: DFSOrderPattern,
161
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
162
+ ): ReturnType<C>[];
163
+
164
+ leaves<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
165
+ callback?: C,
166
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
167
+ iterationType?: IterationType
168
+ ): ReturnType<C>[];
169
+
170
+ listLevels<C extends NodeCallback<BinaryTreeNode<K, V>>>(
171
+ callback?: C,
172
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
173
+ iterationType?: IterationType,
174
+ includeNull?: false
175
+ ): ReturnType<C>[][];
176
+
177
+ listLevels<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
178
+ callback?: C,
179
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
180
+ iterationType?: IterationType,
181
+ includeNull?: true
182
+ ): ReturnType<C>[][];
183
+
184
+ getPathToRoot<C extends NodeCallback<OptNodeOrNull<BinaryTreeNode<K, V>>>>(
185
+ beginNode: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
186
+ callback?: C,
187
+ isReverse?: boolean
188
+ ): ReturnType<C>[];
189
+
190
+ // ---- metrics & validation ----
191
+ getDepth(
192
+ dist: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
193
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
194
+ ): number;
195
+
196
+ getHeight(
197
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
198
+ iterationType?: IterationType
199
+ ): number;
200
+
201
+ getMinHeight(
202
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
203
+ iterationType?: IterationType
204
+ ): number;
205
+
206
+ isPerfectlyBalanced(
207
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
208
+ ): boolean;
209
+
210
+ isBST(
211
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
212
+ iterationType?: IterationType
213
+ ): boolean;
214
+
215
+ // ---- search helpers ----
216
+ search<C extends NodeCallback<BinaryTreeNode<K, V> | null>>(
217
+ keyNodeEntryOrPredicate:
218
+ | K
219
+ | BinaryTreeNode<K, V>
220
+ | [K | null | undefined, V | undefined]
221
+ | null
222
+ | undefined
223
+ | NodePredicate<BinaryTreeNode<K, V> | null>,
224
+ onlyOne?: boolean,
225
+ callback?: C,
226
+ startNode?: K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
227
+ iterationType?: IterationType
228
+ ): ReturnType<C>[];
229
+
230
+ // ---- immutable transforms ----
231
+ clone(): this;
232
+
233
+ filter(predicate: EntryCallback<K, V | undefined, boolean>, thisArg?: unknown): this;
234
+
235
+ map<MK = K, MV = V, MR extends object = object>(
236
+ callback: EntryCallback<K, V | undefined, [MK, MV]>,
237
+ options?: Partial<BinaryTreeOptions<MK, MV, MR>>,
238
+ thisArg?: unknown
239
+ ): IBinaryTree<MK, MV, MR>;
240
+
241
+ // ---- bulk / interop ----
242
+ merge(anotherTree: IBinaryTree<K, V, R>): void;
243
+
244
+ refill(
245
+ keysNodesEntriesOrRaws: Iterable<
246
+ K | BinaryTreeNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R
247
+ >,
248
+ values?: Iterable<V | undefined>
249
+ ): void;
16
250
  }
@@ -1,7 +1,44 @@
1
1
  import { VertexKey } from '../types';
2
2
 
3
3
  export interface IGraph<V, E, VO, EO> {
4
+ // Vertex factories
4
5
  createVertex(key: VertexKey, value?: V): VO;
5
6
 
7
+ // Edge factories
6
8
  createEdge(srcOrV1: VertexKey, destOrV2: VertexKey, weight?: number, value?: E): EO;
9
+
10
+ // Core vertex ops
11
+ getVertex(vertexKey: VertexKey): VO | undefined;
12
+
13
+ hasVertex(vertexOrKey: VO | VertexKey): boolean;
14
+
15
+ addVertex(vertex: VO): boolean;
16
+
17
+ addVertex(key: VertexKey, value?: V): boolean;
18
+
19
+ deleteVertex(vertexOrKey: VO | VertexKey): boolean;
20
+
21
+ // Core edge ops
22
+ deleteEdge(edge: EO): EO | undefined;
23
+
24
+ getEdge(srcOrKey: VO | VertexKey, destOrKey: VO | VertexKey): EO | undefined;
25
+
26
+ degreeOf(vertexOrKey: VO | VertexKey): number;
27
+
28
+ edgeSet(): EO[];
29
+
30
+ edgesOf(vertexOrKey: VO | VertexKey): EO[];
31
+
32
+ getNeighbors(vertexOrKey: VO | VertexKey): VO[];
33
+
34
+ getEndsOfEdge(edge: EO): [VO, VO] | undefined;
35
+
36
+ // Container-like ops
37
+ isEmpty(): boolean;
38
+
39
+ clear(): void;
40
+
41
+ clone(): this;
42
+
43
+ filter(...args: any[]): this;
7
44
  }
@@ -11,12 +11,12 @@ export type ReduceEntryCallback<K, V, R> = (
11
11
  original: IterableEntryBase<K, V>
12
12
  ) => R;
13
13
 
14
- export type ReduceElementCallback<E, R, RT = E> = (
15
- accumulator: RT,
16
- element: E,
14
+ export type ReduceElementCallback<E, R, U = E> = (
15
+ accumulator: U,
16
+ value: E,
17
17
  index: number,
18
- original: IterableElementBase<E, R>
19
- ) => RT;
18
+ self: IterableElementBase<E, R>
19
+ ) => U;
20
20
 
21
21
  export type ReduceLinearCallback<E, RT = E> = (
22
22
  accumulator: RT,
@@ -11,3 +11,8 @@ export type DijkstraResult<V> =
11
11
  minPath: V[];
12
12
  }
13
13
  | undefined;
14
+
15
+ export type GraphOptions<V = any> = {
16
+ vertexValueInitializer?: (key: VertexKey) => V;
17
+ defaultEdgeWeight?: number;
18
+ };
@@ -1,14 +1,11 @@
1
- export type ToThunkFn<R = any> = () => R;
2
- export type Thunk<R = any> = ToThunkFn<R> & { __THUNK__?: symbol };
3
- export type TrlFn<A extends any[] = any[], R = any> = (...args: A) => R;
4
- export type TrlAsyncFn = (...args: any[]) => any;
5
-
6
1
  export type SpecifyOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
7
2
 
8
3
  export type Any = string | number | bigint | boolean | symbol | undefined | object;
9
4
 
10
5
  export type Arithmetic = number | bigint;
11
6
 
7
+ export type ElemOf<T> = T extends (infer U)[] ? U : never;
8
+
12
9
  export type ComparablePrimitive = number | bigint | string | boolean;
13
10
 
14
11
  export interface BaseComparableObject {
@@ -27,3 +24,10 @@ export interface StringComparableObject extends BaseComparableObject {
27
24
  export type ComparableObject = ValueComparableObject | StringComparableObject;
28
25
 
29
26
  export type Comparable = ComparablePrimitive | Date | ComparableObject;
27
+
28
+ export type TrampolineThunk<T> = {
29
+ readonly isThunk: true;
30
+ readonly fn: () => Trampoline<T>;
31
+ };
32
+
33
+ export type Trampoline<T> = T | TrampolineThunk<T>;
@@ -5,7 +5,7 @@
5
5
  * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
6
6
  * @license MIT License
7
7
  */
8
- import type { Comparable, ComparablePrimitive, Thunk, ToThunkFn, TrlAsyncFn, TrlFn } from '../types';
8
+ import type { Comparable, ComparablePrimitive, Trampoline, TrampolineThunk } from '../types';
9
9
 
10
10
  /**
11
11
  * The function generates a random UUID (Universally Unique Identifier) in TypeScript.
@@ -47,91 +47,6 @@ export const arrayRemove = function <T>(array: T[], predicate: (item: T, index:
47
47
  return result;
48
48
  };
49
49
 
50
- export const THUNK_SYMBOL = Symbol('thunk');
51
-
52
- /**
53
- * The function `isThunk` checks if a given value is a function with a specific symbol property.
54
- * @param {any} fnOrValue - The `fnOrValue` parameter in the `isThunk` function can be either a
55
- * function or a value that you want to check if it is a thunk. Thunks are functions that are wrapped
56
- * around a value or computation for lazy evaluation. The function checks if the `fnOrValue` is
57
- * @returns The function `isThunk` is checking if the input `fnOrValue` is a function and if it has a
58
- * property `__THUNK__` equal to `THUNK_SYMBOL`. The return value will be `true` if both conditions are
59
- * met, otherwise it will be `false`.
60
- */
61
- export const isThunk = (fnOrValue: any) => {
62
- return typeof fnOrValue === 'function' && fnOrValue.__THUNK__ === THUNK_SYMBOL;
63
- };
64
-
65
- /**
66
- * The `toThunk` function in TypeScript converts a function into a thunk by wrapping it in a closure.
67
- * @param {ToThunkFn} fn - `fn` is a function that will be converted into a thunk.
68
- * @returns A thunk function is being returned. Thunk functions are functions that delay the evaluation
69
- * of an expression or operation until it is explicitly called or invoked. In this case, the `toThunk`
70
- * function takes a function `fn` as an argument and returns a thunk function that, when called, will
71
- * execute the `fn` function provided as an argument.
72
- */
73
- export const toThunk = (fn: ToThunkFn): Thunk => {
74
- const thunk = () => fn();
75
- thunk.__THUNK__ = THUNK_SYMBOL;
76
- return thunk;
77
- };
78
-
79
- /**
80
- * The `trampoline` function in TypeScript enables tail call optimization by using thunks to avoid
81
- * stack overflow.
82
- * @param {TrlFn} fn - The `fn` parameter in the `trampoline` function is a function that takes any
83
- * number of arguments and returns a value.
84
- * @returns The `trampoline` function returns an object with two properties:
85
- * 1. A function that executes the provided function `fn` and continues to execute any thunks returned
86
- * by `fn` until a non-thunk value is returned.
87
- * 2. A `cont` property that is a function which creates a thunk for the provided function `fn`.
88
- */
89
- export const trampoline = (fn: TrlFn) => {
90
- const cont = (...args: [...Parameters<TrlFn>]): ReturnType<TrlFn> => toThunk(() => fn(...args));
91
-
92
- return Object.assign(
93
- (...args: [...Parameters<TrlFn>]) => {
94
- let result = fn(...args);
95
-
96
- while (isThunk(result) && typeof result === 'function') {
97
- result = result();
98
- }
99
-
100
- return result;
101
- },
102
- { cont }
103
- );
104
- };
105
-
106
- /**
107
- * The `trampolineAsync` function in TypeScript allows for asynchronous trampolining of a given
108
- * function.
109
- * @param {TrlAsyncFn} fn - The `fn` parameter in the `trampolineAsync` function is expected to be a
110
- * function that returns a Promise. This function will be called recursively until a non-thunk value is
111
- * returned.
112
- * @returns The `trampolineAsync` function returns an object with two properties:
113
- * 1. An async function that executes the provided `TrlAsyncFn` function and continues to execute any
114
- * thunks returned by the function until a non-thunk value is returned.
115
- * 2. A `cont` property that is a function which wraps the provided `TrlAsyncFn` function in a thunk
116
- * and returns it.
117
- */
118
- export const trampolineAsync = (fn: TrlAsyncFn) => {
119
- const cont = (...args: [...Parameters<TrlAsyncFn>]): ReturnType<TrlAsyncFn> => toThunk(() => fn(...args));
120
-
121
- return Object.assign(
122
- async (...args: [...Parameters<TrlAsyncFn>]) => {
123
- let result = await fn(...args);
124
-
125
- while (isThunk(result) && typeof result === 'function') {
126
- result = await result();
127
- }
128
-
129
- return result;
130
- },
131
- { cont }
132
- );
133
- };
134
-
135
50
  /**
136
51
  * The function `getMSB` returns the most significant bit of a given number.
137
52
  * @param {number} value - The `value` parameter is a number for which we want to find the position of
@@ -282,3 +197,154 @@ export function isComparable(value: unknown, isForceObjectComparable = false): v
282
197
  if (comparableValue === null || comparableValue === undefined) return false;
283
198
  return isPrimitiveComparable(comparableValue);
284
199
  }
200
+
201
+ /**
202
+ * Creates a trampoline thunk object.
203
+ *
204
+ * A "thunk" is a deferred computation — instead of performing a recursive call immediately,
205
+ * it wraps the next step of the computation in a function. This allows recursive processes
206
+ * to be executed iteratively, preventing stack overflows.
207
+ *
208
+ * @template T - The type of the final computation result.
209
+ * @param computation - A function that, when executed, returns the next trampoline step.
210
+ * @returns A TrampolineThunk object containing the deferred computation.
211
+ */
212
+ export const makeTrampolineThunk = <T>(computation: () => Trampoline<T>): TrampolineThunk<T> => ({
213
+ isThunk: true, // Marker indicating this is a thunk
214
+ fn: computation // The deferred computation function
215
+ });
216
+
217
+ /**
218
+ * Type guard to check whether a given value is a TrampolineThunk.
219
+ *
220
+ * This function is used to distinguish between a final computation result (value)
221
+ * and a deferred computation (thunk).
222
+ *
223
+ * @template T - The type of the value being checked.
224
+ * @param value - The value to test.
225
+ * @returns True if the value is a valid TrampolineThunk, false otherwise.
226
+ */
227
+ export const isTrampolineThunk = <T>(value: Trampoline<T>): value is TrampolineThunk<T> =>
228
+ typeof value === 'object' && // Must be an object
229
+ value !== null && // Must not be null
230
+ 'isThunk' in value && // Must have the 'isThunk' property
231
+ value.isThunk; // The flag must be true
232
+
233
+ /**
234
+ * Executes a trampoline computation until a final (non-thunk) result is obtained.
235
+ *
236
+ * The trampoline function repeatedly invokes the deferred computations (thunks)
237
+ * in an iterative loop. This avoids deep recursive calls and prevents stack overflow,
238
+ * which is particularly useful for implementing recursion in a stack-safe manner.
239
+ *
240
+ * @template T - The type of the final result.
241
+ * @param initial - The initial Trampoline value or thunk to start execution from.
242
+ * @returns The final result of the computation (a non-thunk value).
243
+ */
244
+ export function trampoline<T>(initial: Trampoline<T>): T {
245
+ let current = initial; // Start with the initial trampoline value
246
+ while (isTrampolineThunk(current)) {
247
+ // Keep unwrapping while we have thunks
248
+ current = current.fn(); // Execute the deferred function to get the next step
249
+ }
250
+ return current; // Once no thunks remain, return the final result
251
+ }
252
+
253
+ /**
254
+ * Wraps a recursive function inside a trampoline executor.
255
+ *
256
+ * This function transforms a potentially recursive function (that returns a Trampoline<Result>)
257
+ * into a *stack-safe* function that executes iteratively using the `trampoline` runner.
258
+ *
259
+ * In other words, it allows you to write functions that look recursive,
260
+ * but actually run in constant stack space.
261
+ *
262
+ * @template Args - The tuple type representing the argument list of the original function.
263
+ * @template Result - The final return type after all trampoline steps are resolved.
264
+ *
265
+ * @param fn - A function that performs a single step of computation
266
+ * and returns a Trampoline (either a final value or a deferred thunk).
267
+ *
268
+ * @returns A new function with the same arguments, but which automatically
269
+ * runs the trampoline process and returns the *final result* instead
270
+ * of a Trampoline.
271
+ *
272
+ * @example
273
+ * // Example: Computing factorial in a stack-safe way
274
+ * const factorial = makeTrampoline(function fact(n: number, acc: number = 1): Trampoline<number> {
275
+ * return n === 0
276
+ * ? acc
277
+ * : makeTrampolineThunk(() => fact(n - 1, acc * n));
278
+ * });
279
+ *
280
+ * console.log(factorial(100000)); // Works without stack overflow
281
+ */
282
+ export function makeTrampoline<Args extends any[], Result>(
283
+ fn: (...args: Args) => Trampoline<Result> // A function that returns a trampoline step
284
+ ): (...args: Args) => Result {
285
+ // Return a wrapped function that automatically runs the trampoline execution loop
286
+ return (...args: Args) => trampoline(fn(...args));
287
+ }
288
+
289
+ /**
290
+ * Executes an asynchronous trampoline computation until a final (non-thunk) result is obtained.
291
+ *
292
+ * This function repeatedly invokes asynchronous deferred computations (thunks)
293
+ * in an iterative loop. Each thunk may return either a Trampoline<T> or a Promise<Trampoline<T>>.
294
+ *
295
+ * It ensures that asynchronous recursive functions can run without growing the call stack,
296
+ * making it suitable for stack-safe async recursion.
297
+ *
298
+ * @template T - The type of the final result.
299
+ * @param initial - The initial Trampoline or Promise of Trampoline to start execution from.
300
+ * @returns A Promise that resolves to the final result (a non-thunk value).
301
+ */
302
+ export async function asyncTrampoline<T>(initial: Trampoline<T> | Promise<Trampoline<T>>): Promise<T> {
303
+ let current = await initial; // Wait for the initial step to resolve if it's a Promise
304
+
305
+ // Keep executing thunks until we reach a non-thunk (final) value
306
+ while (isTrampolineThunk(current)) {
307
+ current = await current.fn(); // Execute the thunk function (may be async)
308
+ }
309
+
310
+ // Once the final value is reached, return it
311
+ return current;
312
+ }
313
+
314
+ /**
315
+ * Wraps an asynchronous recursive function inside an async trampoline executor.
316
+ *
317
+ * This helper transforms a recursive async function that returns a Trampoline<Result>
318
+ * (or Promise<Trampoline<Result>>) into a *stack-safe* async function that executes
319
+ * iteratively via the `asyncTrampoline` runner.
320
+ *
321
+ * @template Args - The tuple type representing the argument list of the original function.
322
+ * @template Result - The final return type after all async trampoline steps are resolved.
323
+ *
324
+ * @param fn - An async or sync function that performs a single step of computation
325
+ * and returns a Trampoline (either a final value or a deferred thunk).
326
+ *
327
+ * @returns An async function with the same arguments, but which automatically
328
+ * runs the trampoline process and resolves to the *final result*.
329
+ *
330
+ * @example
331
+ * // Example: Async factorial using trampoline
332
+ * const asyncFactorial = makeAsyncTrampoline(async function fact(
333
+ * n: number,
334
+ * acc: number = 1
335
+ * ): Promise<Trampoline<number>> {
336
+ * return n === 0
337
+ * ? acc
338
+ * : makeTrampolineThunk(() => fact(n - 1, acc * n));
339
+ * });
340
+ *
341
+ * asyncFactorial(100000).then(console.log); // Works without stack overflow
342
+ */
343
+ export function makeAsyncTrampoline<Args extends any[], Result>(
344
+ fn: (...args: Args) => Trampoline<Result> | Promise<Trampoline<Result>>
345
+ ): (...args: Args) => Promise<Result> {
346
+ // Return a wrapped async function that runs through the async trampoline loop
347
+ return async (...args: Args): Promise<Result> => {
348
+ return asyncTrampoline(fn(...args));
349
+ };
350
+ }
@@ -86,7 +86,7 @@
86
86
  tree.print(undefined, { isShowUndefined: true });
87
87
 
88
88
  const node3 = tree.getNode(3);
89
- if (node3) node3.right = tree.createNode(1);
89
+ if (node3) node3.right = tree._createNode(1);
90
90
  console.log(tree.isPerfectlyBalanced(), `tree.isPerfectlyBalanced()`);
91
91
  tree.print();
92
92