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
@@ -88,8 +88,8 @@ describe('BinaryTreeNode', () => {
88
88
  });
89
89
  });
90
90
 
91
- describe('BinaryTree addMany', () => {
92
- it('should addMany', () => {
91
+ describe('BinaryTree.addMany', () => {
92
+ it('addMany(): adds entries via toEntryFn and values override', () => {
93
93
  const binTree = new BinaryTree<number, number, { id: number; name: number }>([], {
94
94
  toEntryFn: ({ id, name }) => [id, name]
95
95
  });
@@ -108,7 +108,7 @@ describe('BinaryTree addMany', () => {
108
108
  expect(binTree.get(binTree.getNode(1))).toBe(1);
109
109
  });
110
110
 
111
- it('should addMany undefined and null', () => {
111
+ it('addMany(): handles undefined and null keys', () => {
112
112
  const binaryTree = new BinaryTree<number, string>();
113
113
  const addManyWithUndefined = binaryTree.addMany([1, undefined, 3]);
114
114
  expect(addManyWithUndefined).toEqual([true, false, true]);
@@ -143,16 +143,16 @@ describe('BinaryTree', () => {
143
143
  binTree.clear();
144
144
  });
145
145
 
146
- it('should add a node', () => {
146
+ it('add(): inserts a node and updates size', () => {
147
147
  const node = binTree.add(1);
148
148
  expect(node).not.toBeNull();
149
149
  expect(binTree.size).toBe(1);
150
150
  });
151
151
 
152
- it('should delete nodes', () => {
152
+ it('delete(): leaf/one-child/two-children/missing; updates size and minHeight', () => {
153
153
  expect(binTree.getHeight(binTree.root, 'ITERATIVE')).toBe(-1);
154
154
  expect(binTree.getMinHeight()).toBe(-1);
155
- const node1 = binTree.createNode(1);
155
+ const node1 = binTree._createNode(1);
156
156
  binTree.add(node1);
157
157
  expect(binTree.size).toBe(1);
158
158
 
@@ -182,7 +182,7 @@ describe('BinaryTree', () => {
182
182
  }
183
183
  });
184
184
 
185
- it('should add and find nodes', () => {
185
+ it('add()/has()/getNode(): find nodes by key and predicate', () => {
186
186
  binTree.add([1, 1]);
187
187
  binTree.add(undefined);
188
188
  binTree.add([2, 2]);
@@ -198,7 +198,7 @@ describe('BinaryTree', () => {
198
198
  expect(binTree.has(node => node.key?.toString() === '3')).toBe(true);
199
199
  });
200
200
 
201
- it('should the clone method work fine', () => {
201
+ it('clone(): structural copy; subtree dfs with includeNull permutations', () => {
202
202
  expect(binTree.isEmpty()).toBe(true);
203
203
  binTree.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]);
204
204
  expect(binTree.root?.key).toBe(4);
@@ -252,7 +252,7 @@ describe('BinaryTree', () => {
252
252
  // expect(cloned.isEmpty()).toBe(true);
253
253
  });
254
254
 
255
- it('should be a balance binTree after malicious manipulation', () => {
255
+ it('isPerfectlyBalanced(): toggles with pointer tampering and skewed levels', () => {
256
256
  binTree.add(3);
257
257
  binTree.add(12);
258
258
  binTree.addMany(getRandomIntArray(100, 1, 100));
@@ -261,7 +261,7 @@ describe('BinaryTree', () => {
261
261
  expect(binTree.isPerfectlyBalanced()).toBe(true);
262
262
  const node3 = binTree.getNode(3);
263
263
 
264
- if (node3) node3.right = binTree.createNode(1);
264
+ if (node3) node3.right = binTree._createNode(1);
265
265
  expect(binTree.isPerfectlyBalanced()).toBe(false);
266
266
 
267
267
  binTree.clear();
@@ -269,7 +269,7 @@ describe('BinaryTree', () => {
269
269
  expect(binTree.isPerfectlyBalanced()).toBe(false);
270
270
  });
271
271
 
272
- it('should getDepth return correct depth', () => {
272
+ it('getDepth(): returns correct depth with/without root parameter', () => {
273
273
  binTree.add(1);
274
274
  expect(binTree.getDepth(1)).toBe(0);
275
275
  binTree.add(2);
@@ -282,7 +282,7 @@ describe('BinaryTree', () => {
282
282
  expect(binTree.getDepth(4, 2)).toBe(1);
283
283
  });
284
284
 
285
- it('should traverse in-order', () => {
285
+ it('dfs(IN): returns in-order; height respects iterationType', () => {
286
286
  binTree.add(null);
287
287
  binTree.delete(1);
288
288
  expect(binTree.getHeight()).toBe(-1);
@@ -304,7 +304,7 @@ describe('BinaryTree', () => {
304
304
  expect(inOrder).toEqual([1, 2, 3, 4, 5, 6, 7]);
305
305
  });
306
306
 
307
- it('should isSubtreeBST', () => {
307
+ it('isBST(): returns true for subtree (iterative & recursive)', () => {
308
308
  binTree.addMany([
309
309
  new BinaryTreeNode(4, 4),
310
310
  new BinaryTreeNode(2, 2),
@@ -320,7 +320,7 @@ describe('BinaryTree', () => {
320
320
  expect(binTree.isBST(binTree.getNode(4), 'ITERATIVE')).toBe(true);
321
321
  });
322
322
 
323
- it('should isSubtreeBST', () => {
323
+ it('isBST(): returns true for subtree (iterative & recursive)', () => {
324
324
  expect(binTree.toVisual()).toBe('');
325
325
  binTree.addMany([4, 2, 6, 1, 3, 5, 7, 4]);
326
326
  expect(binTree.toVisual()).toBe(
@@ -358,9 +358,9 @@ describe('BinaryTree', () => {
358
358
  expect(binTree.getNodes(binTree.getNode(2), false, binTree.root)).toEqual([binTree.getNode(2)]);
359
359
  });
360
360
 
361
- describe('should isValidKey', () => {
361
+ describe('isValidKey', () => {
362
362
  describe('primitive types', () => {
363
- it('numbers should be a key', () => {
363
+ it('isValidKey(): numbers are valid keys', () => {
364
364
  expect(binTree.isValidKey(42)).toBe(true);
365
365
  expect(binTree.isValidKey(0)).toBe(true);
366
366
  expect(binTree.isValidKey(-1)).toBe(true);
@@ -368,40 +368,40 @@ describe('BinaryTree', () => {
368
368
  expect(binTree.isValidKey(-Infinity)).toBe(true);
369
369
  });
370
370
 
371
- // it('NaN should not be a key', () => {
371
+ // it('isValidKey(): NaN is not a valid key', () => {
372
372
  // expect(binTree.isValidKey(NaN)).toBe(false);
373
373
  // });
374
374
 
375
- it('strings should be a key', () => {
375
+ it('isValidKey(): strings are valid keys', () => {
376
376
  expect(binTree.isValidKey('hello')).toBe(true);
377
377
  expect(binTree.isValidKey('')).toBe(true);
378
378
  expect(binTree.isValidKey('123')).toBe(true);
379
379
  });
380
380
 
381
- it('BigInt should be a key', () => {
381
+ it('isValidKey(): BigInt is a valid key', () => {
382
382
  expect(binTree.isValidKey(BigInt(42))).toBe(true);
383
383
  expect(binTree.isValidKey(BigInt(0))).toBe(true);
384
384
  expect(binTree.isValidKey(BigInt(-1))).toBe(true);
385
385
  });
386
386
 
387
- it('boolean should not be a key', () => {
387
+ it('isValidKey(): booleans are valid keys', () => {
388
388
  expect(binTree.isValidKey(true)).toBe(true);
389
389
  expect(binTree.isValidKey(false)).toBe(true);
390
390
  });
391
391
 
392
- it('null and undefined should not be a key', () => {
392
+ it('isValidKey(): null is valid, undefined is not', () => {
393
393
  expect(binTree.isValidKey(null)).toBe(true);
394
394
  expect(binTree.isValidKey(undefined)).toBe(false);
395
395
  });
396
396
 
397
- it('symbols should not be a key', () => {
397
+ it('isValidKey(): symbols are not valid keys', () => {
398
398
  expect(binTree.isValidKey(Symbol('test'))).toBe(false);
399
399
  expect(binTree.isValidKey(Symbol.for('test'))).toBe(false);
400
400
  });
401
401
  });
402
402
 
403
403
  describe('Date objects', () => {
404
- it('valid Date objects should be a key', () => {
404
+ it('isValidKey(): valid Date objects are valid keys', () => {
405
405
  expect(binTree.isValidKey(new Date())).toBe(true);
406
406
  expect(binTree.isValidKey(new Date('2024-01-01'))).toBe(true);
407
407
  });
@@ -412,7 +412,7 @@ describe('BinaryTree', () => {
412
412
  });
413
413
 
414
414
  describe('arrays', () => {
415
- it('arrays should be a key as they convert to string', () => {
415
+ it('isValidKey(): arrays are valid (stringified) keys', () => {
416
416
  expect(binTree.isValidKey([])).toBe(true);
417
417
  expect(binTree.isValidKey([1, 2, 3])).toBe(true);
418
418
  expect(binTree.isValidKey(['a', 'b', 'c'])).toBe(true);
@@ -420,26 +420,26 @@ describe('BinaryTree', () => {
420
420
  });
421
421
 
422
422
  describe('plain objects', () => {
423
- it('plain objects should not be a key', () => {
423
+ it('isValidKey(): plain objects are not valid keys', () => {
424
424
  expect(binTree.isValidKey({})).toBe(false);
425
425
  expect(binTree.isValidKey({ a: 1 })).toBe(false);
426
426
  });
427
427
  });
428
428
 
429
429
  describe('custom objects', () => {
430
- it('objects with numeric valueOf should be a key', () => {
430
+ it('isValidKey(): objects with numeric valueOf are valid keys', () => {
431
431
  expect(binTree.isValidKey({ valueOf: () => 42 })).toBe(true);
432
432
  });
433
433
 
434
- it('objects with string valueOf should be a key', () => {
434
+ it('isValidKey(): objects with string valueOf are valid keys', () => {
435
435
  expect(binTree.isValidKey({ valueOf: () => 'test' })).toBe(true);
436
436
  });
437
437
 
438
- it('objects with boolean valueOf should not be a key', () => {
438
+ it('isValidKey(): objects with boolean valueOf are treated as valid', () => {
439
439
  expect(binTree.isValidKey({ valueOf: () => true })).toBe(true);
440
440
  });
441
441
 
442
- it('objects with nested valueOf/toString should be a key', () => {
442
+ it('isValidKey(): nested valueOf/toString results in valid key', () => {
443
443
  expect(
444
444
  binTree.isValidKey({
445
445
  valueOf: () => ({ toString: () => '42' })
@@ -449,7 +449,7 @@ describe('BinaryTree', () => {
449
449
  });
450
450
 
451
451
  describe('deeply nested objects', () => {
452
- it('objects with deeply nested valueOf should be a key', () => {
452
+ it('isValidKey(): deeply nested valueOf is valid', () => {
453
453
  const deeplyNested = {
454
454
  valueOf: () => ({
455
455
  valueOf: () => 42
@@ -458,7 +458,7 @@ describe('BinaryTree', () => {
458
458
  expect(binTree.isValidKey(deeplyNested)).toBe(true);
459
459
  });
460
460
 
461
- it('objects with very deeply nested conversion should be a key', () => {
461
+ it('isValidKey(): very deep conversion to string is valid', () => {
462
462
  const veryDeeplyNested = {
463
463
  valueOf: () => ({
464
464
  valueOf: () => ({
@@ -469,7 +469,7 @@ describe('BinaryTree', () => {
469
469
  expect(binTree.isValidKey(veryDeeplyNested)).toBe(true);
470
470
  });
471
471
 
472
- it('objects with circular references should not be a key', () => {
472
+ it('isValidKey(): circular reference is invalid', () => {
473
473
  const circular: any = {
474
474
  valueOf: () => circular
475
475
  };
@@ -478,7 +478,7 @@ describe('BinaryTree', () => {
478
478
  });
479
479
 
480
480
  describe('edge cases', () => {
481
- it('objects returning non-primitive values should be handled correctly', () => {
481
+ it('isValidKey(): non-primitive ultimate value is invalid', () => {
482
482
  const complexObject = {
483
483
  valueOf: () => ({
484
484
  toString: () => ({
@@ -489,7 +489,7 @@ describe('BinaryTree', () => {
489
489
  expect(binTree.isValidKey(complexObject)).toBe(false);
490
490
  });
491
491
 
492
- it('objects returning primitive values should be handled correctly', () => {
492
+ it('isValidKey(): ultimately primitive conversion is valid', () => {
493
493
  const complexObject = {
494
494
  valueOf: () => ({
495
495
  valueOf: () => ({
@@ -508,7 +508,7 @@ describe('BinaryTree', () => {
508
508
  });
509
509
 
510
510
  describe('type checking', () => {
511
- it('should work with type guard in array methods', () => {
511
+ it('isValidKey(): works as a type guard in array methods', () => {
512
512
  const values: unknown[] = [42, 'test', true, null, undefined, new Date()];
513
513
  const comparableValues = values.filter(item => binTree.isValidKey(item));
514
514
  expect(comparableValues.length).toBe(5);
@@ -516,7 +516,7 @@ describe('BinaryTree', () => {
516
516
  });
517
517
  });
518
518
 
519
- it('should isLeaf', () => {
519
+ it('isLeaf(): detects leaves; null is treated as leaf', () => {
520
520
  expect(binTree.getLeftMost()).toBe(undefined);
521
521
  expect(binTree.getRightMost()).toBe(undefined);
522
522
  binTree.addMany([4, 2, 6, 1, 3, 5, 7, 4]);
@@ -528,7 +528,7 @@ describe('BinaryTree', () => {
528
528
  expect(binTree.isLeaf(null)).toBe(true);
529
529
  });
530
530
 
531
- it('should binTree traverse', () => {
531
+ it('dfs/bfs on mixed-null level-order tree: expected orders (includeNull on/off)', () => {
532
532
  expect(binTree.dfs()).toEqual([]);
533
533
  expect([...binTree.values()]).toEqual([]);
534
534
  binTree.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]);
@@ -617,7 +617,7 @@ describe('BinaryTree', () => {
617
617
  );
618
618
  });
619
619
 
620
- it('should sub binTree traverse', () => {
620
+ it('dfs on subtree (startNode): expected orders (includeNull on/off)', () => {
621
621
  binTree.addMany([4, 2, 6, null, 1, 3, null, 5, null, 7]);
622
622
  expect(binTree.dfs(node => node.key, 'PRE', false, binTree.getNode(6), 'ITERATIVE')).toEqual([6, 3, 7]);
623
623
  expect(
@@ -668,7 +668,7 @@ describe('BinaryTree', () => {
668
668
  ).toEqual([7, 3, null, 6]);
669
669
  });
670
670
 
671
- it('should clear the binTree', () => {
671
+ it('clear(): empties tree and resets root', () => {
672
672
  binTree.add(1);
673
673
  binTree.add(2);
674
674
 
@@ -680,7 +680,7 @@ describe('BinaryTree', () => {
680
680
  expect(binTree.root).toBeUndefined();
681
681
  });
682
682
 
683
- it('should duplicated nodes just replace the node exists', function () {
683
+ it('duplicate keys: replace existing value; bfs includeNull snapshot', function () {
684
684
  binTree.clear();
685
685
  expect(binTree.bfs()).toEqual([]);
686
686
  binTree.addMany([-10, -10, -10, 9, 9, 20, null, null, 15, 7, 8, null, 2, null, 6, null, null, 8, 8, 8]);
@@ -739,7 +739,7 @@ describe('BinaryTree', () => {
739
739
  // expect(bTree.keyValueNodeEntryRawToNodeAndValue({ obj: { id: 1 } })).toEqual([undefined, undefined]);
740
740
  // });
741
741
 
742
- it('should replace value', () => {
742
+ it('add(): duplicate key updates value (Map vs non-Map behavior)', () => {
743
743
  const binTree = new BinaryTree<number, string>([4, 5, [1, '1'], 2, 3], { isMapMode: false });
744
744
  expect(binTree.get(1)).toBe('1');
745
745
  expect(binTree.getNode(1)?.value).toBe('1');
@@ -759,8 +759,8 @@ describe('BinaryTree', () => {
759
759
  });
760
760
  });
761
761
 
762
- describe('BinaryTree ensureNode', () => {
763
- it('should ensureNode with toEntryFn', () => {
762
+ describe('BinaryTree.ensureNode', () => {
763
+ it('ensureNode(): with toEntryFn returns existing node; handles null/undefined/Symbol', () => {
764
764
  const binTree = new BinaryTree<
765
765
  number,
766
766
  string,
@@ -779,7 +779,7 @@ describe('BinaryTree ensureNode', () => {
779
779
  });
780
780
  });
781
781
 
782
- describe('BinaryTree Morris Traversal', () => {
782
+ describe('BinaryTree - Morris traversal', () => {
783
783
  // Create a binary binTree
784
784
  const binTree = new BinaryTree<number>();
785
785
  binTree.add(1);
@@ -787,7 +787,7 @@ describe('BinaryTree Morris Traversal', () => {
787
787
  binTree.add(3);
788
788
  binTree.add(4);
789
789
  binTree.add(5);
790
- it('should perform in-order Morris traversal correctly as dfs traversal', () => {
790
+ it('morris(IN): equals dfs(IN) (iterative/recursive)', () => {
791
791
  // Perform in-order Morris traversal
792
792
  const result = binTree.morris(node => node.key, 'IN');
793
793
 
@@ -799,7 +799,7 @@ describe('BinaryTree Morris Traversal', () => {
799
799
  expect(binTree.dfs(node => node.key, 'IN', false, binTree.root, 'RECURSIVE')).toEqual(expected);
800
800
  });
801
801
 
802
- it('should perform pre-order Morris traversal correctly as dfs traversal', () => {
802
+ it('morris(PRE): equals dfs(PRE)', () => {
803
803
  // Perform pre-order Morris traversal
804
804
  const result = binTree.morris(node => node.key, 'PRE');
805
805
 
@@ -810,7 +810,7 @@ describe('BinaryTree Morris Traversal', () => {
810
810
  expect(binTree.dfs(node => node.key, 'PRE')).toEqual(expected);
811
811
  });
812
812
 
813
- it('should perform post-order Morris traversal correctly as dfs traversal', () => {
813
+ it('morris(POST): equals dfs(POST)', () => {
814
814
  // Perform post-order Morris traversal
815
815
  const result = binTree.morris(node => node.key, 'POST');
816
816
 
@@ -821,7 +821,7 @@ describe('BinaryTree Morris Traversal', () => {
821
821
  expect(binTree.dfs(node => node.key, 'POST')).toEqual(expected);
822
822
  });
823
823
 
824
- it('after morris traversals should the structure of the binTree be correct', () => {
824
+ it('morris(): structure intact afterwards', () => {
825
825
  const node1 = binTree.getNode(1);
826
826
  const node2 = binTree.getNode(2);
827
827
  const node3 = binTree.getNode(3);
@@ -830,8 +830,8 @@ describe('BinaryTree Morris Traversal', () => {
830
830
  });
831
831
  });
832
832
 
833
- describe('BinaryTree toEntryFn', () => {
834
- it('should toEntryFn throw', () => {
833
+ describe('BinaryTree.toEntryFn', () => {
834
+ it('toEntryFn: non-function throws toEntryFn must be a function type', () => {
835
835
  expect(() => {
836
836
  new BinaryTree<number, number, { obj: { id: number } }>([], {
837
837
  toEntryFn: `ele => [ele.obj.id, ele.obj.id]` as unknown as (rawElement: {
@@ -841,7 +841,7 @@ describe('BinaryTree toEntryFn', () => {
841
841
  }).toThrow('toEntryFn must be a function type');
842
842
  });
843
843
 
844
- it('should toEntryFn with add', () => {
844
+ it('toEntryFn + addMany(): IN order equals dfs/Morris', () => {
845
845
  const binTree = new BinaryTree<number, number, { obj: { id: number } }>([], {
846
846
  toEntryFn: ele => [ele.obj.id, ele.obj.id]
847
847
  });
@@ -860,7 +860,7 @@ describe('BinaryTree toEntryFn', () => {
860
860
  expect(binTree.dfs(node => node.key, 'IN', false, binTree.root, 'RECURSIVE')).toEqual(expected);
861
861
  });
862
862
 
863
- it('should toEntryFn with initial', () => {
863
+ it('constructor toEntryFn (initial data): IN order equals dfs/Morris', () => {
864
864
  const binTree = new BinaryTree<number, number, { obj: { id: number } }>(
865
865
  [{ obj: { id: 1 } }, { obj: { id: 2 } }, { obj: { id: 3 } }, { obj: { id: 4 } }, { obj: { id: 5 } }],
866
866
  {
@@ -875,7 +875,7 @@ describe('BinaryTree toEntryFn', () => {
875
875
  expect(binTree.dfs(node => node.key, 'IN', false, binTree.root, 'RECURSIVE')).toEqual(expected);
876
876
  });
877
877
 
878
- it('should no toEntryFn', () => {
878
+ it('without toEntryFn (valueOf-based): dfs/Morris behaviors', () => {
879
879
  const data = [
880
880
  { obj: { id: 4 }, valueOf: () => 4 },
881
881
  { obj: { id: 2 }, valueOf: () => 2 },
@@ -891,8 +891,8 @@ describe('BinaryTree toEntryFn', () => {
891
891
  });
892
892
  });
893
893
 
894
- describe('BinaryTree traversals', () => {
895
- it('traversals', () => {
894
+ describe('BinaryTree - traversal suites', () => {
895
+ it('bfs/dfs/listLevels: permutations return expected sequences', () => {
896
896
  const binTree = new BinaryTree<number>();
897
897
 
898
898
  const arr = [35, 20, 40, 15, 29, null, 50, null, 16, 28, 30, 45, 55];
@@ -997,13 +997,13 @@ describe('BinaryTree', () => {
997
997
  binTree.clear();
998
998
  });
999
999
 
1000
- it('should create an empty BinaryTree', () => {
1000
+ it('constructor: creates an empty BinaryTree', () => {
1001
1001
  expect(binTree.size).toBe(0);
1002
1002
  expect(binTree.isEmpty()).toBe(true);
1003
1003
  expect(binTree.root).toBe(undefined);
1004
1004
  });
1005
1005
 
1006
- it('should add nodes to the binTree', () => {
1006
+ it('add(): inserts nodes and sets root', () => {
1007
1007
  binTree.add([5, 'A']);
1008
1008
  binTree.add([3, 'B']);
1009
1009
  binTree.add([7, 'C']);
@@ -1025,7 +1025,7 @@ describe('BinaryTree', () => {
1025
1025
  expect(binTree.root).toBe(undefined);
1026
1026
  });
1027
1027
 
1028
- it('should get nodes by key', () => {
1028
+ it('getNode()/get(): resolve nodes and values by key', () => {
1029
1029
  binTree.add([5, 'A']);
1030
1030
  binTree.add([3, 'B']);
1031
1031
  binTree.add([7, 'C']);
@@ -1039,7 +1039,7 @@ describe('BinaryTree', () => {
1039
1039
  expect(binTree.get(nodeB)).toBe('B');
1040
1040
  });
1041
1041
 
1042
- it('should return undefined when getting a non-existent node', () => {
1042
+ it('getNode(): returns undefined for missing key', () => {
1043
1043
  binTree.add([5, 'A']);
1044
1044
 
1045
1045
  const node = binTree.getNode(3);
@@ -1056,7 +1056,7 @@ describe('BinaryTree', () => {
1056
1056
  expect(binTree.getDepth(3)).toBe(1);
1057
1057
  });
1058
1058
 
1059
- it('should get the height of the binTree', () => {
1059
+ it('getHeight()/getMinHeight(): expected heights', () => {
1060
1060
  expect(binTree.getMinHeight()).toBe(-1);
1061
1061
  binTree.add([5, 'A']);
1062
1062
  binTree.add(3, 'B');
@@ -1067,7 +1067,7 @@ describe('BinaryTree', () => {
1067
1067
  expect(binTree.getMinHeight(undefined, 'RECURSIVE')).toBe(1);
1068
1068
  });
1069
1069
 
1070
- it('should check if the binTree is a binary search binTree', () => {
1070
+ it('isBST(): returns true for valid tree', () => {
1071
1071
  binTree.add([5, 'A']);
1072
1072
  binTree.add([3, 'B']);
1073
1073
  binTree.add([7, 'C']);
@@ -1075,7 +1075,7 @@ describe('BinaryTree', () => {
1075
1075
  expect(binTree.isBST()).toBe(true);
1076
1076
  });
1077
1077
 
1078
- it('should perform a depth-first traversal', () => {
1078
+ it('dfs(default IN): returns expected order', () => {
1079
1079
  binTree.add([5, 'A']);
1080
1080
  binTree.add([3, 'B']);
1081
1081
  binTree.add([7, 'C']);
@@ -1085,7 +1085,7 @@ describe('BinaryTree', () => {
1085
1085
  // Add assertions for the result of depth-first traversal
1086
1086
  });
1087
1087
 
1088
- it('should perform a breadth-first traversal', () => {
1088
+ it('bfs(): returns expected level-order', () => {
1089
1089
  binTree.add([5, 'A']);
1090
1090
  binTree.add([3, 'B']);
1091
1091
  binTree.add([7, 'C']);
@@ -1095,7 +1095,7 @@ describe('BinaryTree', () => {
1095
1095
  // Add assertions for the result of breadth-first traversal
1096
1096
  });
1097
1097
 
1098
- it('should list levels of the binTree', () => {
1098
+ it('listLevels(): returns keys by level', () => {
1099
1099
  binTree.add([5, 'A']);
1100
1100
  binTree.add([3, 'B']);
1101
1101
  binTree.add([7, 'C']);
@@ -1105,7 +1105,7 @@ describe('BinaryTree', () => {
1105
1105
  // Add assertions for the levels of the binTree
1106
1106
  });
1107
1107
 
1108
- it('should delete nodes from the binTree', () => {
1108
+ it('delete(): removes nodes and updates size', () => {
1109
1109
  binTree.add([5, 'A']);
1110
1110
  binTree.add([3, 'B']);
1111
1111
  binTree.add([7, 'C']);
@@ -1116,7 +1116,7 @@ describe('BinaryTree', () => {
1116
1116
  expect(binTree.getNode(3)).toBe(undefined);
1117
1117
  });
1118
1118
 
1119
- it('should getPathToRoot', () => {
1119
+ it('getPathToRoot(): path from key to root; [] for missing', () => {
1120
1120
  binTree.add([5, 'A']);
1121
1121
  binTree.add([3, 'B']);
1122
1122
  binTree.add([7, 'C']);
@@ -1125,7 +1125,7 @@ describe('BinaryTree', () => {
1125
1125
  expect(binTree.getPathToRoot(1)).toEqual([]);
1126
1126
  });
1127
1127
 
1128
- it('should check if the binTree is perfectly balanced', () => {
1128
+ it('isPerfectlyBalanced(): true for balanced tree', () => {
1129
1129
  binTree.add([5, 'A']);
1130
1130
  binTree.add([3, 'B']);
1131
1131
  binTree.add([7, 'C']);
@@ -1133,7 +1133,7 @@ describe('BinaryTree', () => {
1133
1133
  expect(binTree.isPerfectlyBalanced()).toBe(true);
1134
1134
  });
1135
1135
 
1136
- it('should get nodes by a custom callback', () => {
1136
+ it('getNodes(predicate): returns matches (iterative & recursive)', () => {
1137
1137
  binTree.add([5, 'E']);
1138
1138
  binTree.add([4, 'D']);
1139
1139
  binTree.add([3, 'C']);
@@ -1163,7 +1163,7 @@ describe('BinaryTree', () => {
1163
1163
  expect(nodesItr).toEqual(nodesRec);
1164
1164
  });
1165
1165
 
1166
- it('should perform Morris traversal', () => {
1166
+ it('morris(IN): equals dfs(IN); clear() => []', () => {
1167
1167
  binTree.add([5, 'A']);
1168
1168
  binTree.add([3, 'B']);
1169
1169
  binTree.add([7, 'C']);
@@ -1188,7 +1188,7 @@ describe('BinaryTree', () => {
1188
1188
  expect(binTree.morris()).toEqual([]);
1189
1189
  });
1190
1190
 
1191
- it('should perform delete all', () => {
1191
+ it('delete(): removes all nodes; height == -1', () => {
1192
1192
  binTree.add([5, 'A']);
1193
1193
  binTree.add([3, 'B']);
1194
1194
  binTree.add([7, 'C']);
@@ -1201,7 +1201,7 @@ describe('BinaryTree', () => {
1201
1201
  });
1202
1202
  });
1203
1203
 
1204
- describe('BinaryTree not map mode', () => {
1204
+ describe('BinaryTree (non-Map mode)', () => {
1205
1205
  let binTree: BinaryTree<number, string>;
1206
1206
 
1207
1207
  beforeEach(() => {
@@ -1215,7 +1215,7 @@ describe('BinaryTree not map mode', () => {
1215
1215
  binTree.clear();
1216
1216
  });
1217
1217
 
1218
- it('should add and find nodes', () => {
1218
+ it('add()/has()/getNode(): find nodes by key and predicate', () => {
1219
1219
  binTree.add([1, '1']);
1220
1220
  binTree.add(undefined);
1221
1221
  binTree.add([2, '2']);
@@ -1231,7 +1231,7 @@ describe('BinaryTree not map mode', () => {
1231
1231
  expect(binTree.has(node => node.value?.toString() === '3')).toBe(true);
1232
1232
  });
1233
1233
 
1234
- it('should isSubtreeBST', () => {
1234
+ it('isBST(): returns true for subtree (iterative & recursive)', () => {
1235
1235
  binTree.addMany([
1236
1236
  new BinaryTreeNode(4),
1237
1237
  new BinaryTreeNode(2),
@@ -1247,7 +1247,7 @@ describe('BinaryTree not map mode', () => {
1247
1247
  expect(binTree.isBST(binTree.getNode(4), 'ITERATIVE')).toBe(true);
1248
1248
  });
1249
1249
 
1250
- it('should get nodes by key', () => {
1250
+ it('getNode()/get(): resolve nodes and values by key', () => {
1251
1251
  binTree.add([5, 'A']);
1252
1252
  binTree.add([3, 'B']);
1253
1253
  binTree.add([7, 'C']);
@@ -1261,7 +1261,7 @@ describe('BinaryTree not map mode', () => {
1261
1261
  expect(binTree.get(nodeB)).toBe('B');
1262
1262
  });
1263
1263
 
1264
- it('should get nodes by a custom callback', () => {
1264
+ it('getNodes(predicate): returns matches (iterative & recursive)', () => {
1265
1265
  binTree.add([5, 'E']);
1266
1266
  binTree.add([4, 'D']);
1267
1267
  binTree.add([3, 'C']);
@@ -1292,7 +1292,7 @@ describe('BinaryTree not map mode', () => {
1292
1292
  });
1293
1293
  });
1294
1294
 
1295
- describe('BinaryTree iterative methods test', () => {
1295
+ describe('BinaryTree (map mode) - higher-order & iteration', () => {
1296
1296
  let binaryTree: BinaryTree<number, string>;
1297
1297
  beforeEach(() => {
1298
1298
  binaryTree = new BinaryTree();
@@ -1301,12 +1301,12 @@ describe('BinaryTree iterative methods test', () => {
1301
1301
  binaryTree.add([3, 'c']);
1302
1302
  });
1303
1303
 
1304
- it('The node obtained by get Node should match the node type', () => {
1304
+ it('getNode(): returns BinaryTreeNode instance', () => {
1305
1305
  const node3 = binaryTree.getNode(3);
1306
1306
  expect(node3).toBeInstanceOf(BinaryTreeNode);
1307
1307
  });
1308
1308
 
1309
- it('forEach should iterate over all elements', () => {
1309
+ it('forEach(): iterates all entries', () => {
1310
1310
  const mockCallback = jest.fn();
1311
1311
  binaryTree.forEach((key, value) => {
1312
1312
  mockCallback(key, value);
@@ -1318,7 +1318,7 @@ describe('BinaryTree iterative methods test', () => {
1318
1318
  expect(mockCallback.mock.calls[2]).toEqual([3, 'c']);
1319
1319
  });
1320
1320
 
1321
- it('filter should return a new binTree with filtered elements', () => {
1321
+ it('filter(): returns new tree with filtered entries', () => {
1322
1322
  const filteredTree = binaryTree.filter(key => key > 1);
1323
1323
  expect(filteredTree.size).toBe(2);
1324
1324
  expect([...filteredTree]).toEqual([
@@ -1327,7 +1327,7 @@ describe('BinaryTree iterative methods test', () => {
1327
1327
  ]);
1328
1328
  });
1329
1329
 
1330
- it('map should return a new binTree with modified elements', () => {
1330
+ it('map(): returns new tree with transformed keys/values', () => {
1331
1331
  const mappedTree = binaryTree.map((key, value) => [(key * 2).toString(), value]);
1332
1332
  expect(mappedTree.size).toBe(3);
1333
1333
  expect([...mappedTree]).toEqual([
@@ -1337,12 +1337,12 @@ describe('BinaryTree iterative methods test', () => {
1337
1337
  ]);
1338
1338
  });
1339
1339
 
1340
- it('reduce should accumulate values', () => {
1340
+ it('reduce(): aggregates over entries', () => {
1341
1341
  const sum = binaryTree.reduce((acc, currentValue, currentKey) => acc + currentKey, 0);
1342
1342
  expect(sum).toBe(6);
1343
1343
  });
1344
1344
 
1345
- it('[Symbol.iterator] should provide an iterator', () => {
1345
+ it('[Symbol.iterator]: yields entries', () => {
1346
1346
  const entries = [];
1347
1347
  for (const entry of binaryTree) {
1348
1348
  entries.push(entry);
@@ -1356,31 +1356,31 @@ describe('BinaryTree iterative methods test', () => {
1356
1356
  ]);
1357
1357
  });
1358
1358
 
1359
- it('should clone work well', () => {
1359
+ it('clone(): preserves structure and allows get() by node', () => {
1360
1360
  const cloned = binaryTree.clone();
1361
1361
  expect(cloned.root?.left?.key).toBe(2);
1362
1362
  expect(cloned.root?.right?.value).toBe(undefined);
1363
1363
  expect(cloned.get(cloned.root?.right)).toBe('c');
1364
1364
  });
1365
1365
 
1366
- it('should keys', () => {
1366
+ it('keys(): iterator yields keys in-order', () => {
1367
1367
  const keys = binaryTree.keys();
1368
1368
  expect([...keys]).toEqual([2, 1, 3]);
1369
1369
  });
1370
1370
 
1371
- it('should values', () => {
1371
+ it('values(): iterator yields values in-order', () => {
1372
1372
  const values = binaryTree.values();
1373
1373
  expect([...values]).toEqual(['b', 'a', 'c']);
1374
1374
  });
1375
1375
 
1376
- it('should leaves', () => {
1376
+ it('leaves(): returns leaf keys; clear() => []', () => {
1377
1377
  const leaves = binaryTree.leaves();
1378
1378
  expect(leaves).toEqual([2, 3]);
1379
1379
  binaryTree.clear();
1380
1380
  expect(binaryTree.leaves()).toEqual([]);
1381
1381
  });
1382
1382
 
1383
- it('should iterative method return undefined when the node is null', () => {
1383
+ it('bfs(includeNull=true, no callback): yields undefined placeholders', () => {
1384
1384
  const binTree = new BinaryTree();
1385
1385
  binTree.addMany([-10, -10, -10, 9, 9, 20, null, null, 15, 7, 8, null, 2, null, 6, null, null, 8, 8, 8]);
1386
1386
  const bfsResult = binTree.bfs(undefined, undefined, undefined, true);
@@ -1403,7 +1403,7 @@ describe('BinaryTree iterative methods test', () => {
1403
1403
  });
1404
1404
  });
1405
1405
 
1406
- describe('BinaryTree not map mode iterative methods test', () => {
1406
+ describe('BinaryTree (non-Map mode) - higher-order & iteration', () => {
1407
1407
  let binaryTree: BinaryTree<number, string>;
1408
1408
  beforeEach(() => {
1409
1409
  binaryTree = new BinaryTree<number, string>([], { isMapMode: false });
@@ -1412,14 +1412,274 @@ describe('BinaryTree not map mode iterative methods test', () => {
1412
1412
  binaryTree.add([3, 'c']);
1413
1413
  });
1414
1414
 
1415
- it('should clone work well', () => {
1415
+ it('clone(): preserves structure and allows get() by node', () => {
1416
1416
  const cloned = binaryTree.clone();
1417
1417
  expect(cloned.root?.left?.key).toBe(2);
1418
1418
  expect(cloned.get(cloned.root?.right)).toBe('c');
1419
1419
  });
1420
1420
  });
1421
1421
 
1422
- describe('classic use', () => {
1422
+ describe('Coverage boosters - merge/print/iterator/startNode/addMany-mismatch/delete-miss', () => {
1423
+ it('merge: merge another tree (Map mode)', () => {
1424
+ const a = new BinaryTree<number, string>(
1425
+ [
1426
+ [2, 'b'],
1427
+ [1, 'a']
1428
+ ],
1429
+ { isMapMode: true }
1430
+ );
1431
+ const b = new BinaryTree<number, string>(
1432
+ [
1433
+ [3, 'c'],
1434
+ [4, 'd']
1435
+ ],
1436
+ { isMapMode: true }
1437
+ );
1438
+ a.merge(b);
1439
+ expect(a.size).toBe(4);
1440
+ expect(a.get(3)).toBe('c');
1441
+ expect(a.get(4)).toBe('d');
1442
+ });
1443
+
1444
+ it('print: cover console.log branch (invokes toVisual)', () => {
1445
+ const t = new BinaryTree<number>([4, 2, 6, 1, 3]);
1446
+ const spy = jest.spyOn(console, 'log').mockImplementation(() => void 0);
1447
+ t.print({ isShowNull: true } as any, t.root);
1448
+ expect(spy).toHaveBeenCalledTimes(1);
1449
+ const out: string = (spy.mock.calls[0]?.[0] as string) ?? '';
1450
+ expect(out.includes('N for null')).toBe(true);
1451
+ spy.mockRestore();
1452
+ });
1453
+
1454
+ it('for...of: trigger [Symbol.iterator] path (IterableEntryBase)', () => {
1455
+ const t = new BinaryTree<number, string>(
1456
+ [
1457
+ [1, 'x'],
1458
+ [2, 'y'],
1459
+ [3, 'z']
1460
+ ],
1461
+ { isMapMode: true } as any
1462
+ );
1463
+ const arr = Array.from(t); // like Array<[K, V | undefined]>
1464
+ const keys = arr.map(e => e?.[0]);
1465
+ const vals = arr.map(e => e?.[1]);
1466
+ expect(new Set(keys)).toEqual(new Set([1, 2, 3]));
1467
+ expect(new Set(vals)).toEqual(new Set(['x', 'y', 'z']));
1468
+ });
1469
+
1470
+ it('startNode restricted to subtree: hits only within subtree', () => {
1471
+ const t = new BinaryTree<number, string>([
1472
+ [4, 'd'],
1473
+ [2, 'b'],
1474
+ [6, 'f'],
1475
+ [1, 'a'],
1476
+ [3, 'c']
1477
+ ]);
1478
+ const sub = t.getNode(2)!; // subtree {2,1,3}
1479
+ // search 6 in subtree rooted at 2 -> miss
1480
+ expect(t.search(6, true, n => (n ? n.key : undefined), sub)).toEqual([]);
1481
+ // search 3 -> hit
1482
+ expect(t.search(3, true, n => (n ? n.key : undefined), sub)).toEqual([3]);
1483
+ });
1484
+
1485
+ it('addMany: edge cases when values iterator shorter/longer than keys', () => {
1486
+ const t = new BinaryTree<number, number>([], { isMapMode: true } as any);
1487
+ // values has only 1 item, keys has 3
1488
+ t.addMany([1, 2, 3], [10]);
1489
+ expect(t.get(1)).toBe(10);
1490
+ expect(t.get(2)).toBeUndefined(); // subsequent value not provided
1491
+ expect(t.get(3)).toBeUndefined();
1492
+
1493
+ // reverse test: values longer (extra values should be ignored)
1494
+ const t2 = new BinaryTree<number, number>([], { isMapMode: true } as any);
1495
+ t2.addMany([7, 8], [70, 80, 90, 100]);
1496
+ expect(t2.get(7)).toBe(70);
1497
+ expect(t2.get(8)).toBe(80);
1498
+ });
1499
+
1500
+ it('delete non-existent key: returns empty array and does not affect size', () => {
1501
+ const t = new BinaryTree<number>([1, 2, 3]);
1502
+ const before = t.size;
1503
+ const res = t.delete(999);
1504
+ expect(Array.isArray(res)).toBe(true);
1505
+ expect(res.length).toBe(0);
1506
+ expect(t.size).toBe(before);
1507
+ });
1508
+
1509
+ it('toVisual additional combinations (S only / U only)', () => {
1510
+ const t = new BinaryTree<number>([2, 1, 3]);
1511
+ const sOnly = t.toVisual(t.root, { isShowRedBlackNIL: true } as any);
1512
+ const uOnly = t.toVisual(t.root, { isShowUndefined: true } as any);
1513
+ expect(sOnly.includes('S for Sentinel Node')).toBe(true);
1514
+ expect(uOnly.startsWith('U for undefined')).toBe(true);
1515
+ });
1516
+
1517
+ it('clone in Map mode shares storage: updates in original visible in clone', () => {
1518
+ const t = new BinaryTree<number, string>(
1519
+ [
1520
+ [1, 'a'],
1521
+ [2, 'b']
1522
+ ],
1523
+ { isMapMode: true } as any
1524
+ );
1525
+ const c = t.clone() as BinaryTree<number, string>;
1526
+ // In the original tree, "replace" the value for the same key (Map mode triggers _store.set)
1527
+ t.add([2, 'B']);
1528
+ // Because clone shares Map storage, the clone can also read the new value
1529
+ expect(c.get(2)).toBe('B');
1530
+ });
1531
+ });
1532
+
1533
+ // === [Coverage boosters - appended at end of file] ===
1534
+
1535
+ describe('Coverage boosters - close remaining uncovered branches', () => {
1536
+ it('print(): omit all params -> hit default startNode branch', () => {
1537
+ const t = new BinaryTree<number>([2, 1, 3]);
1538
+ const spy = jest.spyOn(console, 'log').mockImplementation(() => void 0);
1539
+ t.print(); // Use default arguments to cover the branch startNode = this._root
1540
+ expect(spy).toHaveBeenCalledTimes(1);
1541
+ spy.mockRestore();
1542
+ });
1543
+
1544
+ it('toVisual(): cover default args and empty-tree early return', () => {
1545
+ const t1 = new BinaryTree<number>([2, 1, 3]);
1546
+ const out1 = t1.toVisual(); // default startNode / options
1547
+ expect(typeof out1).toBe('string');
1548
+
1549
+ const t2 = new BinaryTree<number>(); // empty tree
1550
+ expect(t2.toVisual()).toBe(''); // no root after ensureNode -> directly return empty string
1551
+ });
1552
+
1553
+ it('for...of (non-Map mode): hit else branch yielding [key, value]', () => {
1554
+ // default isMapMode=false
1555
+ const t = new BinaryTree<number, string>([
1556
+ [1, 'a'],
1557
+ [2, 'b']
1558
+ ]);
1559
+ const got = Array.from(t); // Iterator runs in non-Map mode
1560
+ expect(got).toContainEqual([1, 'a']);
1561
+ expect(got).toContainEqual([2, 'b']);
1562
+ });
1563
+
1564
+ it('listLevels(): cover default args + RECURSIVE + includeNull=true', () => {
1565
+ // Level-order initialization with nulls to observe includeNull branch
1566
+ const t = new BinaryTree<number>([4, 2, 6, null, 3]);
1567
+ const levelsDefault = t.listLevels() as any; // default callback/startNode/iterationType
1568
+ expect(Array.isArray(levelsDefault)).toBe(true);
1569
+
1570
+ // enable includeNull=true (recursive branch)
1571
+ const levelsWithNulls = t.listLevels(n => (n ? n.key : null), undefined, 'RECURSIVE', true);
1572
+ const hasNull = levelsWithNulls.some(level => level.some(x => x === null));
1573
+ expect(hasNull).toBe(true);
1574
+ });
1575
+
1576
+ it('map(options): pass options to cover _speciesCreate(options) path', () => {
1577
+ const t = new BinaryTree<number, string>([
1578
+ [1, 'a'],
1579
+ [2, 'b']
1580
+ ]);
1581
+ const mapped = t.map((k, v) => [String(k), (v ?? '').toUpperCase()], { iterationType: 'RECURSIVE' } as any);
1582
+ expect(Array.from(mapped)).toEqual([
1583
+ ['1', 'A'],
1584
+ ['2', 'B']
1585
+ ]);
1586
+ });
1587
+
1588
+ it('add(): build tree with no undefined child slot -> return false path', () => {
1589
+ const t = new BinaryTree<number>();
1590
+ const r = t._createNode(1)!;
1591
+ // explicitly set left/right child pointers to null (not undefined) so BFS finds no insertion slot
1592
+ (r as any).left = null;
1593
+ (r as any).right = null;
1594
+ (t as any)._root = r;
1595
+ (t as any)._size = 1;
1596
+
1597
+ expect(t.add(2)).toBe(false); // no insertion position -> return false
1598
+ });
1599
+ });
1600
+
1601
+ // === [Coverage Boosters #2 - append below] ===
1602
+ describe('Coverage boosters v2 - hit remaining statements', () => {
1603
+ it('BinaryTreeNode.familyPosition -> MAL_NODE when parent does not point back', () => {
1604
+ const parent = new BinaryTreeNode<number>(1);
1605
+ const child = new BinaryTreeNode<number>(2);
1606
+ (child as any).parent = parent; // one-way parent assignment; parent does not attach child as left/right
1607
+ expect(child.familyPosition).toBe('MAL_NODE');
1608
+ });
1609
+
1610
+ it('add(): returns false when tree has no undefined slots (all defined as null)', () => {
1611
+ const t = new BinaryTree<number>();
1612
+ const root = new BinaryTreeNode<number>(1);
1613
+ (root as any).left = null;
1614
+ (root as any).right = null;
1615
+ (t as any)._root = root;
1616
+ (t as any)._size = 1;
1617
+ expect(t.add(2)).toBe(false); // no slot with left/right undefined after queue traversal
1618
+ });
1619
+
1620
+ it('getSuccessor(): climb ancestors while x is a right child', () => {
1621
+ const t = new BinaryTree<number>();
1622
+ const a = new BinaryTreeNode<number>(1);
1623
+ const b = new BinaryTreeNode<number>(2);
1624
+ const c = new BinaryTreeNode<number>(3);
1625
+ (t as any)._root = a;
1626
+ a.right = b;
1627
+ (b as any).parent = a;
1628
+ b.right = c;
1629
+ (c as any).parent = b;
1630
+ expect(t.getSuccessor(c)).toBe(undefined); // trigger multiple climbs in while (x === y.right)
1631
+ });
1632
+
1633
+ it('getPredecessor(): walk to right-most of left subtree', () => {
1634
+ const t = new BinaryTree<number>();
1635
+ const n5 = new BinaryTreeNode<number>(5);
1636
+ const n3 = new BinaryTreeNode<number>(3);
1637
+ const n4 = new BinaryTreeNode<number>(4);
1638
+ (t as any)._root = n5;
1639
+ n5.left = n3;
1640
+ (n3 as any).parent = n5;
1641
+ n3.right = n4;
1642
+ (n4 as any).parent = n3;
1643
+ expect(t.getPredecessor(n5)).toBe(n4); // hit the while loop
1644
+ });
1645
+
1646
+ it('_extractKey via Map mode: get/has on entry tuple + null/undefined keys', () => {
1647
+ const t = new BinaryTree<number, string>([], { isMapMode: true } as any);
1648
+ t.add([1, 'a']);
1649
+ t.add([2, 'b']);
1650
+ expect(t.get([2, 'anything'] as any)).toBe('b'); // entry tuple path
1651
+ expect(t.has([1, 'x'] as any)).toBe(true);
1652
+ expect(t.get([null as any, 'x'] as any)).toBeUndefined(); // null key
1653
+ expect(t.get([undefined as any, 'x'] as any)).toBeUndefined(); // undefined key
1654
+ });
1655
+
1656
+ it('_setValue: value is undefined branch executes (Map mode)', () => {
1657
+ const t = new BinaryTree<number, string>([], { isMapMode: true } as any);
1658
+ expect(t.add([10, undefined] as any)).toBe(true); // trigger _setValue branch where value is undefined
1659
+ expect(t.get(10)).toBeUndefined();
1660
+ });
1661
+
1662
+ it('print(): default-args branch (no params)', () => {
1663
+ const t = new BinaryTree<number>([2, 1, 3]);
1664
+ const spy = jest.spyOn(console, 'log').mockImplementation(() => void 0);
1665
+ t.print(); // no arguments -> hit default startNode branch
1666
+ expect(spy).toHaveBeenCalledTimes(1);
1667
+ spy.mockRestore();
1668
+ });
1669
+
1670
+ it('search(undefined): returns [] (early return)', () => {
1671
+ const t = new BinaryTree<number>([1, 2, 3]);
1672
+ expect(t.search(undefined as any)).toEqual([]);
1673
+ expect(t.search(null as any)).toEqual([]);
1674
+ });
1675
+
1676
+ it('isValidKey(null): returns true', () => {
1677
+ const t = new BinaryTree<number>();
1678
+ expect(t.isValidKey(null)).toBe(true);
1679
+ });
1680
+ });
1681
+
1682
+ describe('Classic usage examples', () => {
1423
1683
  it('@example determine loan approval using a decision tree', () => {
1424
1684
  // Decision tree structure
1425
1685
  const loanDecisionTree = new BinaryTree<string>(