tree-multimap-typed 1.42.5

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 (366) hide show
  1. package/.dependency-cruiser.js +449 -0
  2. package/.eslintrc.js +65 -0
  3. package/.prettierignore +6 -0
  4. package/.prettierrc.js +16 -0
  5. package/LICENSE +21 -0
  6. package/README.md +527 -0
  7. package/coverage/clover.xml +14 -0
  8. package/coverage/coverage-final.json +96 -0
  9. package/coverage/coverage-summary.json +60 -0
  10. package/coverage/lcov-report/base.css +403 -0
  11. package/coverage/lcov-report/block-navigation.js +87 -0
  12. package/coverage/lcov-report/favicon.png +0 -0
  13. package/coverage/lcov-report/index.html +120 -0
  14. package/coverage/lcov-report/index.ts.html +110 -0
  15. package/coverage/lcov-report/prettify.css +1 -0
  16. package/coverage/lcov-report/prettify.js +2 -0
  17. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  18. package/coverage/lcov-report/sorter.js +206 -0
  19. package/coverage/lcov.info +14 -0
  20. package/dist/data-structures/binary-tree/avl-tree.d.ts +106 -0
  21. package/dist/data-structures/binary-tree/avl-tree.js +349 -0
  22. package/dist/data-structures/binary-tree/binary-indexed-tree.d.ts +149 -0
  23. package/dist/data-structures/binary-tree/binary-indexed-tree.js +269 -0
  24. package/dist/data-structures/binary-tree/binary-tree.d.ts +322 -0
  25. package/dist/data-structures/binary-tree/binary-tree.js +1305 -0
  26. package/dist/data-structures/binary-tree/bst.d.ts +175 -0
  27. package/dist/data-structures/binary-tree/bst.js +546 -0
  28. package/dist/data-structures/binary-tree/index.d.ts +7 -0
  29. package/dist/data-structures/binary-tree/index.js +23 -0
  30. package/dist/data-structures/binary-tree/rb-tree.d.ts +93 -0
  31. package/dist/data-structures/binary-tree/rb-tree.js +434 -0
  32. package/dist/data-structures/binary-tree/segment-tree.d.ts +67 -0
  33. package/dist/data-structures/binary-tree/segment-tree.js +180 -0
  34. package/dist/data-structures/binary-tree/tree-multimap.d.ts +126 -0
  35. package/dist/data-structures/binary-tree/tree-multimap.js +358 -0
  36. package/dist/data-structures/graph/abstract-graph.d.ts +347 -0
  37. package/dist/data-structures/graph/abstract-graph.js +936 -0
  38. package/dist/data-structures/graph/directed-graph.d.ts +194 -0
  39. package/dist/data-structures/graph/directed-graph.js +404 -0
  40. package/dist/data-structures/graph/index.d.ts +4 -0
  41. package/dist/data-structures/graph/index.js +20 -0
  42. package/dist/data-structures/graph/map-graph.d.ts +73 -0
  43. package/dist/data-structures/graph/map-graph.js +93 -0
  44. package/dist/data-structures/graph/undirected-graph.d.ts +120 -0
  45. package/dist/data-structures/graph/undirected-graph.js +239 -0
  46. package/dist/data-structures/hash/coordinate-map.d.ts +44 -0
  47. package/dist/data-structures/hash/coordinate-map.js +62 -0
  48. package/dist/data-structures/hash/coordinate-set.d.ts +36 -0
  49. package/dist/data-structures/hash/coordinate-set.js +52 -0
  50. package/dist/data-structures/hash/hash-map.d.ts +50 -0
  51. package/dist/data-structures/hash/hash-map.js +153 -0
  52. package/dist/data-structures/hash/hash-table.d.ts +103 -0
  53. package/dist/data-structures/hash/hash-table.js +236 -0
  54. package/dist/data-structures/hash/index.d.ts +6 -0
  55. package/dist/data-structures/hash/index.js +22 -0
  56. package/dist/data-structures/hash/tree-map.d.ts +2 -0
  57. package/dist/data-structures/hash/tree-map.js +6 -0
  58. package/dist/data-structures/hash/tree-set.d.ts +2 -0
  59. package/dist/data-structures/hash/tree-set.js +6 -0
  60. package/dist/data-structures/heap/heap.d.ts +235 -0
  61. package/dist/data-structures/heap/heap.js +515 -0
  62. package/dist/data-structures/heap/index.d.ts +3 -0
  63. package/dist/data-structures/heap/index.js +19 -0
  64. package/dist/data-structures/heap/max-heap.d.ts +15 -0
  65. package/dist/data-structures/heap/max-heap.js +26 -0
  66. package/dist/data-structures/heap/min-heap.d.ts +15 -0
  67. package/dist/data-structures/heap/min-heap.js +26 -0
  68. package/dist/data-structures/index.d.ts +11 -0
  69. package/dist/data-structures/index.js +27 -0
  70. package/dist/data-structures/linked-list/doubly-linked-list.d.ts +253 -0
  71. package/dist/data-structures/linked-list/doubly-linked-list.js +569 -0
  72. package/dist/data-structures/linked-list/index.d.ts +3 -0
  73. package/dist/data-structures/linked-list/index.js +19 -0
  74. package/dist/data-structures/linked-list/singly-linked-list.d.ts +232 -0
  75. package/dist/data-structures/linked-list/singly-linked-list.js +533 -0
  76. package/dist/data-structures/linked-list/skip-linked-list.d.ts +80 -0
  77. package/dist/data-structures/linked-list/skip-linked-list.js +187 -0
  78. package/dist/data-structures/matrix/index.d.ts +4 -0
  79. package/dist/data-structures/matrix/index.js +20 -0
  80. package/dist/data-structures/matrix/matrix.d.ts +21 -0
  81. package/dist/data-structures/matrix/matrix.js +28 -0
  82. package/dist/data-structures/matrix/matrix2d.d.ts +107 -0
  83. package/dist/data-structures/matrix/matrix2d.js +199 -0
  84. package/dist/data-structures/matrix/navigator.d.ts +52 -0
  85. package/dist/data-structures/matrix/navigator.js +106 -0
  86. package/dist/data-structures/matrix/vector2d.d.ts +200 -0
  87. package/dist/data-structures/matrix/vector2d.js +290 -0
  88. package/dist/data-structures/priority-queue/index.d.ts +3 -0
  89. package/dist/data-structures/priority-queue/index.js +19 -0
  90. package/dist/data-structures/priority-queue/max-priority-queue.d.ts +15 -0
  91. package/dist/data-structures/priority-queue/max-priority-queue.js +26 -0
  92. package/dist/data-structures/priority-queue/min-priority-queue.d.ts +15 -0
  93. package/dist/data-structures/priority-queue/min-priority-queue.js +26 -0
  94. package/dist/data-structures/priority-queue/priority-queue.d.ts +15 -0
  95. package/dist/data-structures/priority-queue/priority-queue.js +17 -0
  96. package/dist/data-structures/queue/deque.d.ts +161 -0
  97. package/dist/data-structures/queue/deque.js +264 -0
  98. package/dist/data-structures/queue/index.d.ts +2 -0
  99. package/dist/data-structures/queue/index.js +18 -0
  100. package/dist/data-structures/queue/queue.d.ts +122 -0
  101. package/dist/data-structures/queue/queue.js +187 -0
  102. package/dist/data-structures/stack/index.d.ts +1 -0
  103. package/dist/data-structures/stack/index.js +17 -0
  104. package/dist/data-structures/stack/stack.d.ts +64 -0
  105. package/dist/data-structures/stack/stack.js +94 -0
  106. package/dist/data-structures/tree/index.d.ts +1 -0
  107. package/dist/data-structures/tree/index.js +17 -0
  108. package/dist/data-structures/tree/tree.d.ts +8 -0
  109. package/dist/data-structures/tree/tree.js +40 -0
  110. package/dist/data-structures/trie/index.d.ts +1 -0
  111. package/dist/data-structures/trie/index.js +17 -0
  112. package/dist/data-structures/trie/trie.d.ts +79 -0
  113. package/dist/data-structures/trie/trie.js +251 -0
  114. package/dist/index.d.ts +10 -0
  115. package/dist/index.js +27 -0
  116. package/dist/interfaces/binary-tree.d.ts +7 -0
  117. package/dist/interfaces/binary-tree.js +2 -0
  118. package/dist/interfaces/doubly-linked-list.d.ts +1 -0
  119. package/dist/interfaces/doubly-linked-list.js +2 -0
  120. package/dist/interfaces/graph.d.ts +5 -0
  121. package/dist/interfaces/graph.js +2 -0
  122. package/dist/interfaces/heap.d.ts +1 -0
  123. package/dist/interfaces/heap.js +2 -0
  124. package/dist/interfaces/index.d.ts +8 -0
  125. package/dist/interfaces/index.js +24 -0
  126. package/dist/interfaces/navigator.d.ts +1 -0
  127. package/dist/interfaces/navigator.js +2 -0
  128. package/dist/interfaces/priority-queue.d.ts +1 -0
  129. package/dist/interfaces/priority-queue.js +2 -0
  130. package/dist/interfaces/segment-tree.d.ts +1 -0
  131. package/dist/interfaces/segment-tree.js +2 -0
  132. package/dist/interfaces/singly-linked-list.d.ts +1 -0
  133. package/dist/interfaces/singly-linked-list.js +2 -0
  134. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +4 -0
  135. package/dist/types/data-structures/binary-tree/avl-tree.js +2 -0
  136. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +1 -0
  137. package/dist/types/data-structures/binary-tree/binary-indexed-tree.js +2 -0
  138. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +29 -0
  139. package/dist/types/data-structures/binary-tree/binary-tree.js +24 -0
  140. package/dist/types/data-structures/binary-tree/bst.d.ts +7 -0
  141. package/dist/types/data-structures/binary-tree/bst.js +2 -0
  142. package/dist/types/data-structures/binary-tree/index.d.ts +6 -0
  143. package/dist/types/data-structures/binary-tree/index.js +22 -0
  144. package/dist/types/data-structures/binary-tree/rb-tree.d.ts +8 -0
  145. package/dist/types/data-structures/binary-tree/rb-tree.js +8 -0
  146. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +1 -0
  147. package/dist/types/data-structures/binary-tree/segment-tree.js +2 -0
  148. package/dist/types/data-structures/binary-tree/tree-multimap.d.ts +4 -0
  149. package/dist/types/data-structures/binary-tree/tree-multimap.js +2 -0
  150. package/dist/types/data-structures/graph/abstract-graph.d.ts +10 -0
  151. package/dist/types/data-structures/graph/abstract-graph.js +2 -0
  152. package/dist/types/data-structures/graph/directed-graph.d.ts +6 -0
  153. package/dist/types/data-structures/graph/directed-graph.js +9 -0
  154. package/dist/types/data-structures/graph/index.d.ts +3 -0
  155. package/dist/types/data-structures/graph/index.js +19 -0
  156. package/dist/types/data-structures/graph/map-graph.d.ts +1 -0
  157. package/dist/types/data-structures/graph/map-graph.js +2 -0
  158. package/dist/types/data-structures/graph/undirected-graph.d.ts +1 -0
  159. package/dist/types/data-structures/graph/undirected-graph.js +2 -0
  160. package/dist/types/data-structures/hash/coordinate-map.d.ts +1 -0
  161. package/dist/types/data-structures/hash/coordinate-map.js +2 -0
  162. package/dist/types/data-structures/hash/coordinate-set.d.ts +1 -0
  163. package/dist/types/data-structures/hash/coordinate-set.js +2 -0
  164. package/dist/types/data-structures/hash/hash-map.d.ts +1 -0
  165. package/dist/types/data-structures/hash/hash-map.js +2 -0
  166. package/dist/types/data-structures/hash/hash-table.d.ts +1 -0
  167. package/dist/types/data-structures/hash/hash-table.js +2 -0
  168. package/dist/types/data-structures/hash/index.d.ts +1 -0
  169. package/dist/types/data-structures/hash/index.js +2 -0
  170. package/dist/types/data-structures/hash/tree-map.d.ts +1 -0
  171. package/dist/types/data-structures/hash/tree-map.js +2 -0
  172. package/dist/types/data-structures/hash/tree-set.d.ts +1 -0
  173. package/dist/types/data-structures/hash/tree-set.js +2 -0
  174. package/dist/types/data-structures/heap/heap.d.ts +1 -0
  175. package/dist/types/data-structures/heap/heap.js +2 -0
  176. package/dist/types/data-structures/heap/index.d.ts +1 -0
  177. package/dist/types/data-structures/heap/index.js +17 -0
  178. package/dist/types/data-structures/heap/max-heap.d.ts +1 -0
  179. package/dist/types/data-structures/heap/max-heap.js +2 -0
  180. package/dist/types/data-structures/heap/min-heap.d.ts +1 -0
  181. package/dist/types/data-structures/heap/min-heap.js +2 -0
  182. package/dist/types/data-structures/index.d.ts +11 -0
  183. package/dist/types/data-structures/index.js +27 -0
  184. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +1 -0
  185. package/dist/types/data-structures/linked-list/doubly-linked-list.js +2 -0
  186. package/dist/types/data-structures/linked-list/index.d.ts +2 -0
  187. package/dist/types/data-structures/linked-list/index.js +18 -0
  188. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +1 -0
  189. package/dist/types/data-structures/linked-list/singly-linked-list.js +2 -0
  190. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +1 -0
  191. package/dist/types/data-structures/linked-list/skip-linked-list.js +2 -0
  192. package/dist/types/data-structures/matrix/index.d.ts +1 -0
  193. package/dist/types/data-structures/matrix/index.js +17 -0
  194. package/dist/types/data-structures/matrix/matrix.d.ts +1 -0
  195. package/dist/types/data-structures/matrix/matrix.js +2 -0
  196. package/dist/types/data-structures/matrix/matrix2d.d.ts +1 -0
  197. package/dist/types/data-structures/matrix/matrix2d.js +2 -0
  198. package/dist/types/data-structures/matrix/navigator.d.ts +14 -0
  199. package/dist/types/data-structures/matrix/navigator.js +2 -0
  200. package/dist/types/data-structures/matrix/vector2d.d.ts +1 -0
  201. package/dist/types/data-structures/matrix/vector2d.js +2 -0
  202. package/dist/types/data-structures/priority-queue/index.d.ts +3 -0
  203. package/dist/types/data-structures/priority-queue/index.js +19 -0
  204. package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +1 -0
  205. package/dist/types/data-structures/priority-queue/max-priority-queue.js +2 -0
  206. package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +1 -0
  207. package/dist/types/data-structures/priority-queue/min-priority-queue.js +2 -0
  208. package/dist/types/data-structures/priority-queue/priority-queue.d.ts +1 -0
  209. package/dist/types/data-structures/priority-queue/priority-queue.js +2 -0
  210. package/dist/types/data-structures/queue/deque.d.ts +1 -0
  211. package/dist/types/data-structures/queue/deque.js +2 -0
  212. package/dist/types/data-structures/queue/index.d.ts +2 -0
  213. package/dist/types/data-structures/queue/index.js +18 -0
  214. package/dist/types/data-structures/queue/queue.d.ts +1 -0
  215. package/dist/types/data-structures/queue/queue.js +2 -0
  216. package/dist/types/data-structures/stack/index.d.ts +1 -0
  217. package/dist/types/data-structures/stack/index.js +17 -0
  218. package/dist/types/data-structures/stack/stack.d.ts +1 -0
  219. package/dist/types/data-structures/stack/stack.js +2 -0
  220. package/dist/types/data-structures/tree/index.d.ts +1 -0
  221. package/dist/types/data-structures/tree/index.js +17 -0
  222. package/dist/types/data-structures/tree/tree.d.ts +1 -0
  223. package/dist/types/data-structures/tree/tree.js +2 -0
  224. package/dist/types/data-structures/trie/index.d.ts +1 -0
  225. package/dist/types/data-structures/trie/index.js +17 -0
  226. package/dist/types/data-structures/trie/trie.d.ts +1 -0
  227. package/dist/types/data-structures/trie/trie.js +2 -0
  228. package/dist/types/helpers.d.ts +8 -0
  229. package/dist/types/helpers.js +9 -0
  230. package/dist/types/index.d.ts +3 -0
  231. package/dist/types/index.js +19 -0
  232. package/dist/types/utils/index.d.ts +2 -0
  233. package/dist/types/utils/index.js +18 -0
  234. package/dist/types/utils/utils.d.ts +7 -0
  235. package/dist/types/utils/utils.js +2 -0
  236. package/dist/types/utils/validate-type.d.ts +19 -0
  237. package/dist/types/utils/validate-type.js +2 -0
  238. package/dist/utils/index.d.ts +1 -0
  239. package/dist/utils/index.js +17 -0
  240. package/dist/utils/utils.d.ts +20 -0
  241. package/dist/utils/utils.js +73 -0
  242. package/docs/.nojekyll +1 -0
  243. package/docs/assets/highlight.css +50 -0
  244. package/docs/assets/main.js +59 -0
  245. package/docs/assets/navigation.js +1 -0
  246. package/docs/assets/search.js +1 -0
  247. package/docs/assets/style.css +1383 -0
  248. package/docs/classes/TreeMultiset.html +2376 -0
  249. package/docs/classes/TreeMultisetNode.html +313 -0
  250. package/docs/index.html +523 -0
  251. package/docs/modules.html +45 -0
  252. package/jest.config.js +8 -0
  253. package/package.json +184 -0
  254. package/src/data-structures/binary-tree/avl-tree.ts +352 -0
  255. package/src/data-structures/binary-tree/binary-indexed-tree.ts +306 -0
  256. package/src/data-structures/binary-tree/binary-tree.ts +1558 -0
  257. package/src/data-structures/binary-tree/bst.ts +564 -0
  258. package/src/data-structures/binary-tree/index.ts +7 -0
  259. package/src/data-structures/binary-tree/rb-tree.ts +486 -0
  260. package/src/data-structures/binary-tree/segment-tree.ts +190 -0
  261. package/src/data-structures/binary-tree/tree-multimap.ts +381 -0
  262. package/src/data-structures/graph/abstract-graph.ts +1056 -0
  263. package/src/data-structures/graph/directed-graph.ts +450 -0
  264. package/src/data-structures/graph/index.ts +4 -0
  265. package/src/data-structures/graph/map-graph.ts +106 -0
  266. package/src/data-structures/graph/undirected-graph.ts +260 -0
  267. package/src/data-structures/hash/coordinate-map.ts +63 -0
  268. package/src/data-structures/hash/coordinate-set.ts +52 -0
  269. package/src/data-structures/hash/hash-map.ts +185 -0
  270. package/src/data-structures/hash/hash-table.ts +268 -0
  271. package/src/data-structures/hash/index.ts +6 -0
  272. package/src/data-structures/hash/tree-map.ts +1 -0
  273. package/src/data-structures/hash/tree-set.ts +1 -0
  274. package/src/data-structures/heap/heap.ts +589 -0
  275. package/src/data-structures/heap/index.ts +3 -0
  276. package/src/data-structures/heap/max-heap.ts +26 -0
  277. package/src/data-structures/heap/min-heap.ts +26 -0
  278. package/src/data-structures/index.ts +11 -0
  279. package/src/data-structures/linked-list/doubly-linked-list.ts +605 -0
  280. package/src/data-structures/linked-list/index.ts +3 -0
  281. package/src/data-structures/linked-list/singly-linked-list.ts +576 -0
  282. package/src/data-structures/linked-list/skip-linked-list.ts +221 -0
  283. package/src/data-structures/matrix/index.ts +4 -0
  284. package/src/data-structures/matrix/matrix.ts +27 -0
  285. package/src/data-structures/matrix/matrix2d.ts +211 -0
  286. package/src/data-structures/matrix/navigator.ts +121 -0
  287. package/src/data-structures/matrix/vector2d.ts +314 -0
  288. package/src/data-structures/priority-queue/index.ts +3 -0
  289. package/src/data-structures/priority-queue/max-priority-queue.ts +25 -0
  290. package/src/data-structures/priority-queue/min-priority-queue.ts +25 -0
  291. package/src/data-structures/priority-queue/priority-queue.ts +16 -0
  292. package/src/data-structures/queue/deque.ts +281 -0
  293. package/src/data-structures/queue/index.ts +2 -0
  294. package/src/data-structures/queue/queue.ts +209 -0
  295. package/src/data-structures/stack/index.ts +1 -0
  296. package/src/data-structures/stack/stack.ts +102 -0
  297. package/src/data-structures/tree/index.ts +1 -0
  298. package/src/data-structures/tree/tree.ts +41 -0
  299. package/src/data-structures/trie/index.ts +1 -0
  300. package/src/data-structures/trie/trie.ts +262 -0
  301. package/src/index.ts +11 -0
  302. package/src/interfaces/binary-tree.ts +10 -0
  303. package/src/interfaces/doubly-linked-list.ts +1 -0
  304. package/src/interfaces/graph.ts +7 -0
  305. package/src/interfaces/heap.ts +1 -0
  306. package/src/interfaces/index.ts +8 -0
  307. package/src/interfaces/navigator.ts +1 -0
  308. package/src/interfaces/priority-queue.ts +1 -0
  309. package/src/interfaces/segment-tree.ts +1 -0
  310. package/src/interfaces/singly-linked-list.ts +1 -0
  311. package/src/types/data-structures/binary-tree/avl-tree.ts +5 -0
  312. package/src/types/data-structures/binary-tree/binary-indexed-tree.ts +1 -0
  313. package/src/types/data-structures/binary-tree/binary-tree.ts +31 -0
  314. package/src/types/data-structures/binary-tree/bst.ts +11 -0
  315. package/src/types/data-structures/binary-tree/index.ts +6 -0
  316. package/src/types/data-structures/binary-tree/rb-tree.ts +8 -0
  317. package/src/types/data-structures/binary-tree/segment-tree.ts +1 -0
  318. package/src/types/data-structures/binary-tree/tree-multimap.ts +6 -0
  319. package/src/types/data-structures/graph/abstract-graph.ts +11 -0
  320. package/src/types/data-structures/graph/directed-graph.ts +8 -0
  321. package/src/types/data-structures/graph/index.ts +3 -0
  322. package/src/types/data-structures/graph/map-graph.ts +1 -0
  323. package/src/types/data-structures/graph/undirected-graph.ts +1 -0
  324. package/src/types/data-structures/hash/coordinate-map.ts +1 -0
  325. package/src/types/data-structures/hash/coordinate-set.ts +1 -0
  326. package/src/types/data-structures/hash/hash-map.ts +1 -0
  327. package/src/types/data-structures/hash/hash-table.ts +1 -0
  328. package/src/types/data-structures/hash/index.ts +1 -0
  329. package/src/types/data-structures/hash/tree-map.ts +1 -0
  330. package/src/types/data-structures/hash/tree-set.ts +1 -0
  331. package/src/types/data-structures/heap/heap.ts +1 -0
  332. package/src/types/data-structures/heap/index.ts +1 -0
  333. package/src/types/data-structures/heap/max-heap.ts +1 -0
  334. package/src/types/data-structures/heap/min-heap.ts +1 -0
  335. package/src/types/data-structures/index.ts +11 -0
  336. package/src/types/data-structures/linked-list/doubly-linked-list.ts +1 -0
  337. package/src/types/data-structures/linked-list/index.ts +2 -0
  338. package/src/types/data-structures/linked-list/singly-linked-list.ts +1 -0
  339. package/src/types/data-structures/linked-list/skip-linked-list.ts +1 -0
  340. package/src/types/data-structures/matrix/index.ts +1 -0
  341. package/src/types/data-structures/matrix/matrix.ts +1 -0
  342. package/src/types/data-structures/matrix/matrix2d.ts +1 -0
  343. package/src/types/data-structures/matrix/navigator.ts +14 -0
  344. package/src/types/data-structures/matrix/vector2d.ts +1 -0
  345. package/src/types/data-structures/priority-queue/index.ts +3 -0
  346. package/src/types/data-structures/priority-queue/max-priority-queue.ts +1 -0
  347. package/src/types/data-structures/priority-queue/min-priority-queue.ts +1 -0
  348. package/src/types/data-structures/priority-queue/priority-queue.ts +1 -0
  349. package/src/types/data-structures/queue/deque.ts +1 -0
  350. package/src/types/data-structures/queue/index.ts +2 -0
  351. package/src/types/data-structures/queue/queue.ts +1 -0
  352. package/src/types/data-structures/stack/index.ts +1 -0
  353. package/src/types/data-structures/stack/stack.ts +1 -0
  354. package/src/types/data-structures/tree/index.ts +1 -0
  355. package/src/types/data-structures/tree/tree.ts +1 -0
  356. package/src/types/data-structures/trie/index.ts +1 -0
  357. package/src/types/data-structures/trie/trie.ts +1 -0
  358. package/src/types/helpers.ts +11 -0
  359. package/src/types/index.ts +3 -0
  360. package/src/types/utils/index.ts +2 -0
  361. package/src/types/utils/utils.ts +6 -0
  362. package/src/types/utils/validate-type.ts +35 -0
  363. package/src/utils/index.ts +1 -0
  364. package/src/utils/utils.ts +86 -0
  365. package/test/index.test.ts +461 -0
  366. package/tsconfig.json +38 -0
@@ -0,0 +1,1558 @@
1
+ /**
2
+ * data-structure-typed
3
+ *
4
+ * @author Tyler Zeng
5
+ * @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
6
+ * @license MIT License
7
+ */
8
+
9
+ import type {BinaryTreeNodeNested, BinaryTreeOptions, BTNCallback, BTNKey} from '../../types';
10
+ import {BinaryTreeDeletedResult, DFSOrderPattern, FamilyPosition, IterationType} from '../../types';
11
+ import {IBinaryTree} from '../../interfaces';
12
+ import {trampoline} from '../../utils';
13
+ import {Queue} from '../queue';
14
+
15
+ /**
16
+ * Represents a node in a binary tree.
17
+ * @template V - The type of data stored in the node.
18
+ * @template N - The type of the family relationship in the binary tree.
19
+ */
20
+ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>> {
21
+ /**
22
+ * The key associated with the node.
23
+ */
24
+ key: BTNKey;
25
+
26
+ /**
27
+ * The value stored in the node.
28
+ */
29
+ value: V | undefined;
30
+
31
+ /**
32
+ * The parent node of the current node.
33
+ */
34
+ parent: N | null | undefined;
35
+
36
+ /**
37
+ * Creates a new instance of BinaryTreeNode.
38
+ * @param {BTNKey} key - The key associated with the node.
39
+ * @param {V} value - The value stored in the node.
40
+ */
41
+ constructor(key: BTNKey, value?: V) {
42
+ this.key = key;
43
+ this.value = value;
44
+ }
45
+
46
+ protected _left: N | null | undefined;
47
+
48
+ /**
49
+ * Get the left child node.
50
+ */
51
+ get left(): N | null | undefined {
52
+ return this._left;
53
+ }
54
+
55
+ /**
56
+ * Set the left child node.
57
+ * @param {N | null | undefined} v - The left child node.
58
+ */
59
+ set left(v: N | null | undefined) {
60
+ if (v) {
61
+ v.parent = this as unknown as N;
62
+ }
63
+ this._left = v;
64
+ }
65
+
66
+ protected _right: N | null | undefined;
67
+
68
+ /**
69
+ * Get the right child node.
70
+ */
71
+ get right(): N | null | undefined {
72
+ return this._right;
73
+ }
74
+
75
+ /**
76
+ * Set the right child node.
77
+ * @param {N | null | undefined} v - The right child node.
78
+ */
79
+ set right(v: N | null | undefined) {
80
+ if (v) {
81
+ v.parent = this as unknown as N;
82
+ }
83
+ this._right = v;
84
+ }
85
+
86
+ /**
87
+ * Get the position of the node within its family.
88
+ * @returns {FamilyPosition} - The family position of the node.
89
+ */
90
+ get familyPosition(): FamilyPosition {
91
+ const that = this as unknown as N;
92
+ if (!this.parent) {
93
+ return this.left || this.right ? FamilyPosition.ROOT : FamilyPosition.ISOLATED;
94
+ }
95
+
96
+ if (this.parent.left === that) {
97
+ return this.left || this.right ? FamilyPosition.ROOT_LEFT : FamilyPosition.LEFT;
98
+ } else if (this.parent.right === that) {
99
+ return this.left || this.right ? FamilyPosition.ROOT_RIGHT : FamilyPosition.RIGHT;
100
+ }
101
+
102
+ return FamilyPosition.MAL_NODE;
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Represents a binary tree data structure.
108
+ * @template N - The type of the binary tree's nodes.
109
+ */
110
+ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>>
111
+ implements IBinaryTree<V, N>
112
+ {
113
+ iterationType: IterationType = IterationType.ITERATIVE;
114
+
115
+ /**
116
+ * Creates a new instance of BinaryTree.
117
+ * @param {BinaryTreeOptions} [options] - The options for the binary tree.
118
+ */
119
+ constructor(options?: BinaryTreeOptions) {
120
+ if (options !== undefined) {
121
+ const {iterationType = IterationType.ITERATIVE} = options;
122
+ this.iterationType = iterationType;
123
+ }
124
+ }
125
+
126
+ protected _root: N | null | undefined = undefined;
127
+
128
+ /**
129
+ * Get the root node of the binary tree.
130
+ */
131
+ get root(): N | null | undefined {
132
+ return this._root;
133
+ }
134
+
135
+ protected _size = 0;
136
+
137
+ /**
138
+ * Get the number of nodes in the binary tree.
139
+ */
140
+ get size(): number {
141
+ return this._size;
142
+ }
143
+
144
+ /**
145
+ * Creates a new instance of BinaryTreeNode with the given key and value.
146
+ * @param {BTNKey} key - The key for the new node.
147
+ * @param {V} value - The value for the new node.
148
+ * @returns {N} - The newly created BinaryTreeNode.
149
+ */
150
+ createNode(key: BTNKey, value?: V): N {
151
+ return new BinaryTreeNode<V, N>(key, value) as N;
152
+ }
153
+
154
+ /**
155
+ * Clear the binary tree, removing all nodes.
156
+ */
157
+ clear() {
158
+ this._setRoot(undefined);
159
+ this._size = 0;
160
+ }
161
+
162
+ /**
163
+ * Check if the binary tree is empty.
164
+ * @returns {boolean} - True if the binary tree is empty, false otherwise.
165
+ */
166
+ isEmpty(): boolean {
167
+ return this.size === 0;
168
+ }
169
+
170
+ /**
171
+ * Add a node with the given key and value to the binary tree.
172
+ * @param {BTNKey | N | null} keyOrNode - The key or node to add to the binary tree.
173
+ * @param {V} value - The value for the new node (optional).
174
+ * @returns {N | null | undefined} - The inserted node, or null if nothing was inserted, or undefined if the operation failed.
175
+ */
176
+ add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | null | undefined {
177
+ const _bfs = (root: N, newNode: N | null): N | undefined | null => {
178
+ const queue = new Queue<N | null>([root]);
179
+ while (queue.size > 0) {
180
+ const cur = queue.shift();
181
+ if (cur) {
182
+ if (newNode && cur.key === newNode.key) {
183
+ cur.value = newNode.value;
184
+ return;
185
+ }
186
+ const inserted = this._addTo(newNode, cur);
187
+ if (inserted !== undefined) return inserted;
188
+ if (cur.left) queue.push(cur.left);
189
+ if (cur.right) queue.push(cur.right);
190
+ } else return;
191
+ }
192
+ return;
193
+ };
194
+
195
+ let inserted: N | null | undefined, needInsert: N | null;
196
+
197
+ if (keyOrNode === null) {
198
+ needInsert = null;
199
+ } else if (typeof keyOrNode === 'number') {
200
+ needInsert = this.createNode(keyOrNode, value);
201
+ } else if (keyOrNode instanceof BinaryTreeNode) {
202
+ needInsert = keyOrNode;
203
+ } else {
204
+ return;
205
+ }
206
+
207
+ // const key = typeof keyOrNode === 'number' ? keyOrNode : keyOrNode ? keyOrNode.key : undefined;
208
+ // const existNode = key !== undefined ? this.getNode(key, (node: N) => node.key) : undefined;
209
+
210
+ if (this.root) {
211
+ // if (existNode) {
212
+ // existNode.value = value;
213
+ // inserted = existNode;
214
+ // } else {
215
+ inserted = _bfs(this.root, needInsert);
216
+ // }
217
+ } else {
218
+ this._setRoot(needInsert);
219
+ if (needInsert !== null) {
220
+ this._size = 1;
221
+ } else {
222
+ this._size = 0;
223
+ }
224
+ inserted = this.root;
225
+ }
226
+ return inserted;
227
+ }
228
+
229
+ /**
230
+ * The `addMany` function takes an array of binary tree node IDs or nodes, and optionally an array of corresponding data
231
+ * values, and adds them to the binary tree.
232
+ * @param {(BTNKey | null)[] | (N | null)[]} keysOrNodes - An array of BTNKey or BinaryTreeNode
233
+ * objects, or null values.
234
+ * @param {V[]} [values] - The `values` parameter is an optional array of values (`V[]`) that corresponds to
235
+ * the nodes or node IDs being added. It is used to set the value of each node being added. If `values` is not provided,
236
+ * the value of the nodes will be `undefined`.
237
+ * @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
238
+ */
239
+ addMany(keysOrNodes: (BTNKey | null | undefined)[] | (N | null | undefined)[], values?: V[]): (N | null | undefined)[] {
240
+ // TODO not sure addMany not be run multi times
241
+ return keysOrNodes.map((keyOrNode, i) => {
242
+ if (keyOrNode instanceof BinaryTreeNode) {
243
+ return this.add(keyOrNode.key, keyOrNode.value);
244
+ }
245
+
246
+ if (keyOrNode === null) {
247
+ return this.add(null);
248
+ }
249
+
250
+ const value = values?.[i];
251
+ return this.add(keyOrNode, value);
252
+ });
253
+ }
254
+
255
+ /**
256
+ * The `refill` function clears the binary tree and adds multiple nodes with the given IDs or nodes and optional data.
257
+ * @param {(BTNKey | N)[]} keysOrNodes - The `keysOrNodes` parameter is an array that can contain either
258
+ * `BTNKey` or `N` values.
259
+ * @param {N[] | Array<V>} [data] - The `data` parameter is an optional array of values that will be assigned to
260
+ * the nodes being added. If provided, the length of the `data` array should be equal to the length of the `keysOrNodes`
261
+ * array. Each value in the `data` array will be assigned to the
262
+ * @returns The method is returning a boolean value.
263
+ */
264
+ refill(keysOrNodes: (BTNKey | null | undefined)[] | (N | null | undefined)[], data?: Array<V>): boolean {
265
+ this.clear();
266
+ return keysOrNodes.length === this.addMany(keysOrNodes, data).length;
267
+ }
268
+
269
+ delete<C extends BTNCallback<N, BTNKey>>(identifier: BTNKey, callback?: C): BinaryTreeDeletedResult<N>[];
270
+
271
+ delete<C extends BTNCallback<N, N>>(identifier: N | null | undefined, callback?: C): BinaryTreeDeletedResult<N>[];
272
+
273
+ delete<C extends BTNCallback<N>>(identifier: ReturnType<C>, callback: C): BinaryTreeDeletedResult<N>[];
274
+
275
+ /**
276
+ * The `delete` function removes a node from a binary search tree and returns the deleted node along
277
+ * with the parent node that needs to be balanced.
278
+ * a key (`BTNKey`). If it is a key, the function will find the corresponding node in the
279
+ * binary tree.
280
+ * @returns an array of `BinaryTreeDeletedResult<N>` objects.
281
+ * @param {ReturnType<C>} identifier - The `identifier` parameter is either a
282
+ * `BTNKey` or a generic type `N`. It represents the property of the node that we are
283
+ * searching for. It can be a specific key value or any other property of the node.
284
+ * @param callback - The `callback` parameter is a function that takes a node as input and returns a
285
+ * value. This value is compared with the `identifier` parameter to determine if the node should be
286
+ * included in the result. The `callback` parameter has a default value of
287
+ * `this.defaultOneParamCallback`, which
288
+ */
289
+ delete<C extends BTNCallback<N>>(
290
+ identifier: ReturnType<C> | null | undefined,
291
+ callback: C = this.defaultOneParamCallback as C
292
+ ): BinaryTreeDeletedResult<N>[] {
293
+ const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];
294
+ if (!this.root) return bstDeletedResult;
295
+ if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
296
+
297
+ const curr = this.getNode(identifier, callback);
298
+ if (!curr) return bstDeletedResult;
299
+
300
+ const parent: N | null | undefined = curr?.parent ? curr.parent : null;
301
+ let needBalanced: N | null | undefined = null,
302
+ orgCurrent = curr;
303
+
304
+ if (!curr.left) {
305
+ if (!parent) {
306
+ // Handle the case when there's only one root node
307
+ this._setRoot(null);
308
+ } else {
309
+ const {familyPosition: fp} = curr;
310
+ if (fp === FamilyPosition.LEFT || fp === FamilyPosition.ROOT_LEFT) {
311
+ parent.left = curr.right;
312
+ } else if (fp === FamilyPosition.RIGHT || fp === FamilyPosition.ROOT_RIGHT) {
313
+ parent.right = curr.right;
314
+ }
315
+ needBalanced = parent;
316
+ }
317
+ } else {
318
+ const leftSubTreeRightMost = curr.left ? this.getRightMost(curr.left) : null;
319
+ if (leftSubTreeRightMost) {
320
+ const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
321
+ orgCurrent = this._swap(curr, leftSubTreeRightMost);
322
+ if (parentOfLeftSubTreeMax) {
323
+ if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost)
324
+ parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
325
+ else parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;
326
+ needBalanced = parentOfLeftSubTreeMax;
327
+ }
328
+ }
329
+ }
330
+ this._size = this.size - 1;
331
+
332
+ bstDeletedResult.push({deleted: orgCurrent, needBalanced});
333
+ return bstDeletedResult;
334
+ }
335
+
336
+ /**
337
+ * The function `getDepth` calculates the depth of a given node in a binary tree relative to a
338
+ * specified root node.
339
+ * @param {BTNKey | N | null | undefined} distNode - The `distNode` parameter represents the node
340
+ * whose depth we want to find in the binary tree. It can be either a node object (`N`), a key value
341
+ * of the node (`BTNKey`), or `null`.
342
+ * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
343
+ * starting node from which we want to calculate the depth. It can be either a node object or the key
344
+ * of a node in the binary tree. If no value is provided for `beginRoot`, it defaults to the root
345
+ * node of the binary tree.
346
+ * @returns the depth of the `distNode` relative to the `beginRoot`.
347
+ */
348
+ getDepth(distNode: BTNKey | N | null | undefined, beginRoot: BTNKey | N | null | undefined = this.root): number {
349
+ if (typeof distNode === 'number') distNode = this.getNode(distNode);
350
+ if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
351
+ let depth = 0;
352
+ while (distNode?.parent) {
353
+ if (distNode === beginRoot) {
354
+ return depth;
355
+ }
356
+ depth++;
357
+ distNode = distNode.parent;
358
+ }
359
+ return depth;
360
+ }
361
+
362
+ /**
363
+ * The `getHeight` function calculates the maximum height of a binary tree using either recursive or
364
+ * iterative approach.
365
+ * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter represents the
366
+ * starting node from which the height of the binary tree is calculated. It can be either a node
367
+ * object (`N`), a key value of a node in the tree (`BTNKey`), or `null` if no starting
368
+ * node is specified. If `
369
+ * @param iterationType - The `iterationType` parameter is used to determine whether to calculate the
370
+ * height of the binary tree using a recursive approach or an iterative approach. It can have two
371
+ * possible values:
372
+ * @returns the height of the binary tree.
373
+ */
374
+ getHeight(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): number {
375
+ if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
376
+ if (!beginRoot) return -1;
377
+
378
+ if (iterationType === IterationType.RECURSIVE) {
379
+ const _getMaxHeight = (cur: N | null | undefined): number => {
380
+ if (!cur) return -1;
381
+ const leftHeight = _getMaxHeight(cur.left);
382
+ const rightHeight = _getMaxHeight(cur.right);
383
+ return Math.max(leftHeight, rightHeight) + 1;
384
+ };
385
+
386
+ return _getMaxHeight(beginRoot);
387
+ } else {
388
+ if (!beginRoot) {
389
+ return -1;
390
+ }
391
+
392
+ const stack: {node: N; depth: number}[] = [{node: beginRoot, depth: 0}];
393
+ let maxHeight = 0;
394
+
395
+ while (stack.length > 0) {
396
+ const {node, depth} = stack.pop()!;
397
+
398
+ if (node.left) {
399
+ stack.push({node: node.left, depth: depth + 1});
400
+ }
401
+
402
+ if (node.right) {
403
+ stack.push({node: node.right, depth: depth + 1});
404
+ }
405
+
406
+ maxHeight = Math.max(maxHeight, depth);
407
+ }
408
+
409
+ return maxHeight;
410
+ }
411
+ }
412
+
413
+ /**
414
+ * The `getMinHeight` function calculates the minimum height of a binary tree using either a
415
+ * recursive or iterative approach.
416
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which we want to
417
+ * calculate the minimum height of the tree. It is optional and defaults to the root of the tree if
418
+ * not provided.
419
+ * @param iterationType - The `iterationType` parameter is used to determine the method of iteration
420
+ * to calculate the minimum height of a binary tree. It can have two possible values:
421
+ * @returns The function `getMinHeight` returns the minimum height of a binary tree.
422
+ */
423
+ getMinHeight(beginRoot: N | null | undefined = this.root, iterationType = this.iterationType): number {
424
+ if (!beginRoot) return -1;
425
+
426
+ if (iterationType === IterationType.RECURSIVE) {
427
+ const _getMinHeight = (cur: N | null | undefined): number => {
428
+ if (!cur) return 0;
429
+ if (!cur.left && !cur.right) return 0;
430
+ const leftMinHeight = _getMinHeight(cur.left);
431
+ const rightMinHeight = _getMinHeight(cur.right);
432
+ return Math.min(leftMinHeight, rightMinHeight) + 1;
433
+ };
434
+
435
+ return _getMinHeight(beginRoot);
436
+ } else {
437
+ const stack: N[] = [];
438
+ let node: N | null | undefined = beginRoot,
439
+ last: N | null | undefined = null;
440
+ const depths: Map<N, number> = new Map();
441
+
442
+ while (stack.length > 0 || node) {
443
+ if (node) {
444
+ stack.push(node);
445
+ node = node.left;
446
+ } else {
447
+ node = stack[stack.length - 1];
448
+ if (!node.right || last === node.right) {
449
+ node = stack.pop();
450
+ if (node) {
451
+ const leftMinHeight = node.left ? depths.get(node.left) ?? -1 : -1;
452
+ const rightMinHeight = node.right ? depths.get(node.right) ?? -1 : -1;
453
+ depths.set(node, 1 + Math.min(leftMinHeight, rightMinHeight));
454
+ last = node;
455
+ node = null;
456
+ }
457
+ } else node = node.right;
458
+ }
459
+ }
460
+
461
+ return depths.get(beginRoot) ?? -1;
462
+ }
463
+ }
464
+
465
+ /**
466
+ * The function checks if a binary tree is perfectly balanced by comparing the minimum height and the
467
+ * height of the tree.
468
+ * @param {N | null | undefined} beginRoot - The parameter `beginRoot` is of type `N | null | undefined`, which means it can
469
+ * either be of type `N` (representing a node in a tree) or `null` (representing an empty tree).
470
+ * @returns The method is returning a boolean value.
471
+ */
472
+ isPerfectlyBalanced(beginRoot: N | null | undefined = this.root): boolean {
473
+ return this.getMinHeight(beginRoot) + 1 >= this.getHeight(beginRoot);
474
+ }
475
+
476
+ getNodes<C extends BTNCallback<N, BTNKey>>(
477
+ identifier: BTNKey,
478
+ callback?: C,
479
+ onlyOne?: boolean,
480
+ beginRoot?: N | null | undefined,
481
+ iterationType?: IterationType
482
+ ): N[];
483
+
484
+ getNodes<C extends BTNCallback<N, N>>(
485
+ identifier: N | null | undefined,
486
+ callback?: C,
487
+ onlyOne?: boolean,
488
+ beginRoot?: N | null | undefined,
489
+ iterationType?: IterationType
490
+ ): N[];
491
+
492
+ getNodes<C extends BTNCallback<N>>(
493
+ identifier: ReturnType<C>,
494
+ callback: C,
495
+ onlyOne?: boolean,
496
+ beginRoot?: N | null | undefined,
497
+ iterationType?: IterationType
498
+ ): N[];
499
+
500
+ /**
501
+ * The function `getNodes` returns an array of nodes that match a given node property, using either
502
+ * recursive or iterative traversal.
503
+ * @param {ReturnType<C>} identifier - The `identifier` parameter is either a
504
+ * `BTNKey` or a generic type `N`. It represents the property of the node that we are
505
+ * searching for. It can be a specific key value or any other property of the node.
506
+ * @param callback - The `callback` parameter is a function that takes a node as input and returns a
507
+ * value. This value is compared with the `identifier` parameter to determine if the node should be
508
+ * included in the result. The `callback` parameter has a default value of
509
+ * `this.defaultOneParamCallback`, which
510
+ * @param [onlyOne=false] - A boolean value indicating whether to stop searching after finding the
511
+ * first node that matches the identifier. If set to true, the function will return an array with
512
+ * only one element (or an empty array if no matching node is found). If set to false (default), the
513
+ * function will continue searching for all
514
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which the
515
+ * traversal of the binary tree will begin. It is optional and defaults to the root of the binary
516
+ * tree.
517
+ * @param iterationType - The `iterationType` parameter determines the type of iteration used to
518
+ * traverse the binary tree. It can have two possible values:
519
+ * @returns The function `getNodes` returns an array of nodes (`N[]`).
520
+ */
521
+ getNodes<C extends BTNCallback<N>>(
522
+ identifier: ReturnType<C> | null | undefined,
523
+ callback: C = this.defaultOneParamCallback as C,
524
+ onlyOne = false,
525
+ beginRoot: N | null | undefined = this.root,
526
+ iterationType = this.iterationType
527
+ ): N[] {
528
+ if (!beginRoot) return [];
529
+ if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
530
+ const ans: N[] = [];
531
+
532
+ if (iterationType === IterationType.RECURSIVE) {
533
+ const _traverse = (cur: N) => {
534
+ if (callback(cur) === identifier) {
535
+ ans.push(cur);
536
+ if (onlyOne) return;
537
+ }
538
+ if (!cur.left && !cur.right) return;
539
+ cur.left && _traverse(cur.left);
540
+ cur.right && _traverse(cur.right);
541
+ };
542
+
543
+ _traverse(beginRoot);
544
+ } else {
545
+ const queue = new Queue<N>([beginRoot]);
546
+ while (queue.size > 0) {
547
+ const cur = queue.shift();
548
+ if (cur) {
549
+ if (callback(cur) === identifier) {
550
+ ans.push(cur);
551
+ if (onlyOne) return ans;
552
+ }
553
+ cur.left && queue.push(cur.left);
554
+ cur.right && queue.push(cur.right);
555
+ }
556
+ }
557
+ }
558
+
559
+ return ans;
560
+ }
561
+
562
+ has<C extends BTNCallback<N, BTNKey>>(
563
+ identifier: BTNKey,
564
+ callback?: C,
565
+ beginRoot?: N | null | undefined,
566
+ iterationType?: IterationType
567
+ ): boolean;
568
+
569
+ has<C extends BTNCallback<N, N>>(
570
+ identifier: N | null | undefined,
571
+ callback?: C,
572
+ beginRoot?: N | null | undefined,
573
+ iterationType?: IterationType
574
+ ): boolean;
575
+
576
+ has<C extends BTNCallback<N>>(
577
+ identifier: ReturnType<C> | null | undefined,
578
+ callback: C,
579
+ beginRoot?: N | null | undefined,
580
+ iterationType?: IterationType
581
+ ): boolean;
582
+
583
+ /**
584
+ * The function checks if a binary tree has a node with a given property or key.
585
+ * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of
586
+ * the node that you want to find in the binary tree. It can be either a `BTNKey` or a
587
+ * generic type `N`.
588
+ * @param callback - The `callback` parameter is a function that is used to determine whether a node
589
+ * matches the desired criteria. It takes a node as input and returns a boolean value indicating
590
+ * whether the node matches the criteria or not. The default callback function
591
+ * `this.defaultOneParamCallback` is used if no callback function is
592
+ * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
593
+ * the node from which the search should begin. By default, it is set to `this.root`, which means the
594
+ * search will start from the root node of the binary tree. However, you can provide a different node
595
+ * as
596
+ * @param iterationType - The `iterationType` parameter specifies the type of iteration to be
597
+ * performed when searching for nodes in the binary tree. It can have one of the following values:
598
+ * @returns a boolean value.
599
+ */
600
+ has<C extends BTNCallback<N>>(
601
+ identifier: ReturnType<C> | null | undefined,
602
+ callback: C = this.defaultOneParamCallback as C,
603
+ beginRoot = this.root,
604
+ iterationType = this.iterationType
605
+ ): boolean {
606
+ if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
607
+
608
+ return this.getNodes(identifier, callback, true, beginRoot, iterationType).length > 0;
609
+ }
610
+
611
+ getNode<C extends BTNCallback<N, BTNKey>>(
612
+ identifier: BTNKey,
613
+ callback?: C,
614
+ beginRoot?: N | null | undefined,
615
+ iterationType?: IterationType
616
+ ): N | null | undefined;
617
+
618
+ getNode<C extends BTNCallback<N, N>>(
619
+ identifier: N | null | undefined,
620
+ callback?: C,
621
+ beginRoot?: N | null | undefined,
622
+ iterationType?: IterationType
623
+ ): N | null | undefined;
624
+
625
+ getNode<C extends BTNCallback<N>>(
626
+ identifier: ReturnType<C>,
627
+ callback: C,
628
+ beginRoot?: N | null | undefined,
629
+ iterationType?: IterationType
630
+ ): N | null | undefined;
631
+
632
+ /**
633
+ * The function `get` returns the first node in a binary tree that matches the given property or key.
634
+ * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of
635
+ * the node that you want to find in the binary tree. It can be either a `BTNKey` or `N`
636
+ * type.
637
+ * @param callback - The `callback` parameter is a function that is used to determine whether a node
638
+ * matches the desired criteria. It takes a node as input and returns a boolean value indicating
639
+ * whether the node matches the criteria or not. The default callback function
640
+ * (`this.defaultOneParamCallback`) is used if no callback function is
641
+ * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
642
+ * the root node from which the search should begin.
643
+ * @param iterationType - The `iterationType` parameter specifies the type of iteration to be
644
+ * performed when searching for a node in the binary tree. It can have one of the following values:
645
+ * @returns either the found node (of type N) or null if no node is found.
646
+ */
647
+ getNode<C extends BTNCallback<N>>(
648
+ identifier: ReturnType<C> | null | undefined,
649
+ callback: C = this.defaultOneParamCallback as C,
650
+ beginRoot = this.root,
651
+ iterationType = this.iterationType
652
+ ): N | null | undefined {
653
+ if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
654
+
655
+ return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
656
+ }
657
+
658
+ get<C extends BTNCallback<N, BTNKey>>(
659
+ identifier: BTNKey,
660
+ callback?: C,
661
+ beginRoot?: N | null | undefined,
662
+ iterationType?: IterationType
663
+ ): V | undefined;
664
+
665
+ get<C extends BTNCallback<N, N>>(
666
+ identifier: N | null | undefined,
667
+ callback?: C,
668
+ beginRoot?: N | null | undefined,
669
+ iterationType?: IterationType
670
+ ): V | undefined;
671
+
672
+ get<C extends BTNCallback<N>>(
673
+ identifier: ReturnType<C>,
674
+ callback: C,
675
+ beginRoot?: N | null | undefined,
676
+ iterationType?: IterationType
677
+ ): V | undefined;
678
+
679
+ /**
680
+ * The function `get` returns the first node value in a binary tree that matches the given property or key.
681
+ * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of
682
+ * the node that you want to find in the binary tree. It can be either a `BTNKey` or `N`
683
+ * type.
684
+ * @param callback - The `callback` parameter is a function that is used to determine whether a node
685
+ * matches the desired criteria. It takes a node as input and returns a boolean value indicating
686
+ * whether the node matches the criteria or not. The default callback function
687
+ * (`this.defaultOneParamCallback`) is used if no callback function is
688
+ * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
689
+ * the root node from which the search should begin.
690
+ * @param iterationType - The `iterationType` parameter specifies the type of iteration to be
691
+ * performed when searching for a node in the binary tree. It can have one of the following values:
692
+ * @returns either the found value (of type V) or undefined if no node value is found.
693
+ */
694
+ get<C extends BTNCallback<N>>(
695
+ identifier: ReturnType<C> | null | undefined,
696
+ callback: C = this.defaultOneParamCallback as C,
697
+ beginRoot = this.root,
698
+ iterationType = this.iterationType
699
+ ): V | undefined {
700
+ if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
701
+
702
+ return this.getNode(identifier, callback, beginRoot, iterationType)?.value ?? undefined;
703
+ }
704
+
705
+ /**
706
+ * The function `getPathToRoot` returns an array of nodes starting from a given node and traversing
707
+ * up to the root node, with the option to reverse the order of the nodes.
708
+ * @param {N} beginRoot - The `beginRoot` parameter represents the starting node from which you want
709
+ * to find the path to the root node.
710
+ * @param [isReverse=true] - The `isReverse` parameter is a boolean flag that determines whether the
711
+ * resulting path should be reversed or not. If `isReverse` is set to `true`, the path will be
712
+ * reversed before returning it. If `isReverse` is set to `false` or not provided, the path will
713
+ * @returns The function `getPathToRoot` returns an array of type `N[]`.
714
+ */
715
+ getPathToRoot(beginRoot: N, isReverse = true): N[] {
716
+ // TODO to support get path through passing key
717
+ const result: N[] = [];
718
+ while (beginRoot.parent) {
719
+ // Array.push + Array.reverse is more efficient than Array.unshift
720
+ // TODO may consider using Deque, so far this is not the performance bottleneck
721
+ result.push(beginRoot);
722
+ beginRoot = beginRoot.parent;
723
+ }
724
+ result.push(beginRoot);
725
+ return isReverse ? result.reverse() : result;
726
+ }
727
+
728
+ /**
729
+ * The function `getLeftMost` returns the leftmost node in a binary tree, either using recursive or
730
+ * iterative traversal.
731
+ * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
732
+ * for finding the leftmost node in a binary tree. It can be either a node object (`N`), a key value
733
+ * of a node (`BTNKey`), or `null` if the tree is empty.
734
+ * @param iterationType - The `iterationType` parameter is used to determine the type of iteration to
735
+ * be performed when finding the leftmost node in a binary tree. It can have two possible values:
736
+ * @returns The function `getLeftMost` returns the leftmost node (`N`) in a binary tree. If there is
737
+ * no leftmost node, it returns `null`.
738
+ */
739
+ getLeftMost(beginRoot: BTNKey | N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {
740
+ if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
741
+
742
+ if (!beginRoot) return beginRoot;
743
+
744
+ if (iterationType === IterationType.RECURSIVE) {
745
+ const _traverse = (cur: N): N => {
746
+ if (!cur.left) return cur;
747
+ return _traverse(cur.left);
748
+ };
749
+
750
+ return _traverse(beginRoot);
751
+ } else {
752
+ // Indirect implementation of iteration using tail recursion optimization
753
+ const _traverse = trampoline((cur: N) => {
754
+ if (!cur.left) return cur;
755
+ return _traverse.cont(cur.left);
756
+ });
757
+
758
+ return _traverse(beginRoot);
759
+ }
760
+ }
761
+
762
+ /**
763
+ * The function `getRightMost` returns the rightmost node in a binary tree, either recursively or
764
+ * iteratively.
765
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node from which we want to
766
+ * find the rightmost node. It is of type `N | null | undefined`, which means it can either be a node of type `N`
767
+ * or `null`. If it is `null`, it means there is no starting node
768
+ * @param iterationType - The `iterationType` parameter is used to determine the type of iteration to
769
+ * be performed when finding the rightmost node in a binary tree. It can have two possible values:
770
+ * @returns The function `getRightMost` returns the rightmost node (`N`) in a binary tree. If the
771
+ * `beginRoot` parameter is `null`, it returns `null`.
772
+ */
773
+ getRightMost(beginRoot: N | null | undefined = this.root, iterationType = this.iterationType): N | null | undefined {
774
+ // TODO support get right most by passing key in
775
+ if (!beginRoot) return beginRoot;
776
+
777
+ if (iterationType === IterationType.RECURSIVE) {
778
+ const _traverse = (cur: N): N => {
779
+ if (!cur.right) return cur;
780
+ return _traverse(cur.right);
781
+ };
782
+
783
+ return _traverse(beginRoot);
784
+ } else {
785
+ // Indirect implementation of iteration using tail recursion optimization
786
+ const _traverse = trampoline((cur: N) => {
787
+ if (!cur.right) return cur;
788
+ return _traverse.cont(cur.right);
789
+ });
790
+
791
+ return _traverse(beginRoot);
792
+ }
793
+ }
794
+
795
+ /**
796
+ * The function `isSubtreeBST` checks if a given binary tree is a valid binary search tree.
797
+ * @param {N} beginRoot - The `beginRoot` parameter is the root node of the binary tree that you want
798
+ * to check if it is a binary search tree (BST) subtree.
799
+ * @param iterationType - The `iterationType` parameter is an optional parameter that specifies the
800
+ * type of iteration to use when checking if a subtree is a binary search tree (BST). It can have two
801
+ * possible values:
802
+ * @returns The function `isSubtreeBST` returns a boolean value.
803
+ */
804
+ isSubtreeBST(beginRoot: N | null | undefined, iterationType = this.iterationType): boolean {
805
+ // TODO there is a bug
806
+ if (!beginRoot) return true;
807
+
808
+ if (iterationType === IterationType.RECURSIVE) {
809
+ const dfs = (cur: N | null | undefined, min: BTNKey, max: BTNKey): boolean => {
810
+ if (!cur) return true;
811
+ if (cur.key <= min || cur.key >= max) return false;
812
+ return dfs(cur.left, min, cur.key) && dfs(cur.right, cur.key, max);
813
+ };
814
+
815
+ return dfs(beginRoot, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
816
+ } else {
817
+ const stack = [];
818
+ let prev = Number.MIN_SAFE_INTEGER,
819
+ curr: N | null | undefined = beginRoot;
820
+ while (curr || stack.length > 0) {
821
+ while (curr) {
822
+ stack.push(curr);
823
+ curr = curr.left;
824
+ }
825
+ curr = stack.pop()!;
826
+ if (!curr || prev >= curr.key) return false;
827
+ prev = curr.key;
828
+ curr = curr.right;
829
+ }
830
+ return true;
831
+ }
832
+ }
833
+
834
+ /**
835
+ * The function checks if a binary tree is a binary search tree.
836
+ * @param iterationType - The parameter "iterationType" is used to specify the type of iteration to
837
+ * be used when checking if the binary tree is a binary search tree (BST). It is an optional
838
+ * parameter with a default value of "this.iterationType". The value of "this.iterationType" is not
839
+ * provided in
840
+ * @returns a boolean value.
841
+ */
842
+ isBST(iterationType = this.iterationType): boolean {
843
+ if (this.root === null) return true;
844
+ return this.isSubtreeBST(this.root, iterationType);
845
+ }
846
+
847
+ subTreeTraverse<C extends BTNCallback<N>>(
848
+ callback?: C,
849
+ beginRoot?: BTNKey | N | null | undefined,
850
+ iterationType?: IterationType,
851
+ includeNull?: false
852
+ ): ReturnType<C>[];
853
+
854
+ subTreeTraverse<C extends BTNCallback<N>>(
855
+ callback?: C,
856
+ beginRoot?: BTNKey | N | null | undefined,
857
+ iterationType?: IterationType,
858
+ includeNull?: undefined
859
+ ): ReturnType<C>[];
860
+
861
+ subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
862
+ callback?: C,
863
+ beginRoot?: BTNKey | N | null | undefined,
864
+ iterationType?: IterationType,
865
+ includeNull?: true
866
+ ): ReturnType<C>[];
867
+
868
+ /**
869
+ * The function `subTreeTraverse` traverses a binary tree and applies a callback function to each
870
+ * node, either recursively or iteratively.
871
+ * @param callback - The `callback` parameter is a function that will be called on each node in the
872
+ * subtree traversal. It takes a single argument, which is the current node being traversed, and
873
+ * returns a value. The return values from each callback invocation will be collected and returned as
874
+ * an array.
875
+ * @param {BTNKey | N | null | undefined} beginRoot - The `beginRoot` parameter is the starting point
876
+ * for traversing the subtree. It can be either a node object, a key value of a node, or `null` to
877
+ * start from the root of the tree.
878
+ * @param iterationType - The `iterationType` parameter determines the type of traversal to be
879
+ * performed on the binary tree. It can have two possible values:
880
+ * @param includeNull - The choice to output null values during binary tree traversal should be provided.
881
+ * @returns The function `subTreeTraverse` returns an array of `ReturnType<BTNCallback<N>>`.
882
+ */
883
+ subTreeTraverse<C extends BTNCallback<N | null | undefined>>(
884
+ callback: C = this.defaultOneParamCallback as C,
885
+ beginRoot: BTNKey | N | null | undefined = this.root,
886
+ iterationType = this.iterationType,
887
+ includeNull = false
888
+ ): ReturnType<C>[] {
889
+ if (typeof beginRoot === 'number') beginRoot = this.getNode(beginRoot);
890
+
891
+ const ans: (ReturnType<BTNCallback<N>> | null | undefined)[] = [];
892
+ if (!beginRoot) return ans;
893
+
894
+ if (iterationType === IterationType.RECURSIVE) {
895
+ const _traverse = (cur: N | null | undefined) => {
896
+ if (cur !== undefined) {
897
+ ans.push(callback(cur));
898
+ if (includeNull) {
899
+ cur && this.isNodeOrNull(cur.left) && _traverse(cur.left);
900
+ cur && this.isNodeOrNull(cur.right) && _traverse(cur.right);
901
+ } else {
902
+ cur && cur.left && _traverse(cur.left);
903
+ cur && cur.right && _traverse(cur.right);
904
+ }
905
+ }
906
+ };
907
+
908
+ _traverse(beginRoot);
909
+ } else {
910
+ const stack: (N | null | undefined)[] = [beginRoot];
911
+
912
+ while (stack.length > 0) {
913
+ const cur = stack.pop();
914
+ if (cur !== undefined) {
915
+ ans.push(callback(cur));
916
+ if (includeNull) {
917
+ cur && this.isNodeOrNull(cur.right) && stack.push(cur.right);
918
+ cur && this.isNodeOrNull(cur.left) && stack.push(cur.left);
919
+ } else {
920
+ cur && cur.right && stack.push(cur.right);
921
+ cur && cur.left && stack.push(cur.left);
922
+ }
923
+ }
924
+ }
925
+ }
926
+ return ans;
927
+ }
928
+
929
+ isNode(node: any): node is N {
930
+ return node instanceof BinaryTreeNode && node.key.toString() !== 'NaN';
931
+ }
932
+
933
+ isNIL(node: any) {
934
+ return node instanceof BinaryTreeNode && node.key.toString() === 'NaN';
935
+ }
936
+
937
+ isNodeOrNull(node: any): node is (N | null){
938
+ return this.isNode(node) || node === null;
939
+ }
940
+
941
+ dfs<C extends BTNCallback<N>>(
942
+ callback?: C,
943
+ pattern?: DFSOrderPattern,
944
+ beginRoot?: N | null | undefined,
945
+ iterationType?: IterationType,
946
+ includeNull?: false
947
+ ): ReturnType<C>[];
948
+
949
+ dfs<C extends BTNCallback<N>>(
950
+ callback?: C,
951
+ pattern?: DFSOrderPattern,
952
+ beginRoot?: N | null | undefined,
953
+ iterationType?: IterationType,
954
+ includeNull?: undefined
955
+ ): ReturnType<C>[];
956
+
957
+ dfs<C extends BTNCallback<N | null | undefined>>(
958
+ callback?: C,
959
+ pattern?: DFSOrderPattern,
960
+ beginRoot?: N | null | undefined,
961
+ iterationType?: IterationType,
962
+ includeNull?: true
963
+ ): ReturnType<C>[];
964
+
965
+ /**
966
+ * The `dfs` function performs a depth-first search traversal on a binary tree, executing a callback
967
+ * function on each node according to a specified order pattern.
968
+ * @param callback - The `callback` parameter is a function that will be called on each node during
969
+ * the depth-first search traversal. It takes a node as input and returns a value. The default value
970
+ * is `this.defaultOneParamCallback`, which is a callback function defined elsewhere in the code.
971
+ * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter determines the order in which the
972
+ * nodes are visited during the depth-first search. There are three possible values for `pattern`:
973
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the depth-first
974
+ * search. It determines where the search will begin in the tree or graph structure. If `beginRoot`
975
+ * is `null`, an empty array will be returned.
976
+ * @param {IterationType} iterationType - The `iterationType` parameter determines the type of
977
+ * iteration used in the depth-first search algorithm. It can have two possible values:
978
+ * @param includeNull - The choice to output null values during binary tree traversal should be provided.
979
+ * @returns The function `dfs` returns an array of `ReturnType<BTNCallback<N>>` values.
980
+ */
981
+ dfs<C extends BTNCallback<N | null | undefined>>(
982
+ callback: C = this.defaultOneParamCallback as C,
983
+ pattern: DFSOrderPattern = 'in',
984
+ beginRoot: N | null | undefined = this.root,
985
+ iterationType: IterationType = IterationType.ITERATIVE,
986
+ includeNull = false
987
+ ): ReturnType<C>[] {
988
+ if (!beginRoot) return [];
989
+ const ans: ReturnType<C>[] = [];
990
+ if (iterationType === IterationType.RECURSIVE) {
991
+ const _traverse = (node: N | null | undefined) => {
992
+ switch (pattern) {
993
+ case 'in':
994
+ if (includeNull) {
995
+ if (node && this.isNodeOrNull(node.left)) _traverse(node.left);
996
+ this.isNodeOrNull(node) && ans.push(callback(node));
997
+ if (node && this.isNodeOrNull(node.right)) _traverse(node.right);
998
+ } else {
999
+ if (node && node.left) _traverse(node.left);
1000
+ this.isNode(node) && ans.push(callback(node));
1001
+ if (node && node.right) _traverse(node.right);
1002
+ }
1003
+ break;
1004
+ case 'pre':
1005
+ if (includeNull) {
1006
+ this.isNodeOrNull(node) && ans.push(callback(node));
1007
+ if (node && this.isNodeOrNull(node.left)) _traverse(node.left);
1008
+ if (node && this.isNodeOrNull(node.right)) _traverse(node.right);
1009
+ } else {
1010
+ this.isNode(node) && ans.push(callback(node));
1011
+ if (node && node.left) _traverse(node.left);
1012
+ if (node && node.right) _traverse(node.right);
1013
+ }
1014
+ break;
1015
+ case 'post':
1016
+ if (includeNull) {
1017
+ if (node && this.isNodeOrNull(node.left)) _traverse(node.left);
1018
+ if (node && this.isNodeOrNull(node.right)) _traverse(node.right);
1019
+ this.isNodeOrNull(node) && ans.push(callback(node));
1020
+ } else {
1021
+ if (node && node.left) _traverse(node.left);
1022
+ if (node && node.right) _traverse(node.right);
1023
+ this.isNode(node) && ans.push(callback(node));
1024
+ }
1025
+
1026
+ break;
1027
+ }
1028
+ };
1029
+
1030
+ _traverse(beginRoot);
1031
+ } else {
1032
+ // 0: visit, 1: print
1033
+ const stack: {opt: 0 | 1; node: N | null | undefined}[] = [{opt: 0, node: beginRoot}];
1034
+
1035
+ while (stack.length > 0) {
1036
+ const cur = stack.pop();
1037
+ if (cur === undefined || this.isNIL(cur.node)) continue;
1038
+ if (includeNull) {
1039
+ if (cur.node === undefined) continue;
1040
+ } else {
1041
+ if (cur.node === null || cur.node === undefined) continue;
1042
+ }
1043
+ if (cur.opt === 1) {
1044
+ ans.push(callback(cur.node));
1045
+ } else {
1046
+ switch (pattern) {
1047
+ case 'in':
1048
+ cur.node && stack.push({opt: 0, node: cur.node.right});
1049
+ stack.push({opt: 1, node: cur.node});
1050
+ cur.node && stack.push({opt: 0, node: cur.node.left});
1051
+ break;
1052
+ case 'pre':
1053
+ cur.node && stack.push({opt: 0, node: cur.node.right});
1054
+ cur.node && stack.push({opt: 0, node: cur.node.left});
1055
+ stack.push({opt: 1, node: cur.node});
1056
+ break;
1057
+ case 'post':
1058
+ stack.push({opt: 1, node: cur.node});
1059
+ cur.node && stack.push({opt: 0, node: cur.node.right});
1060
+ cur.node && stack.push({opt: 0, node: cur.node.left});
1061
+ break;
1062
+ default:
1063
+ cur.node && stack.push({opt: 0, node: cur.node.right});
1064
+ stack.push({opt: 1, node: cur.node});
1065
+ cur.node && stack.push({opt: 0, node: cur.node.left});
1066
+ break;
1067
+ }
1068
+ }
1069
+ }
1070
+ }
1071
+
1072
+ return ans;
1073
+ }
1074
+
1075
+ bfs<C extends BTNCallback<N>>(
1076
+ callback?: C,
1077
+ beginRoot?: N | null | undefined,
1078
+ iterationType?: IterationType,
1079
+ includeNull?: false
1080
+ ): ReturnType<C>[];
1081
+
1082
+ bfs<C extends BTNCallback<N>>(
1083
+ callback?: C,
1084
+ beginRoot?: N | null | undefined,
1085
+ iterationType?: IterationType,
1086
+ includeNull?: undefined
1087
+ ): ReturnType<C>[];
1088
+
1089
+ bfs<C extends BTNCallback<N | null | undefined>>(
1090
+ callback?: C,
1091
+ beginRoot?: N | null | undefined,
1092
+ iterationType?: IterationType,
1093
+ includeNull?: true
1094
+ ): ReturnType<C>[];
1095
+
1096
+ /**
1097
+ * The bfs function performs a breadth-first search traversal on a binary tree, executing a callback
1098
+ * function on each node.
1099
+ * @param callback - The `callback` parameter is a function that will be called for each node in the
1100
+ * breadth-first search. It takes a node of type `N` as its argument and returns a value of type
1101
+ * `ReturnType<BTNCallback<N>>`. The default value for this parameter is `this.defaultOneParamCallback
1102
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the breadth-first
1103
+ * search. It determines from which node the search will begin. If `beginRoot` is `null`, the search
1104
+ * will not be performed and an empty array will be returned.
1105
+ * @param iterationType - The `iterationType` parameter determines the type of iteration to be used
1106
+ * in the breadth-first search (BFS) algorithm. It can have two possible values:
1107
+ * @param includeNull - The choice to output null values during binary tree traversal should be provided.
1108
+ * @returns The function `bfs` returns an array of `ReturnType<BTNCallback<N>>[]`.
1109
+ */
1110
+ bfs<C extends BTNCallback<N | null | undefined>>(
1111
+ callback: C = this.defaultOneParamCallback as C,
1112
+ beginRoot: N | null | undefined = this.root,
1113
+ iterationType = this.iterationType,
1114
+ includeNull = false
1115
+ ): ReturnType<C>[] {
1116
+ if (!beginRoot) return [];
1117
+
1118
+ const ans: ReturnType<BTNCallback<N>>[] = [];
1119
+
1120
+ if (iterationType === IterationType.RECURSIVE) {
1121
+ const queue: Queue<N | null | undefined> = new Queue<N | null | undefined>([beginRoot]);
1122
+
1123
+ const traverse = (level: number) => {
1124
+ if (queue.size === 0) return;
1125
+
1126
+ const current = queue.shift()!;
1127
+ ans.push(callback(current));
1128
+
1129
+ if (includeNull) {
1130
+ if (current && this.isNodeOrNull(current.left)) queue.push(current.left);
1131
+ if (current && this.isNodeOrNull(current.right)) queue.push(current.right);
1132
+ } else {
1133
+ if (current.left) queue.push(current.left);
1134
+ if (current.right) queue.push(current.right);
1135
+ }
1136
+
1137
+ traverse(level + 1);
1138
+ };
1139
+
1140
+ traverse(0);
1141
+ } else {
1142
+ const queue = new Queue<N | null | undefined>([beginRoot]);
1143
+ while (queue.size > 0) {
1144
+ const levelSize = queue.size;
1145
+
1146
+ for (let i = 0; i < levelSize; i++) {
1147
+ const current = queue.shift()!;
1148
+ ans.push(callback(current));
1149
+
1150
+ if (includeNull) {
1151
+ if (current && this.isNodeOrNull(current.left)) queue.push(current.left);
1152
+ if (current && this.isNodeOrNull(current.right)) queue.push(current.right);
1153
+ } else {
1154
+ if (current.left) queue.push(current.left);
1155
+ if (current.right) queue.push(current.right);
1156
+ }
1157
+ }
1158
+ }
1159
+ }
1160
+ return ans;
1161
+ }
1162
+
1163
+ listLevels<C extends BTNCallback<N>>(
1164
+ callback?: C,
1165
+ beginRoot?: N | null | undefined,
1166
+ iterationType?: IterationType,
1167
+ includeNull?: false
1168
+ ): ReturnType<C>[][];
1169
+
1170
+ listLevels<C extends BTNCallback<N>>(
1171
+ callback?: C,
1172
+ beginRoot?: N | null | undefined,
1173
+ iterationType?: IterationType,
1174
+ includeNull?: undefined
1175
+ ): ReturnType<C>[][];
1176
+
1177
+ listLevels<C extends BTNCallback<N | null | undefined>>(
1178
+ callback?: C,
1179
+ beginRoot?: N | null | undefined,
1180
+ iterationType?: IterationType,
1181
+ includeNull?: true
1182
+ ): ReturnType<C>[][];
1183
+
1184
+ /**
1185
+ * The `listLevels` function takes a binary tree node and a callback function, and returns an array
1186
+ * of arrays representing the levels of the tree.
1187
+ * @param {C} callback - The `callback` parameter is a function that will be called on each node in
1188
+ * the tree. It takes a node as input and returns a value. The return type of the callback function
1189
+ * is determined by the generic type `C`.
1190
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter represents the starting node of the binary tree
1191
+ * traversal. It can be any node in the binary tree. If no node is provided, the traversal will start
1192
+ * from the root node of the binary tree.
1193
+ * @param iterationType - The `iterationType` parameter determines whether the tree traversal is done
1194
+ * recursively or iteratively. It can have two possible values:
1195
+ * @param includeNull - The choice to output null values during binary tree traversal should be provided.
1196
+ * @returns The function `listLevels` returns an array of arrays, where each inner array represents a
1197
+ * level in a binary tree. Each inner array contains the return type of the provided callback
1198
+ * function `C` applied to the nodes at that level.
1199
+ */
1200
+ listLevels<C extends BTNCallback<N | null | undefined>>(
1201
+ callback: C = this.defaultOneParamCallback as C,
1202
+ beginRoot: N | null | undefined = this.root,
1203
+ iterationType = this.iterationType,
1204
+ includeNull = false
1205
+ ): ReturnType<C>[][] {
1206
+ if (!beginRoot) return [];
1207
+ const levelsNodes: ReturnType<C>[][] = [];
1208
+
1209
+ if (iterationType === IterationType.RECURSIVE) {
1210
+ const _recursive = (node: N | null | undefined, level: number) => {
1211
+ if (!levelsNodes[level]) levelsNodes[level] = [];
1212
+ levelsNodes[level].push(callback(node));
1213
+ if (includeNull) {
1214
+ if (node && this.isNodeOrNull(node.left)) _recursive(node.left, level + 1);
1215
+ if (node && this.isNodeOrNull(node.right)) _recursive(node.right, level + 1);
1216
+ } else {
1217
+ if (node && node.left) _recursive(node.left, level + 1);
1218
+ if (node && node.right) _recursive(node.right, level + 1);
1219
+ }
1220
+ };
1221
+
1222
+ _recursive(beginRoot, 0);
1223
+ } else {
1224
+ const stack: [N | null | undefined, number][] = [[beginRoot, 0]];
1225
+
1226
+ while (stack.length > 0) {
1227
+ const head = stack.pop()!;
1228
+ const [node, level] = head;
1229
+
1230
+ if (!levelsNodes[level]) levelsNodes[level] = [];
1231
+ levelsNodes[level].push(callback(node));
1232
+
1233
+ if (includeNull) {
1234
+ if (node && this.isNodeOrNull(node.right)) stack.push([node.right, level + 1]);
1235
+ if (node && this.isNodeOrNull(node.left)) stack.push([node.left, level + 1]);
1236
+ } else {
1237
+ if (node && node.right) stack.push([node.right, level + 1]);
1238
+ if (node && node.left) stack.push([node.left, level + 1]);
1239
+ }
1240
+ }
1241
+ }
1242
+
1243
+ return levelsNodes;
1244
+ }
1245
+
1246
+ /**
1247
+ * The function returns the predecessor node of a given node in a binary tree.
1248
+ * @param {N} node - The parameter "node" represents a node in a binary tree.
1249
+ * @returns The function `getPredecessor` returns the predecessor node of the given node `node`.
1250
+ */
1251
+ getPredecessor(node: N): N {
1252
+ if (node.left) {
1253
+ let predecessor: N | null | undefined = node.left;
1254
+ while (!predecessor || (predecessor.right && predecessor.right !== node)) {
1255
+ if (predecessor) {
1256
+ predecessor = predecessor.right;
1257
+ }
1258
+ }
1259
+ return predecessor;
1260
+ } else {
1261
+ return node;
1262
+ }
1263
+ }
1264
+
1265
+ /**
1266
+ * The function `getSuccessor` returns the next node in a binary tree given a node `x`, or `null` if
1267
+ * `x` is the last node.
1268
+ * @param {N} x - N - a node in a binary tree
1269
+ * @returns The function `getSuccessor` returns a value of type `N` (the successor node), or `null`
1270
+ * if there is no successor, or `undefined` if the input `x` is `undefined`.
1271
+ */
1272
+ getSuccessor(x: N): N | null | undefined {
1273
+ if (x.right) {
1274
+ return this.getLeftMost(x.right);
1275
+ }
1276
+
1277
+ let y: N | null | undefined = x.parent;
1278
+ while (y && y && x === y.right) {
1279
+ x = y;
1280
+ y = y.parent;
1281
+ }
1282
+ return y;
1283
+ }
1284
+
1285
+ /**
1286
+ * The `morris` function performs a depth-first traversal of a binary tree using the Morris traversal
1287
+ * algorithm and returns an array of values obtained by applying a callback function to each node.
1288
+ * @param callback - The `callback` parameter is a function that will be called on each node in the
1289
+ * tree. It takes a node of type `N` as input and returns a value of type `ReturnType<BTNCallback<N>>`. The
1290
+ * default value for this parameter is `this.defaultOneParamCallback`.
1291
+ * @param {DFSOrderPattern} [pattern=in] - The `pattern` parameter in the `morris` function
1292
+ * determines the order in which the nodes of a binary tree are traversed. It can have one of the
1293
+ * following values:
1294
+ * @param {N | null | undefined} beginRoot - The `beginRoot` parameter is the starting node for the Morris
1295
+ * traversal. It specifies the root node of the tree from which the traversal should begin. If
1296
+ * `beginRoot` is `null`, an empty array will be returned.
1297
+ * @returns The `morris` function returns an array of `ReturnType<BTNCallback<N>>` values.
1298
+ */
1299
+ morris<C extends BTNCallback<N>>(
1300
+ callback: C = this.defaultOneParamCallback as C,
1301
+ pattern: DFSOrderPattern = 'in',
1302
+ beginRoot: N | null | undefined = this.root
1303
+ ): ReturnType<C>[] {
1304
+ if (beginRoot === null) return [];
1305
+ const ans: ReturnType<BTNCallback<N>>[] = [];
1306
+
1307
+ let cur: N | null | undefined = beginRoot;
1308
+ const _reverseEdge = (node: N | null | undefined) => {
1309
+ let pre: N | null | undefined = null;
1310
+ let next: N | null | undefined = null;
1311
+ while (node) {
1312
+ next = node.right;
1313
+ node.right = pre;
1314
+ pre = node;
1315
+ node = next;
1316
+ }
1317
+ return pre;
1318
+ };
1319
+ const _printEdge = (node: N | null | undefined) => {
1320
+ const tail: N | null | undefined = _reverseEdge(node);
1321
+ let cur: N | null | undefined = tail;
1322
+ while (cur) {
1323
+ ans.push(callback(cur));
1324
+ cur = cur.right;
1325
+ }
1326
+ _reverseEdge(tail);
1327
+ };
1328
+ switch (pattern) {
1329
+ case 'in':
1330
+ while (cur) {
1331
+ if (cur.left) {
1332
+ const predecessor = this.getPredecessor(cur);
1333
+ if (!predecessor.right) {
1334
+ predecessor.right = cur;
1335
+ cur = cur.left;
1336
+ continue;
1337
+ } else {
1338
+ predecessor.right = null;
1339
+ }
1340
+ }
1341
+ ans.push(callback(cur));
1342
+ cur = cur.right;
1343
+ }
1344
+ break;
1345
+ case 'pre':
1346
+ while (cur) {
1347
+ if (cur.left) {
1348
+ const predecessor = this.getPredecessor(cur);
1349
+ if (!predecessor.right) {
1350
+ predecessor.right = cur;
1351
+ ans.push(callback(cur));
1352
+ cur = cur.left;
1353
+ continue;
1354
+ } else {
1355
+ predecessor.right = null;
1356
+ }
1357
+ } else {
1358
+ ans.push(callback(cur));
1359
+ }
1360
+ cur = cur.right;
1361
+ }
1362
+ break;
1363
+ case 'post':
1364
+ while (cur) {
1365
+ if (cur.left) {
1366
+ const predecessor = this.getPredecessor(cur);
1367
+ if (predecessor.right === null) {
1368
+ predecessor.right = cur;
1369
+ cur = cur.left;
1370
+ continue;
1371
+ } else {
1372
+ predecessor.right = null;
1373
+ _printEdge(cur.left);
1374
+ }
1375
+ }
1376
+ cur = cur.right;
1377
+ }
1378
+ _printEdge(beginRoot);
1379
+ break;
1380
+ }
1381
+ return ans;
1382
+ }
1383
+
1384
+ // --- start additional methods ---
1385
+
1386
+ /**
1387
+ * The above function is an iterator for a binary tree that can be used to traverse the tree in
1388
+ * either an iterative or recursive manner.
1389
+ * @param node - The `node` parameter represents the current node in the binary tree from which the
1390
+ * iteration starts. It is an optional parameter with a default value of `this.root`, which means
1391
+ * that if no node is provided, the iteration will start from the root of the binary tree.
1392
+ * @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the
1393
+ * binary tree nodes in a specific order.
1394
+ */
1395
+ *[Symbol.iterator](node = this.root): Generator<BTNKey, void, undefined> {
1396
+ if (!node) {
1397
+ return;
1398
+ }
1399
+
1400
+ if (this.iterationType === IterationType.ITERATIVE) {
1401
+ const stack: (N | null | undefined)[] = [];
1402
+ let current: N | null | undefined = node;
1403
+
1404
+ while (current || stack.length > 0) {
1405
+ while (current) {
1406
+ stack.push(current);
1407
+ current = current.left;
1408
+ }
1409
+
1410
+ current = stack.pop();
1411
+
1412
+ if (current) yield current.key;
1413
+ if (current) current = current.right;
1414
+ }
1415
+ } else {
1416
+ if (node.left) {
1417
+ // @ts-ignore
1418
+ yield* this[Symbol.iterator](node.left);
1419
+ }
1420
+ yield node.key;
1421
+ if (node.right) {
1422
+ // @ts-ignore
1423
+ yield* this[Symbol.iterator](node.right);
1424
+ }
1425
+ }
1426
+ }
1427
+
1428
+ protected defaultOneParamCallback = (node: N) => node.key;
1429
+
1430
+ /**
1431
+ * Swap the data of two nodes in the binary tree.
1432
+ * @param {N} srcNode - The source node to swap.
1433
+ * @param {N} destNode - The destination node to swap.
1434
+ * @returns {N} - The destination node after the swap.
1435
+ */
1436
+ protected _swap(srcNode: N, destNode: N): N {
1437
+ const {key, value} = destNode;
1438
+ const tempNode = this.createNode(key, value);
1439
+
1440
+ if (tempNode) {
1441
+ destNode.key = srcNode.key;
1442
+ destNode.value = srcNode.value;
1443
+
1444
+ srcNode.key = tempNode.key;
1445
+ srcNode.value = tempNode.value;
1446
+ }
1447
+
1448
+ return destNode;
1449
+ }
1450
+
1451
+ /**
1452
+ * The function `_addTo` adds a new node to a binary tree if there is an available position.
1453
+ * @param {N | null | undefined} newNode - The `newNode` parameter represents the node that you want to add to
1454
+ * the binary tree. It can be either a node object or `null`.
1455
+ * @param {N} parent - The `parent` parameter represents the parent node to which the new node will
1456
+ * be added as a child.
1457
+ * @returns either the left or right child node of the parent node, depending on which child is
1458
+ * available for adding the new node. If a new node is added, the function also updates the size of
1459
+ * the binary tree. If neither the left nor right child is available, the function returns undefined.
1460
+ * If the parent node is null, the function also returns undefined.
1461
+ */
1462
+ protected _addTo(newNode: N | null | undefined, parent: N): N | null | undefined {
1463
+ if (parent) {
1464
+ // When all leaf nodes are null, it will no longer be possible to add new entity nodes to this binary tree.
1465
+ // In this scenario, null nodes serve as "sentinel nodes," "virtual nodes," or "placeholder nodes."
1466
+ if (parent.left === undefined) {
1467
+ parent.left = newNode;
1468
+ if (newNode) {
1469
+ this._size = this.size + 1;
1470
+ }
1471
+ return parent.left;
1472
+ } else if (parent.right === undefined) {
1473
+ parent.right = newNode;
1474
+ if (newNode) {
1475
+ this._size = this.size + 1;
1476
+ }
1477
+ return parent.right;
1478
+ } else {
1479
+ return;
1480
+ }
1481
+ } else {
1482
+ return;
1483
+ }
1484
+ }
1485
+
1486
+ /**
1487
+ * The function sets the root property of an object to a given value, and if the value is not null,
1488
+ * it also sets the parent property of the value to undefined.
1489
+ * @param {N | null | undefined} v - The parameter `v` is of type `N | null | undefined`, which means it can either be of
1490
+ * type `N` or `null`.
1491
+ */
1492
+ protected _setRoot(v: N | null | undefined) {
1493
+ if (v) {
1494
+ v.parent = undefined;
1495
+ }
1496
+ this._root = v;
1497
+ }
1498
+
1499
+ print(beginRoot: N | null | undefined = this.root) {
1500
+ const display = (root: N | null | undefined): void => {
1501
+ const [lines, , ,] = _displayAux(root);
1502
+ for (const line of lines) {
1503
+ console.log(line);
1504
+ }
1505
+ };
1506
+
1507
+ const _displayAux = (node: N | null | undefined): [string[], number, number, number] => {
1508
+ if (node === undefined || node === null) {
1509
+ return [[], 0, 0, 0];
1510
+ }
1511
+
1512
+ if (node && node.right === undefined && node.left === undefined) {
1513
+ const line = `${node.key}`;
1514
+ const width = line.length;
1515
+ const height = 1;
1516
+ const middle = Math.floor(width / 2);
1517
+ return [[line], width, height, middle];
1518
+ }
1519
+
1520
+ if (node && node.right === undefined) {
1521
+ const [lines, n, p, x] = _displayAux(node.left);
1522
+ const s = `${node.key}`;
1523
+ const u = s.length;
1524
+ const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s;
1525
+ const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u);
1526
+ const shifted_lines = lines.map(line => line + ' '.repeat(u));
1527
+ return [[first_line, second_line, ...shifted_lines], n + u, p + 2, n + Math.floor(u / 2)];
1528
+ }
1529
+
1530
+ if (node && node.left === undefined) {
1531
+ const [lines, n, p, u] = _displayAux(node.right);
1532
+ const s = `${node.key}`;
1533
+ const x = s.length;
1534
+ const first_line = s + '_'.repeat(x) + ' '.repeat(n - x);
1535
+ const second_line = ' '.repeat(u + x) + '\\' + ' '.repeat(n - x - 1);
1536
+ const shifted_lines = lines.map(line => ' '.repeat(u) + line);
1537
+ return [[first_line, second_line, ...shifted_lines], n + x, p + 2, Math.floor(u / 2)];
1538
+ }
1539
+
1540
+ const [left, n, p, x] = _displayAux(node.left);
1541
+ const [right, m, q, y] = _displayAux(node.right);
1542
+ const s = `${node.key}`;
1543
+ const u = s.length;
1544
+ const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s + '_'.repeat(y) + ' '.repeat(m - y);
1545
+ const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u + y) + '\\' + ' '.repeat(m - y - 1);
1546
+ if (p < q) {
1547
+ left.push(...new Array(q - p).fill(' '.repeat(n)));
1548
+ } else if (q < p) {
1549
+ right.push(...new Array(p - q).fill(' '.repeat(m)));
1550
+ }
1551
+ const zipped_lines = left.map((a, i) => a + ' '.repeat(u) + right[i]);
1552
+ return [[first_line, second_line, ...zipped_lines], n + m + u, Math.max(p, q) + 2, n + Math.floor(u / 2)];
1553
+ };
1554
+
1555
+ display(beginRoot);
1556
+ }
1557
+ // --- end additional methods ---
1558
+ }