tree-set-typed 2.3.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 (273) hide show
  1. package/.eslintrc.js +61 -0
  2. package/.prettierignore +6 -0
  3. package/.prettierrc.js +16 -0
  4. package/LICENSE +21 -0
  5. package/README.md +482 -0
  6. package/coverage/clover.xml +13 -0
  7. package/coverage/coverage-final.json +96 -0
  8. package/coverage/coverage-summary.json +60 -0
  9. package/coverage/lcov-report/base.css +403 -0
  10. package/coverage/lcov-report/block-navigation.js +87 -0
  11. package/coverage/lcov-report/favicon.png +0 -0
  12. package/coverage/lcov-report/index.html +119 -0
  13. package/coverage/lcov-report/index.ts.html +109 -0
  14. package/coverage/lcov-report/prettify.css +1 -0
  15. package/coverage/lcov-report/prettify.js +2 -0
  16. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  17. package/coverage/lcov-report/sorter.js +206 -0
  18. package/coverage/lcov.info +14 -0
  19. package/dist/cjs/index.cjs +12 -0
  20. package/dist/cjs/index.cjs.map +1 -0
  21. package/dist/cjs-legacy/index.cjs +12 -0
  22. package/dist/cjs-legacy/index.cjs.map +1 -0
  23. package/dist/esm/index.mjs +3 -0
  24. package/dist/esm/index.mjs.map +1 -0
  25. package/dist/esm-legacy/index.mjs +3 -0
  26. package/dist/esm-legacy/index.mjs.map +1 -0
  27. package/dist/types/common/index.d.ts +12 -0
  28. package/dist/types/constants/index.d.ts +4 -0
  29. package/dist/types/data-structures/base/index.d.ts +2 -0
  30. package/dist/types/data-structures/base/iterable-element-base.d.ts +219 -0
  31. package/dist/types/data-structures/base/iterable-entry-base.d.ts +150 -0
  32. package/dist/types/data-structures/base/linear-base.d.ts +335 -0
  33. package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +236 -0
  34. package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +197 -0
  35. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +440 -0
  36. package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +174 -0
  37. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +807 -0
  38. package/dist/types/data-structures/binary-tree/bst.d.ts +645 -0
  39. package/dist/types/data-structures/binary-tree/index.d.ts +10 -0
  40. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +312 -0
  41. package/dist/types/data-structures/binary-tree/segment-tree.d.ts +160 -0
  42. package/dist/types/data-structures/binary-tree/tree-counter.d.ts +243 -0
  43. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +333 -0
  44. package/dist/types/data-structures/graph/abstract-graph.d.ts +340 -0
  45. package/dist/types/data-structures/graph/directed-graph.d.ts +332 -0
  46. package/dist/types/data-structures/graph/index.d.ts +4 -0
  47. package/dist/types/data-structures/graph/map-graph.d.ts +78 -0
  48. package/dist/types/data-structures/graph/undirected-graph.d.ts +347 -0
  49. package/dist/types/data-structures/hash/hash-map.d.ts +428 -0
  50. package/dist/types/data-structures/hash/index.d.ts +1 -0
  51. package/dist/types/data-structures/heap/heap.d.ts +552 -0
  52. package/dist/types/data-structures/heap/index.d.ts +3 -0
  53. package/dist/types/data-structures/heap/max-heap.d.ts +32 -0
  54. package/dist/types/data-structures/heap/min-heap.d.ts +33 -0
  55. package/dist/types/data-structures/index.d.ts +12 -0
  56. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +437 -0
  57. package/dist/types/data-structures/linked-list/index.d.ts +3 -0
  58. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +567 -0
  59. package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +27 -0
  60. package/dist/types/data-structures/matrix/index.d.ts +2 -0
  61. package/dist/types/data-structures/matrix/matrix.d.ts +168 -0
  62. package/dist/types/data-structures/matrix/navigator.d.ts +55 -0
  63. package/dist/types/data-structures/priority-queue/index.d.ts +3 -0
  64. package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +27 -0
  65. package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +26 -0
  66. package/dist/types/data-structures/priority-queue/priority-queue.d.ts +15 -0
  67. package/dist/types/data-structures/queue/deque.d.ts +459 -0
  68. package/dist/types/data-structures/queue/index.d.ts +2 -0
  69. package/dist/types/data-structures/queue/queue.d.ts +364 -0
  70. package/dist/types/data-structures/stack/index.d.ts +1 -0
  71. package/dist/types/data-structures/stack/stack.d.ts +324 -0
  72. package/dist/types/data-structures/tree/index.d.ts +1 -0
  73. package/dist/types/data-structures/tree/tree.d.ts +62 -0
  74. package/dist/types/data-structures/trie/index.d.ts +1 -0
  75. package/dist/types/data-structures/trie/trie.d.ts +412 -0
  76. package/dist/types/index.d.ts +23 -0
  77. package/dist/types/interfaces/binary-tree.d.ts +60 -0
  78. package/dist/types/interfaces/doubly-linked-list.d.ts +1 -0
  79. package/dist/types/interfaces/graph.d.ts +21 -0
  80. package/dist/types/interfaces/heap.d.ts +1 -0
  81. package/dist/types/interfaces/index.d.ts +8 -0
  82. package/dist/types/interfaces/navigator.d.ts +1 -0
  83. package/dist/types/interfaces/priority-queue.d.ts +1 -0
  84. package/dist/types/interfaces/segment-tree.d.ts +1 -0
  85. package/dist/types/interfaces/singly-linked-list.d.ts +1 -0
  86. package/dist/types/types/common.d.ts +15 -0
  87. package/dist/types/types/data-structures/base/base.d.ts +13 -0
  88. package/dist/types/types/data-structures/base/index.d.ts +1 -0
  89. package/dist/types/types/data-structures/binary-tree/avl-tree-counter.d.ts +2 -0
  90. package/dist/types/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +2 -0
  91. package/dist/types/types/data-structures/binary-tree/avl-tree.d.ts +2 -0
  92. package/dist/types/types/data-structures/binary-tree/binary-indexed-tree.d.ts +1 -0
  93. package/dist/types/types/data-structures/binary-tree/binary-tree.d.ts +29 -0
  94. package/dist/types/types/data-structures/binary-tree/bst.d.ts +12 -0
  95. package/dist/types/types/data-structures/binary-tree/index.d.ts +9 -0
  96. package/dist/types/types/data-structures/binary-tree/red-black-tree.d.ts +3 -0
  97. package/dist/types/types/data-structures/binary-tree/segment-tree.d.ts +1 -0
  98. package/dist/types/types/data-structures/binary-tree/tree-counter.d.ts +2 -0
  99. package/dist/types/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -0
  100. package/dist/types/types/data-structures/graph/abstract-graph.d.ts +14 -0
  101. package/dist/types/types/data-structures/graph/directed-graph.d.ts +1 -0
  102. package/dist/types/types/data-structures/graph/index.d.ts +3 -0
  103. package/dist/types/types/data-structures/graph/map-graph.d.ts +1 -0
  104. package/dist/types/types/data-structures/graph/undirected-graph.d.ts +1 -0
  105. package/dist/types/types/data-structures/hash/hash-map.d.ts +19 -0
  106. package/dist/types/types/data-structures/hash/index.d.ts +2 -0
  107. package/dist/types/types/data-structures/heap/heap.d.ts +5 -0
  108. package/dist/types/types/data-structures/heap/index.d.ts +1 -0
  109. package/dist/types/types/data-structures/heap/max-heap.d.ts +1 -0
  110. package/dist/types/types/data-structures/heap/min-heap.d.ts +1 -0
  111. package/dist/types/types/data-structures/index.d.ts +12 -0
  112. package/dist/types/types/data-structures/linked-list/doubly-linked-list.d.ts +2 -0
  113. package/dist/types/types/data-structures/linked-list/index.d.ts +3 -0
  114. package/dist/types/types/data-structures/linked-list/singly-linked-list.d.ts +2 -0
  115. package/dist/types/types/data-structures/linked-list/skip-linked-list.d.ts +4 -0
  116. package/dist/types/types/data-structures/matrix/index.d.ts +2 -0
  117. package/dist/types/types/data-structures/matrix/matrix.d.ts +7 -0
  118. package/dist/types/types/data-structures/matrix/navigator.d.ts +14 -0
  119. package/dist/types/types/data-structures/priority-queue/index.d.ts +3 -0
  120. package/dist/types/types/data-structures/priority-queue/max-priority-queue.d.ts +1 -0
  121. package/dist/types/types/data-structures/priority-queue/min-priority-queue.d.ts +1 -0
  122. package/dist/types/types/data-structures/priority-queue/priority-queue.d.ts +2 -0
  123. package/dist/types/types/data-structures/queue/deque.d.ts +4 -0
  124. package/dist/types/types/data-structures/queue/index.d.ts +2 -0
  125. package/dist/types/types/data-structures/queue/queue.d.ts +4 -0
  126. package/dist/types/types/data-structures/stack/index.d.ts +1 -0
  127. package/dist/types/types/data-structures/stack/stack.d.ts +2 -0
  128. package/dist/types/types/data-structures/tree/index.d.ts +1 -0
  129. package/dist/types/types/data-structures/tree/tree.d.ts +1 -0
  130. package/dist/types/types/data-structures/trie/index.d.ts +1 -0
  131. package/dist/types/types/data-structures/trie/trie.d.ts +4 -0
  132. package/dist/types/types/index.d.ts +3 -0
  133. package/dist/types/types/utils/index.d.ts +2 -0
  134. package/dist/types/types/utils/utils.d.ts +22 -0
  135. package/dist/types/types/utils/validate-type.d.ts +19 -0
  136. package/dist/types/utils/index.d.ts +2 -0
  137. package/dist/types/utils/number.d.ts +14 -0
  138. package/dist/types/utils/utils.d.ts +209 -0
  139. package/dist/umd/red-black-tree-typed.js +14578 -0
  140. package/dist/umd/red-black-tree-typed.js.map +1 -0
  141. package/dist/umd/red-black-tree-typed.min.js +44 -0
  142. package/dist/umd/red-black-tree-typed.min.js.map +1 -0
  143. package/docs/.nojekyll +1 -0
  144. package/docs/assets/highlight.css +92 -0
  145. package/docs/assets/main.js +59 -0
  146. package/docs/assets/navigation.js +1 -0
  147. package/docs/assets/search.js +1 -0
  148. package/docs/assets/style.css +1383 -0
  149. package/docs/classes/AVLTree.html +2046 -0
  150. package/docs/classes/AVLTreeNode.html +263 -0
  151. package/docs/index.html +523 -0
  152. package/docs/modules.html +45 -0
  153. package/jest.config.js +8 -0
  154. package/package.json +113 -0
  155. package/src/common/index.ts +23 -0
  156. package/src/constants/index.ts +4 -0
  157. package/src/data-structures/base/index.ts +2 -0
  158. package/src/data-structures/base/iterable-element-base.ts +352 -0
  159. package/src/data-structures/base/iterable-entry-base.ts +246 -0
  160. package/src/data-structures/base/linear-base.ts +643 -0
  161. package/src/data-structures/binary-tree/avl-tree-counter.ts +539 -0
  162. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +438 -0
  163. package/src/data-structures/binary-tree/avl-tree.ts +840 -0
  164. package/src/data-structures/binary-tree/binary-indexed-tree.ts +331 -0
  165. package/src/data-structures/binary-tree/binary-tree.ts +2492 -0
  166. package/src/data-structures/binary-tree/bst.ts +2024 -0
  167. package/src/data-structures/binary-tree/index.ts +10 -0
  168. package/src/data-structures/binary-tree/red-black-tree.ts +767 -0
  169. package/src/data-structures/binary-tree/segment-tree.ts +324 -0
  170. package/src/data-structures/binary-tree/tree-counter.ts +575 -0
  171. package/src/data-structures/binary-tree/tree-multi-map.ts +549 -0
  172. package/src/data-structures/graph/abstract-graph.ts +1081 -0
  173. package/src/data-structures/graph/directed-graph.ts +715 -0
  174. package/src/data-structures/graph/index.ts +4 -0
  175. package/src/data-structures/graph/map-graph.ts +132 -0
  176. package/src/data-structures/graph/undirected-graph.ts +626 -0
  177. package/src/data-structures/hash/hash-map.ts +813 -0
  178. package/src/data-structures/hash/index.ts +1 -0
  179. package/src/data-structures/heap/heap.ts +1020 -0
  180. package/src/data-structures/heap/index.ts +3 -0
  181. package/src/data-structures/heap/max-heap.ts +47 -0
  182. package/src/data-structures/heap/min-heap.ts +36 -0
  183. package/src/data-structures/index.ts +12 -0
  184. package/src/data-structures/linked-list/doubly-linked-list.ts +876 -0
  185. package/src/data-structures/linked-list/index.ts +3 -0
  186. package/src/data-structures/linked-list/singly-linked-list.ts +1050 -0
  187. package/src/data-structures/linked-list/skip-linked-list.ts +173 -0
  188. package/src/data-structures/matrix/index.ts +2 -0
  189. package/src/data-structures/matrix/matrix.ts +491 -0
  190. package/src/data-structures/matrix/navigator.ts +124 -0
  191. package/src/data-structures/priority-queue/index.ts +3 -0
  192. package/src/data-structures/priority-queue/max-priority-queue.ts +42 -0
  193. package/src/data-structures/priority-queue/min-priority-queue.ts +29 -0
  194. package/src/data-structures/priority-queue/priority-queue.ts +19 -0
  195. package/src/data-structures/queue/deque.ts +1001 -0
  196. package/src/data-structures/queue/index.ts +2 -0
  197. package/src/data-structures/queue/queue.ts +592 -0
  198. package/src/data-structures/stack/index.ts +1 -0
  199. package/src/data-structures/stack/stack.ts +469 -0
  200. package/src/data-structures/tree/index.ts +1 -0
  201. package/src/data-structures/tree/tree.ts +115 -0
  202. package/src/data-structures/trie/index.ts +1 -0
  203. package/src/data-structures/trie/trie.ts +756 -0
  204. package/src/index.ts +24 -0
  205. package/src/interfaces/binary-tree.ts +252 -0
  206. package/src/interfaces/doubly-linked-list.ts +1 -0
  207. package/src/interfaces/graph.ts +44 -0
  208. package/src/interfaces/heap.ts +1 -0
  209. package/src/interfaces/index.ts +8 -0
  210. package/src/interfaces/navigator.ts +1 -0
  211. package/src/interfaces/priority-queue.ts +1 -0
  212. package/src/interfaces/segment-tree.ts +1 -0
  213. package/src/interfaces/singly-linked-list.ts +1 -0
  214. package/src/types/common.ts +25 -0
  215. package/src/types/data-structures/base/base.ts +34 -0
  216. package/src/types/data-structures/base/index.ts +1 -0
  217. package/src/types/data-structures/binary-tree/avl-tree-counter.ts +3 -0
  218. package/src/types/data-structures/binary-tree/avl-tree-multi-map.ts +3 -0
  219. package/src/types/data-structures/binary-tree/avl-tree.ts +3 -0
  220. package/src/types/data-structures/binary-tree/binary-indexed-tree.ts +1 -0
  221. package/src/types/data-structures/binary-tree/binary-tree.ts +31 -0
  222. package/src/types/data-structures/binary-tree/bst.ts +19 -0
  223. package/src/types/data-structures/binary-tree/index.ts +9 -0
  224. package/src/types/data-structures/binary-tree/red-black-tree.ts +5 -0
  225. package/src/types/data-structures/binary-tree/segment-tree.ts +1 -0
  226. package/src/types/data-structures/binary-tree/tree-counter.ts +3 -0
  227. package/src/types/data-structures/binary-tree/tree-multi-map.ts +3 -0
  228. package/src/types/data-structures/graph/abstract-graph.ts +18 -0
  229. package/src/types/data-structures/graph/directed-graph.ts +2 -0
  230. package/src/types/data-structures/graph/index.ts +3 -0
  231. package/src/types/data-structures/graph/map-graph.ts +1 -0
  232. package/src/types/data-structures/graph/undirected-graph.ts +1 -0
  233. package/src/types/data-structures/hash/hash-map.ts +19 -0
  234. package/src/types/data-structures/hash/index.ts +3 -0
  235. package/src/types/data-structures/heap/heap.ts +6 -0
  236. package/src/types/data-structures/heap/index.ts +1 -0
  237. package/src/types/data-structures/heap/max-heap.ts +1 -0
  238. package/src/types/data-structures/heap/min-heap.ts +1 -0
  239. package/src/types/data-structures/index.ts +12 -0
  240. package/src/types/data-structures/linked-list/doubly-linked-list.ts +3 -0
  241. package/src/types/data-structures/linked-list/index.ts +3 -0
  242. package/src/types/data-structures/linked-list/singly-linked-list.ts +3 -0
  243. package/src/types/data-structures/linked-list/skip-linked-list.ts +1 -0
  244. package/src/types/data-structures/matrix/index.ts +2 -0
  245. package/src/types/data-structures/matrix/matrix.ts +7 -0
  246. package/src/types/data-structures/matrix/navigator.ts +14 -0
  247. package/src/types/data-structures/priority-queue/index.ts +3 -0
  248. package/src/types/data-structures/priority-queue/max-priority-queue.ts +1 -0
  249. package/src/types/data-structures/priority-queue/min-priority-queue.ts +1 -0
  250. package/src/types/data-structures/priority-queue/priority-queue.ts +3 -0
  251. package/src/types/data-structures/queue/deque.ts +5 -0
  252. package/src/types/data-structures/queue/index.ts +2 -0
  253. package/src/types/data-structures/queue/queue.ts +5 -0
  254. package/src/types/data-structures/stack/index.ts +1 -0
  255. package/src/types/data-structures/stack/stack.ts +3 -0
  256. package/src/types/data-structures/tree/index.ts +1 -0
  257. package/src/types/data-structures/tree/tree.ts +1 -0
  258. package/src/types/data-structures/trie/index.ts +1 -0
  259. package/src/types/data-structures/trie/trie.ts +3 -0
  260. package/src/types/index.ts +3 -0
  261. package/src/types/utils/index.ts +2 -0
  262. package/src/types/utils/utils.ts +33 -0
  263. package/src/types/utils/validate-type.ts +35 -0
  264. package/src/utils/index.ts +2 -0
  265. package/src/utils/number.ts +22 -0
  266. package/src/utils/utils.ts +350 -0
  267. package/test/index.test.ts +111 -0
  268. package/tsconfig.base.json +23 -0
  269. package/tsconfig.json +12 -0
  270. package/tsconfig.test.json +8 -0
  271. package/tsconfig.types.json +15 -0
  272. package/tsup.config.js +28 -0
  273. package/tsup.node.config.js +71 -0
@@ -0,0 +1,2024 @@
1
+ /**
2
+ * data-structure-typed
3
+ *
4
+ * @author Pablo Zeng
5
+ * @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
6
+ * @license MIT License
7
+ */
8
+
9
+ import type {
10
+ BinaryTreeDeleteResult,
11
+ BSTNOptKeyOrNode,
12
+ BSTOptions,
13
+ BTNRep,
14
+ Comparator,
15
+ CP,
16
+ DFSOrderPattern,
17
+ EntryCallback,
18
+ FamilyPosition,
19
+ IterationType,
20
+ NodeCallback,
21
+ NodePredicate,
22
+ OptNode,
23
+ RBTNColor
24
+ } from '../../types';
25
+ import { BinaryTree } from './binary-tree';
26
+ import { IBinaryTree } from '../../interfaces';
27
+ import { Queue } from '../queue';
28
+ import { isComparable } from '../../utils';
29
+ import { Range } from '../../common';
30
+
31
+ /**
32
+ * Represents a Node in a Binary Search Tree.
33
+ *
34
+ * @template K - The type of the key.
35
+ * @template V - The type of the value.
36
+ */
37
+ export class BSTNode<K = any, V = any> {
38
+ key: K;
39
+ value?: V;
40
+ parent?: BSTNode<K, V> = undefined;
41
+
42
+ /**
43
+ * Creates an instance of BSTNode.
44
+ * @remarks Time O(1), Space O(1)
45
+ *
46
+ * @param key - The key of the node.
47
+ * @param [value] - The value associated with the key.
48
+ */
49
+ constructor(key: K, value?: V) {
50
+ this.key = key;
51
+ this.value = value;
52
+ }
53
+
54
+ _left?: BSTNode<K, V> | null | undefined = undefined;
55
+
56
+ /**
57
+ * Gets the left child of the node.
58
+ * @remarks Time O(1), Space O(1)
59
+ *
60
+ * @returns The left child.
61
+ */
62
+ get left(): BSTNode<K, V> | null | undefined {
63
+ return this._left;
64
+ }
65
+
66
+ /**
67
+ * Sets the left child of the node and updates its parent reference.
68
+ * @remarks Time O(1), Space O(1)
69
+ *
70
+ * @param v - The node to set as the left child.
71
+ */
72
+ set left(v: BSTNode<K, V> | null | undefined) {
73
+ if (v) v.parent = this;
74
+ this._left = v;
75
+ }
76
+
77
+ _right?: BSTNode<K, V> | null | undefined = undefined;
78
+
79
+ /**
80
+ * Gets the right child of the node.
81
+ * @remarks Time O(1), Space O(1)
82
+ *
83
+ * @returns The right child.
84
+ */
85
+ get right(): BSTNode<K, V> | null | undefined {
86
+ return this._right;
87
+ }
88
+
89
+ /**
90
+ * Sets the right child of the node and updates its parent reference.
91
+ * @remarks Time O(1), Space O(1)
92
+ *
93
+ * @param v - The node to set as the right child.
94
+ */
95
+ set right(v: BSTNode<K, V> | null | undefined) {
96
+ if (v) v.parent = this;
97
+ this._right = v;
98
+ }
99
+
100
+ _height: number = 0;
101
+
102
+ /**
103
+ * Gets the height of the node (used in self-balancing trees).
104
+ * @remarks Time O(1), Space O(1)
105
+ *
106
+ * @returns The height.
107
+ */
108
+ get height(): number {
109
+ return this._height;
110
+ }
111
+
112
+ /**
113
+ * Sets the height of the node.
114
+ * @remarks Time O(1), Space O(1)
115
+ *
116
+ * @param value - The new height.
117
+ */
118
+ set height(value: number) {
119
+ this._height = value;
120
+ }
121
+
122
+ _color: RBTNColor = 'BLACK';
123
+
124
+ /**
125
+ * Gets the color of the node (used in Red-Black trees).
126
+ * @remarks Time O(1), Space O(1)
127
+ *
128
+ * @returns The node's color.
129
+ */
130
+ get color(): RBTNColor {
131
+ return this._color;
132
+ }
133
+
134
+ /**
135
+ * Sets the color of the node.
136
+ * @remarks Time O(1), Space O(1)
137
+ *
138
+ * @param value - The new color.
139
+ */
140
+ set color(value: RBTNColor) {
141
+ this._color = value;
142
+ }
143
+
144
+ _count: number = 1;
145
+
146
+ /**
147
+ * Gets the count of nodes in the subtree rooted at this node (used in order-statistic trees).
148
+ * @remarks Time O(1), Space O(1)
149
+ *
150
+ * @returns The subtree node count.
151
+ */
152
+ get count(): number {
153
+ return this._count;
154
+ }
155
+
156
+ /**
157
+ * Sets the count of nodes in the subtree.
158
+ * @remarks Time O(1), Space O(1)
159
+ *
160
+ * @param value - The new count.
161
+ */
162
+ set count(value: number) {
163
+ this._count = value;
164
+ }
165
+
166
+ /**
167
+ * Gets the position of the node relative to its parent.
168
+ * @remarks Time O(1), Space O(1)
169
+ *
170
+ * @returns The family position (e.g., 'ROOT', 'LEFT', 'RIGHT').
171
+ */
172
+ get familyPosition(): FamilyPosition {
173
+ if (!this.parent) {
174
+ return this.left || this.right ? 'ROOT' : 'ISOLATED';
175
+ }
176
+
177
+ if (this.parent.left === this) {
178
+ return this.left || this.right ? 'ROOT_LEFT' : 'LEFT';
179
+ } else if (this.parent.right === this) {
180
+ return this.left || this.right ? 'ROOT_RIGHT' : 'RIGHT';
181
+ }
182
+
183
+ return 'MAL_NODE';
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Represents a Binary Search Tree (BST).
189
+ * Keys are ordered, allowing for faster search operations compared to a standard Binary Tree.
190
+ * @template K - The type of the key.
191
+ * @template V - The type of the value.
192
+ * @template R - The type of the raw data object (if using `toEntryFn`).
193
+ *
194
+ * 1. Node Order: Each node's left child has a lesser value, and the right child has a greater value.
195
+ * 2. Unique Keys: No duplicate keys in a standard BST.
196
+ * 3. Efficient Search: Enables quick search, minimum, and maximum operations.
197
+ * 4. Inorder Traversal: Yields nodes in ascending order.
198
+ * 5. Logarithmic Operations: Ideal operations like insertion, deletion, and searching are O(log n) time-efficient.
199
+ * 6. Balance Variability: Can become unbalanced; special types maintain balance.
200
+ * 7. No Auto-Balancing: Standard BSTs don't automatically balance themselves.
201
+ *
202
+ * @example
203
+ * // basic BST creation and add operation
204
+ * // Create a simple BST with numeric keys
205
+ * const bst = new BST<number>([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
206
+ *
207
+ * bst.print();
208
+ * // _______8__________
209
+ * // / \
210
+ * // ___4___ ____12_____
211
+ * // / \ / \
212
+ * // _2_ _6_ _10__ _14__
213
+ * // / \ / \ / \ / \
214
+ * // 1 3 5 7 9 11 13 15__
215
+ * // \
216
+ * // 16
217
+ *
218
+ * // Verify size
219
+ * console.log(bst.size); // 16;
220
+ *
221
+ * // Add new elements
222
+ * bst.set(17);
223
+ * bst.set(0);
224
+ * console.log(bst.size); // 18;
225
+ *
226
+ * // Verify keys are searchable
227
+ * console.log(bst.has(11)); // true;
228
+ * console.log(bst.has(100)); // false;
229
+ * @example
230
+ * // BST delete and search after deletion
231
+ * const bst = new BST<number>([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
232
+ *
233
+ * // Delete a leaf node
234
+ * bst.delete(1);
235
+ * console.log(bst.has(1)); // false;
236
+ *
237
+ * // Delete a node with one child
238
+ * bst.delete(2);
239
+ * console.log(bst.has(2)); // false;
240
+ *
241
+ * // Delete a node with two children
242
+ * bst.delete(3);
243
+ * console.log(bst.has(3)); // false;
244
+ *
245
+ * // Size decreases with each deletion
246
+ * console.log(bst.size); // 13;
247
+ *
248
+ * // Other nodes remain searchable
249
+ * console.log(bst.has(11)); // true;
250
+ * console.log(bst.has(15)); // true;
251
+ * @example
252
+ * // Merge 3 sorted datasets
253
+ * const dataset1 = new BST<number, string>([
254
+ * [1, 'A'],
255
+ * [7, 'G']
256
+ * ]);
257
+ * const dataset2 = [
258
+ * [2, 'B'],
259
+ * [6, 'F']
260
+ * ];
261
+ * const dataset3 = new BST<number, string>([
262
+ * [3, 'C'],
263
+ * [5, 'E'],
264
+ * [4, 'D']
265
+ * ]);
266
+ *
267
+ * // Merge datasets into a single BinarySearchTree
268
+ * const merged = new BST<number, string>(dataset1);
269
+ * merged.setMany(dataset2);
270
+ * merged.merge(dataset3);
271
+ *
272
+ * // Verify merged dataset is in sorted order
273
+ * console.log([...merged.values()]); // ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
274
+ * @example
275
+ * // BST with custom objects for expression evaluation
276
+ * interface Expression {
277
+ * id: number;
278
+ * operator: string;
279
+ * precedence: number;
280
+ * }
281
+ *
282
+ * // BST efficiently stores and retrieves operators by precedence
283
+ * const operatorTree = new BST<number, Expression>(
284
+ * [
285
+ * [1, { id: 1, operator: '+', precedence: 1 }],
286
+ * [2, { id: 2, operator: '*', precedence: 2 }],
287
+ * [3, { id: 3, operator: '/', precedence: 2 }],
288
+ * [4, { id: 4, operator: '-', precedence: 1 }],
289
+ * [5, { id: 5, operator: '^', precedence: 3 }]
290
+ * ],
291
+ * { isMapMode: false }
292
+ * );
293
+ *
294
+ * console.log(operatorTree.size); // 5;
295
+ *
296
+ * // Quick lookup of operators
297
+ * const mult = operatorTree.get(2);
298
+ * console.log(mult?.operator); // '*';
299
+ * console.log(mult?.precedence); // 2;
300
+ *
301
+ * // Check if operator exists
302
+ * console.log(operatorTree.has(5)); // true;
303
+ * console.log(operatorTree.has(99)); // false;
304
+ *
305
+ * // Retrieve operator by precedence level
306
+ * const expNode = operatorTree.getNode(3);
307
+ * console.log(expNode?.key); // 3;
308
+ * console.log(expNode?.value?.precedence); // 2;
309
+ *
310
+ * // Delete operator and verify
311
+ * operatorTree.delete(1);
312
+ * console.log(operatorTree.has(1)); // false;
313
+ * console.log(operatorTree.size); // 4;
314
+ *
315
+ * // Get tree height for optimization analysis
316
+ * const treeHeight = operatorTree.getHeight();
317
+ * console.log(treeHeight); // > 0;
318
+ *
319
+ * // Remaining operators are still accessible
320
+ * const remaining = operatorTree.get(2);
321
+ * console.log(remaining); // defined;
322
+ * @example
323
+ * // Find lowest common ancestor
324
+ * const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);
325
+ *
326
+ * // LCA helper function
327
+ * const findLCA = (num1: number, num2: number): number | undefined => {
328
+ * const path1 = bst.getPathToRoot(num1);
329
+ * const path2 = bst.getPathToRoot(num2);
330
+ * // Find the first common ancestor
331
+ * return findFirstCommon(path1, path2);
332
+ * };
333
+ *
334
+ * function findFirstCommon(arr1: (number | undefined)[], arr2: (number | undefined)[]): number | undefined {
335
+ * for (const num of arr1) {
336
+ * if (arr2.indexOf(num) !== -1) {
337
+ * return num;
338
+ * }
339
+ * }
340
+ * return undefined;
341
+ * }
342
+ *
343
+ * // Assertions
344
+ * console.log(findLCA(3, 10)); // 7;
345
+ * console.log(findLCA(5, 35)); // 15;
346
+ * console.log(findLCA(20, 30)); // 25;
347
+ */
348
+ export class BST<K = any, V = any, R = any> extends BinaryTree<K, V, R> implements IBinaryTree<K, V, R> {
349
+ /**
350
+ * Creates an instance of BST.
351
+ * @remarks Time O(N log N) or O(N^2) depending on `isBalanceAdd` in `addMany` and input order. Space O(N).
352
+ *
353
+ * @param [keysNodesEntriesOrRaws=[]] - An iterable of items to set.
354
+ * @param [options] - Configuration options for the BST, including comparator.
355
+ */
356
+ constructor(
357
+ keysNodesEntriesOrRaws: Iterable<K | BSTNode | [K | null | undefined, V | undefined] | null | undefined | R> = [],
358
+ options?: BSTOptions<K, V, R>
359
+ ) {
360
+ super([], options);
361
+
362
+ if (options) {
363
+ // Use the 'in' operator to check if the field is present
364
+ if ('comparator' in options && options.comparator !== undefined) {
365
+ this._comparator = options.comparator;
366
+ } else {
367
+ this._comparator = this._createDefaultComparator();
368
+ }
369
+ } else {
370
+ this._comparator = this._createDefaultComparator();
371
+ }
372
+
373
+ if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
374
+ }
375
+
376
+ protected override _root?: BSTNode<K, V> = undefined;
377
+
378
+ /**
379
+ * Gets the root node of the tree.
380
+ * @remarks Time O(1)
381
+ *
382
+ * @returns The root node.
383
+ */
384
+ override get root(): OptNode<BSTNode<K, V>> {
385
+ return this._root;
386
+ }
387
+
388
+ /**
389
+ * The comparator function used to determine the order of keys in the tree.
390
+
391
+ * @remarks Time O(1) Space O(1)
392
+ */
393
+ protected _comparator: Comparator<K>;
394
+
395
+ /**
396
+ * Gets the comparator function used by the tree.
397
+ * @remarks Time O(1)
398
+ *
399
+ * @returns The comparator function.
400
+ */
401
+ get comparator(): Comparator<K> {
402
+ return this._comparator;
403
+ }
404
+
405
+ /**
406
+ * (Protected) Creates a new BST node.
407
+ * @remarks Time O(1), Space O(1)
408
+ *
409
+ * @param key - The key for the new node.
410
+ * @param [value] - The value for the new node (used if not in Map mode).
411
+ * @returns The newly created BSTNode.
412
+ */
413
+ override createNode(key: K, value?: V): BSTNode<K, V> {
414
+ return new BSTNode<K, V>(key, this._isMapMode ? undefined : value);
415
+ }
416
+
417
+ /**
418
+ * Ensures the input is a node. If it's a key or entry, it searches for the node.
419
+ * @remarks Time O(log N) (height of the tree), O(N) worst-case.
420
+ *
421
+ * @param keyNodeOrEntry - The item to resolve to a node.
422
+ * @param [iterationType=this.iterationType] - The traversal method to use if searching.
423
+ * @returns The resolved node, or undefined if not found.
424
+ */
425
+ override ensureNode(
426
+ keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
427
+ iterationType: IterationType = this.iterationType
428
+ ): OptNode<BSTNode<K, V>> {
429
+ return super.ensureNode(keyNodeOrEntry, iterationType) ?? undefined;
430
+ }
431
+
432
+ /**
433
+ * Checks if the given item is a `BSTNode` instance.
434
+ * @remarks Time O(1), Space O(1)
435
+ *
436
+ * @param keyNodeOrEntry - The item to check.
437
+ * @returns True if it's a BSTNode, false otherwise.
438
+ */
439
+ override isNode(
440
+ keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
441
+ ): keyNodeOrEntry is BSTNode<K, V> {
442
+ return keyNodeOrEntry instanceof BSTNode;
443
+ }
444
+
445
+ /**
446
+ * Checks if the given key is valid (comparable).
447
+ * @remarks Time O(1)
448
+ *
449
+ * @param key - The key to validate.
450
+ * @returns True if the key is valid, false otherwise.
451
+ */
452
+ override isValidKey(key: any): key is K {
453
+ return isComparable(key);
454
+ }
455
+
456
+ override dfs(): (K | undefined)[];
457
+
458
+ override dfs<C extends NodeCallback<BSTNode<K, V>>>(
459
+ callback: C,
460
+ pattern?: DFSOrderPattern,
461
+ onlyOne?: boolean,
462
+ startNode?: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
463
+ iterationType?: IterationType
464
+ ): ReturnType<C>[];
465
+
466
+ /**
467
+ * Performs a Depth-First Search (DFS) traversal.
468
+ * @remarks Time O(N), visits every node. Space O(log N) for the call/explicit stack. O(N) worst-case.
469
+ *
470
+ * @template C - The type of the callback function.
471
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
472
+ * @param [pattern='IN'] - The traversal order ('IN', 'PRE', 'POST').
473
+ * @param [onlyOne=false] - If true, stops after the first callback.
474
+ * @param [startNode=this._root] - The node to start from.
475
+ * @param [iterationType=this.iterationType] - The traversal method.
476
+ * @returns An array of callback results.
477
+ */
478
+ override dfs<C extends NodeCallback<BSTNode<K, V>>>(
479
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
480
+ pattern: DFSOrderPattern = 'IN',
481
+ onlyOne: boolean = false,
482
+ startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
483
+ iterationType: IterationType = this.iterationType
484
+ ): ReturnType<C>[] {
485
+ return super.dfs(callback, pattern, onlyOne, startNode, iterationType);
486
+ }
487
+
488
+ override bfs(): (K | undefined)[];
489
+ override bfs<C extends NodeCallback<BSTNode<K, V>>>(
490
+ callback: C,
491
+ startNode?: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
492
+ iterationType?: IterationType
493
+ ): ReturnType<C>[];
494
+
495
+ /**
496
+ * Performs a Breadth-First Search (BFS) or Level-Order traversal.
497
+ * @remarks Time O(N), visits every node. Space O(N) in the worst case for the queue.
498
+ *
499
+ * @template C - The type of the callback function.
500
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
501
+ * @param [startNode=this._root] - The node to start from.
502
+ * @param [iterationType=this.iterationType] - The traversal method.
503
+ * @returns An array of callback results.
504
+ */
505
+ override bfs<C extends NodeCallback<BSTNode<K, V>>>(
506
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
507
+ startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
508
+ iterationType: IterationType = this.iterationType
509
+ ): ReturnType<C>[] {
510
+ return super.bfs(callback, startNode, iterationType, false);
511
+ }
512
+
513
+ override listLevels(): (K | undefined)[][];
514
+
515
+ override listLevels<C extends NodeCallback<BSTNode<K, V>>>(
516
+ callback: C,
517
+ startNode?: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
518
+ iterationType?: IterationType
519
+ ): ReturnType<C>[][];
520
+
521
+ /**
522
+ * Returns a 2D array of nodes, grouped by level.
523
+ * @remarks Time O(N), visits every node. Space O(N) for the result array and the queue/stack.
524
+ *
525
+ * @template C - The type of the callback function.
526
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each node.
527
+ * @param [startNode=this._root] - The node to start from.
528
+ * @param [iterationType=this.iterationType] - The traversal method.
529
+ * @returns A 2D array of callback results.
530
+ */
531
+ override listLevels<C extends NodeCallback<BSTNode<K, V>>>(
532
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
533
+ startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
534
+ iterationType: IterationType = this.iterationType
535
+ ): ReturnType<C>[][] {
536
+ return super.listLevels(callback, startNode, iterationType, false);
537
+ }
538
+
539
+ /**
540
+ * Gets the first node matching a predicate.
541
+ * @remarks Time O(log N) if searching by key, O(N) if searching by predicate. Space O(log N) or O(N).
542
+ *
543
+ * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
544
+ * @param [startNode=this._root] - The node to start the search from.
545
+ * @param [iterationType=this.iterationType] - The traversal method.
546
+ * @returns The first matching node, or undefined if not found.
547
+ */
548
+ override getNode(
549
+ keyNodeEntryOrPredicate:
550
+ | K
551
+ | BSTNode<K, V>
552
+ | [K | null | undefined, V | undefined]
553
+ | null
554
+ | undefined
555
+ | NodePredicate<BSTNode<K, V>>,
556
+ startNode: BSTNOptKeyOrNode<K, BSTNode<K, V>> = this._root,
557
+ iterationType: IterationType = this.iterationType
558
+ ): OptNode<BSTNode<K, V>> {
559
+ return this.getNodes(keyNodeEntryOrPredicate, true, startNode, iterationType)[0] ?? undefined;
560
+ }
561
+
562
+ override search(
563
+ keyNodeEntryOrPredicate:
564
+ | K
565
+ | BSTNode<K, V>
566
+ | [K | null | undefined, V | undefined]
567
+ | null
568
+ | undefined
569
+ | NodePredicate<BSTNode<K, V>>
570
+ | Range<K>,
571
+ onlyOne?: boolean
572
+ ): (K | undefined)[];
573
+
574
+ override search<C extends NodeCallback<BSTNode<K, V>>>(
575
+ keyNodeEntryOrPredicate:
576
+ | K
577
+ | BSTNode<K, V>
578
+ | [K | null | undefined, V | undefined]
579
+ | null
580
+ | undefined
581
+ | NodePredicate<BSTNode<K, V>>
582
+ | Range<K>,
583
+ onlyOne: boolean,
584
+ callback: C,
585
+ startNode?: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
586
+ iterationType?: IterationType
587
+ ): ReturnType<C>[];
588
+
589
+ /**
590
+ * Searches the tree for nodes matching a predicate, key, or range.
591
+ * @remarks This is an optimized search for a BST. If searching by key or range, it prunes branches.
592
+ * Time O(H + M) for key/range search (H=height, M=matches). O(N) for predicate search.
593
+ * Space O(log N) for the stack.
594
+ *
595
+ * @template C - The type of the callback function.
596
+ * @param keyNodeEntryOrPredicate - The key, node, entry, predicate, or range to search for.
597
+ * @param [onlyOne=false] - If true, stops after finding the first match.
598
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on matching nodes.
599
+ * @param [startNode=this._root] - The node to start the search from.
600
+ * @param [iterationType=this.iterationType] - Whether to use 'RECURSIVE' or 'ITERATIVE' search.
601
+ * @returns An array of results from the callback function for each matching node.
602
+ */
603
+ override search<C extends NodeCallback<BSTNode<K, V>>>(
604
+ keyNodeEntryOrPredicate:
605
+ | K
606
+ | BSTNode<K, V>
607
+ | [K | null | undefined, V | undefined]
608
+ | null
609
+ | undefined
610
+ | NodePredicate<BSTNode<K, V>>
611
+ | Range<K>,
612
+ onlyOne = false,
613
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
614
+ startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
615
+ iterationType: IterationType = this.iterationType
616
+ ): ReturnType<C>[] {
617
+ if (keyNodeEntryOrPredicate === undefined) return [];
618
+ if (keyNodeEntryOrPredicate === null) return [];
619
+ startNode = this.ensureNode(startNode);
620
+ if (!startNode) return [];
621
+
622
+ let predicate: NodePredicate<BSTNode<K, V>>;
623
+ const isRange = this.isRange(keyNodeEntryOrPredicate);
624
+
625
+ if (isRange) {
626
+ predicate = node => {
627
+ if (!node) return false;
628
+ return (keyNodeEntryOrPredicate).isInRange(node.key, this._comparator);
629
+ };
630
+ } else {
631
+ predicate = this._ensurePredicate(keyNodeEntryOrPredicate);
632
+ }
633
+
634
+ // Optimization: Pruning logic
635
+ const shouldVisitLeft = (cur: BSTNode<K, V> | null | undefined) => {
636
+ if (!cur) return false;
637
+ if (!this.isRealNode(cur.left)) return false;
638
+ if (isRange) {
639
+ // Range search: Only go left if the current key is >= the lower bound
640
+ const range = keyNodeEntryOrPredicate;
641
+ const leftS = range.low;
642
+ const leftI = range.includeLow;
643
+ return (leftI && this._compare(cur.key, leftS) >= 0) || (!leftI && this._compare(cur.key, leftS) > 0);
644
+ }
645
+ if (!isRange && !this._isPredicate(keyNodeEntryOrPredicate)) {
646
+ // Key search: Only go left if current key > target key
647
+ const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
648
+ return benchmarkKey !== null && benchmarkKey !== undefined && this._compare(cur.key, benchmarkKey) > 0;
649
+ }
650
+ return true; // Predicate search: must visit all
651
+ };
652
+
653
+ const shouldVisitRight = (cur: BSTNode<K, V> | null | undefined) => {
654
+ if (!cur) return false;
655
+ if (!this.isRealNode(cur.right)) return false;
656
+ if (isRange) {
657
+ // Range search: Only go right if current key <= upper bound
658
+ const range = keyNodeEntryOrPredicate;
659
+ const rightS = range.high;
660
+ const rightI = range.includeHigh;
661
+ return (rightI && this._compare(cur.key, rightS) <= 0) || (!rightI && this._compare(cur.key, rightS) < 0);
662
+ }
663
+ if (!isRange && !this._isPredicate(keyNodeEntryOrPredicate)) {
664
+ // Key search: Only go right if current key < target key
665
+ const benchmarkKey = this._extractKey(keyNodeEntryOrPredicate);
666
+ return benchmarkKey !== null && benchmarkKey !== undefined && this._compare(cur.key, benchmarkKey) < 0;
667
+ }
668
+ return true; // Predicate search: must visit all
669
+ };
670
+
671
+ return super._dfs(
672
+ callback,
673
+ 'IN', // In-order is efficient for range/key search
674
+ onlyOne,
675
+ startNode,
676
+ iterationType,
677
+ false,
678
+ shouldVisitLeft,
679
+ shouldVisitRight,
680
+ () => true, // shouldVisitRoot (always visit)
681
+ cur => !!cur && predicate(cur) // shouldProcessRoot (only process if predicate matches)
682
+ );
683
+ }
684
+
685
+ rangeSearch(range: Range<K> | [K, K]): (K | undefined)[];
686
+
687
+ rangeSearch<C extends NodeCallback<BSTNode<K, V>>>(
688
+ range: Range<K> | [K, K],
689
+ callback: C,
690
+ startNode?: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
691
+ iterationType?: IterationType
692
+ ): ReturnType<C>[];
693
+
694
+ /**
695
+ * Performs an optimized search for nodes within a given key range.
696
+ * @remarks Time O(H + M), where H is tree height and M is the number of matches.
697
+ *
698
+ * @template C - The type of the callback function.
699
+ * @param range - A `Range` object or a `[low, high]` tuple.
700
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - A function to call on matching nodes.
701
+ * @param [startNode=this._root] - The node to start the search from.
702
+ * @param [iterationType=this.iterationType] - The traversal method.
703
+ * @returns An array of callback results.
704
+ */
705
+ rangeSearch<C extends NodeCallback<BSTNode<K, V>>>(
706
+ range: Range<K> | [K, K],
707
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
708
+ startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
709
+ iterationType: IterationType = this.iterationType
710
+ ) {
711
+ const searchRange: Range<K> = range instanceof Range ? range : new Range(range[0], range[1]);
712
+ return this.search(searchRange, false, callback, startNode, iterationType);
713
+ }
714
+
715
+ /**
716
+ * Adds a new node to the BST based on key comparison.
717
+ * @remarks Time O(log N), where H is tree height. O(N) worst-case (unbalanced tree), O(log N) average. Space O(1).
718
+ *
719
+ * @param keyNodeOrEntry - The key, node, or entry to set.
720
+ * @param [value] - The value, if providing just a key.
721
+ * @returns True if the addition was successful, false otherwise.
722
+ */
723
+ override set(
724
+ keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
725
+ value?: V
726
+ ): boolean {
727
+ const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
728
+ if (newNode === undefined) return false;
729
+
730
+ if (this._root === undefined) {
731
+ this._setRoot(newNode);
732
+ if (this._isMapMode) this._setValue(newNode?.key, newValue);
733
+ this._size++;
734
+ return true;
735
+ }
736
+
737
+ let current = this._root;
738
+ while (current !== undefined) {
739
+ if (this._compare(current.key, newNode.key) === 0) {
740
+ // Key exists, replace node
741
+ this._replaceNode(current, newNode);
742
+ if (this._isMapMode) this._setValue(current.key, newValue);
743
+ return true;
744
+ } else if (this._compare(current.key, newNode.key) > 0) {
745
+ // Go left
746
+ if (current.left === undefined) {
747
+ current.left = newNode;
748
+ if (this._isMapMode) this._setValue(newNode?.key, newValue);
749
+ this._size++;
750
+ return true;
751
+ }
752
+ if (current.left !== null) current = current.left;
753
+ } else {
754
+ // Go right
755
+ if (current.right === undefined) {
756
+ current.right = newNode;
757
+ if (this._isMapMode) this._setValue(newNode?.key, newValue);
758
+ this._size++;
759
+ return true;
760
+ }
761
+ if (current.right !== null) current = current.right;
762
+ }
763
+ }
764
+ return false;
765
+ }
766
+
767
+ /**
768
+ * Adds multiple items to the tree.
769
+ * @remarks If `isBalanceAdd` is true, sorts the input and builds a balanced tree. Time O(N log N) (due to sort and balanced set).
770
+ * If false, adds items one by one. Time O(N * H), which is O(N^2) worst-case.
771
+ * Space O(N) for sorting and recursion/iteration stack.
772
+ *
773
+ * @param keysNodesEntriesOrRaws - An iterable of items to set.
774
+ * @param [values] - An optional parallel iterable of values.
775
+ * @param [isBalanceAdd=true] - If true, builds a balanced tree from the items.
776
+ * @param [iterationType=this.iterationType] - The traversal method for balanced set (recursive or iterative).
777
+ * @returns An array of booleans indicating the success of each individual `set` operation.
778
+ */
779
+ override setMany(
780
+ keysNodesEntriesOrRaws: Iterable<R | BTNRep<K, V, BSTNode<K, V>>>,
781
+ values?: Iterable<V | undefined>,
782
+ isBalanceAdd = true,
783
+ iterationType: IterationType = this.iterationType
784
+ ): boolean[] {
785
+ const inserted: boolean[] = [];
786
+ const valuesIterator: Iterator<V | undefined> | undefined = values?.[Symbol.iterator]();
787
+
788
+ if (!isBalanceAdd) {
789
+ // Standard O(N*H) insertion
790
+ for (let kve of keysNodesEntriesOrRaws) {
791
+ const val = valuesIterator?.next().value;
792
+ if (this.isRaw(kve)) kve = this._toEntryFn!(kve);
793
+ inserted.push(this.set(kve, val));
794
+ }
795
+ return inserted;
796
+ }
797
+
798
+ // Balanced O(N log N) insertion
799
+ const realBTNExemplars: {
800
+ key: R | K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined;
801
+ value: V | undefined;
802
+ orgIndex: number;
803
+ }[] = [];
804
+
805
+ let i = 0;
806
+ for (const kve of keysNodesEntriesOrRaws) {
807
+ realBTNExemplars.push({ key: kve, value: valuesIterator?.next().value, orgIndex: i++ });
808
+ }
809
+
810
+ // Sort items by key
811
+ const sorted = realBTNExemplars.sort(({ key: a }, { key: b }) => {
812
+ let keyA: K | undefined | null, keyB: K | undefined | null;
813
+ if (this.isRaw(a)) keyA = this._toEntryFn!(a)[0];
814
+ else if (this.isEntry(a)) keyA = a[0];
815
+ else if (this.isRealNode(a)) keyA = a.key;
816
+ else keyA = a as K;
817
+
818
+ if (this.isRaw(b)) keyB = this._toEntryFn!(b)[0];
819
+ else if (this.isEntry(b)) keyB = b[0];
820
+ else if (this.isRealNode(b)) keyB = b.key;
821
+ else keyB = b as K;
822
+
823
+ if (keyA != null && keyB != null) return this._compare(keyA, keyB);
824
+ return 0;
825
+ });
826
+
827
+ // Recursive balanced build
828
+ const _dfs = (arr: typeof realBTNExemplars) => {
829
+ if (arr.length === 0) return;
830
+ const mid = Math.floor((arr.length - 1) / 2);
831
+ const { key, value, orgIndex } = arr[mid];
832
+ if (this.isRaw(key)) {
833
+ const entry = this._toEntryFn!(key);
834
+ inserted[orgIndex] = this.set(entry);
835
+ } else {
836
+ inserted[orgIndex] = this.set(key, value);
837
+ }
838
+ _dfs(arr.slice(0, mid));
839
+ _dfs(arr.slice(mid + 1));
840
+ };
841
+
842
+ // Iterative balanced build
843
+ const _iterate = () => {
844
+ const n = sorted.length;
845
+ const stack: Array<[number, number]> = [[0, n - 1]];
846
+ while (stack.length > 0) {
847
+ const popped = stack.pop();
848
+ if (!popped) continue;
849
+ const [l, r] = popped;
850
+ if (l > r) continue;
851
+ const m = l + Math.floor((r - l) / 2);
852
+ const { key, value, orgIndex } = sorted[m];
853
+ if (this.isRaw(key)) {
854
+ const entry = this._toEntryFn!(key);
855
+ inserted[orgIndex] = this.set(entry);
856
+ } else {
857
+ inserted[orgIndex] = this.set(key, value);
858
+ }
859
+ stack.push([m + 1, r]);
860
+ stack.push([l, m - 1]);
861
+ }
862
+ };
863
+
864
+ if (iterationType === 'RECURSIVE') _dfs(sorted);
865
+ else _iterate();
866
+
867
+ return inserted;
868
+ }
869
+
870
+ /**
871
+ * Returns the first key with a value >= target.
872
+ * Equivalent to Java TreeMap.ceiling.
873
+ * Time Complexity: O(log n) average, O(h) worst case.
874
+ * Space Complexity: O(h) for recursion, O(1) for iteration.
875
+ */
876
+ ceiling(
877
+ keyNodeEntryOrPredicate:
878
+ | K
879
+ | BSTNode<K, V>
880
+ | [K | null | undefined, V | undefined]
881
+ | null
882
+ | undefined
883
+ | NodePredicate<BSTNode<K, V>>
884
+ ): K | undefined;
885
+
886
+ /**
887
+ * Returns the first node with a key >= target and applies callback.
888
+ * Time Complexity: O(log n) average, O(h) worst case.
889
+ * Space Complexity: O(h) for recursion, O(1) for iteration.
890
+ */
891
+ ceiling<C extends NodeCallback<BSTNode<K, V>>>(
892
+ keyNodeEntryOrPredicate:
893
+ | K
894
+ | BSTNode<K, V>
895
+ | [K | null | undefined, V | undefined]
896
+ | null
897
+ | undefined
898
+ | NodePredicate<BSTNode<K, V>>,
899
+ callback: C,
900
+ iterationType?: IterationType
901
+ ): ReturnType<C>;
902
+
903
+ ceiling<C extends NodeCallback<BSTNode<K, V>>>(
904
+ keyNodeEntryOrPredicate:
905
+ | K
906
+ | BSTNode<K, V>
907
+ | [K | null | undefined, V | undefined]
908
+ | null
909
+ | undefined
910
+ | NodePredicate<BSTNode<K, V>>,
911
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
912
+ iterationType?: IterationType
913
+ ): K | undefined | ReturnType<C> {
914
+ let actualCallback: C | undefined = undefined;
915
+ let actualIterationType: IterationType = this.iterationType;
916
+
917
+ if (typeof callback === 'string') {
918
+ actualIterationType = callback;
919
+ } else if (callback) {
920
+ actualCallback = callback;
921
+ if (iterationType) {
922
+ actualIterationType = iterationType;
923
+ }
924
+ }
925
+
926
+ const node = this._bound(keyNodeEntryOrPredicate, true, actualIterationType);
927
+
928
+ if (!actualCallback) {
929
+ return node?.key;
930
+ }
931
+
932
+ return node ? actualCallback(node) : undefined;
933
+ }
934
+
935
+ /**
936
+ * Returns the first key with a value > target.
937
+ * Equivalent to Java TreeMap.higher.
938
+ * Time Complexity: O(log n) average, O(h) worst case.
939
+ * Space Complexity: O(h) for recursion, O(1) for iteration.
940
+ */
941
+ higher(
942
+ keyNodeEntryOrPredicate:
943
+ | K
944
+ | BSTNode<K, V>
945
+ | [K | null | undefined, V | undefined]
946
+ | null
947
+ | undefined
948
+ | NodePredicate<BSTNode<K, V>>
949
+ ): K | undefined;
950
+
951
+ /**
952
+ * Returns the first node with a key > target and applies callback.
953
+ * Time Complexity: O(log n) average, O(h) worst case.
954
+ * Space Complexity: O(h) for recursion, O(1) for iteration.
955
+ */
956
+ higher<C extends NodeCallback<BSTNode<K, V>>>(
957
+ keyNodeEntryOrPredicate:
958
+ | K
959
+ | BSTNode<K, V>
960
+ | [K | null | undefined, V | undefined]
961
+ | null
962
+ | undefined
963
+ | NodePredicate<BSTNode<K, V>>,
964
+ callback: C,
965
+ iterationType?: IterationType
966
+ ): ReturnType<C>;
967
+
968
+ higher<C extends NodeCallback<BSTNode<K, V>>>(
969
+ keyNodeEntryOrPredicate:
970
+ | K
971
+ | BSTNode<K, V>
972
+ | [K | null | undefined, V | undefined]
973
+ | null
974
+ | undefined
975
+ | NodePredicate<BSTNode<K, V>>,
976
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
977
+ iterationType?: IterationType
978
+ ): K | undefined | ReturnType<C> {
979
+ let actualCallback: C | undefined = undefined;
980
+ let actualIterationType: IterationType = this.iterationType;
981
+
982
+ if (typeof callback === 'string') {
983
+ actualIterationType = callback;
984
+ } else if (callback) {
985
+ actualCallback = callback;
986
+ if (iterationType) {
987
+ actualIterationType = iterationType;
988
+ }
989
+ }
990
+
991
+ const node = this._bound(keyNodeEntryOrPredicate, false, actualIterationType);
992
+
993
+ if (!actualCallback) {
994
+ return node?.key;
995
+ }
996
+
997
+ return node ? actualCallback(node) : undefined;
998
+ }
999
+
1000
+ /**
1001
+ * Returns the first key with a value <= target.
1002
+ * Equivalent to Java TreeMap.floor.
1003
+ * Time Complexity: O(log n) average, O(h) worst case.
1004
+ * Space Complexity: O(h) for recursion, O(1) for iteration.
1005
+ */
1006
+ floor(
1007
+ keyNodeEntryOrPredicate:
1008
+ | K
1009
+ | BSTNode<K, V>
1010
+ | [K | null | undefined, V | undefined]
1011
+ | null
1012
+ | undefined
1013
+ | NodePredicate<BSTNode<K, V>>
1014
+ ): K | undefined;
1015
+
1016
+ /**
1017
+ * Returns the first node with a key <= target and applies callback.
1018
+ * Time Complexity: O(log n) average, O(h) worst case.
1019
+ * Space Complexity: O(h) for recursion, O(1) for iteration.
1020
+ */
1021
+ floor<C extends NodeCallback<BSTNode<K, V>>>(
1022
+ keyNodeEntryOrPredicate:
1023
+ | K
1024
+ | BSTNode<K, V>
1025
+ | [K | null | undefined, V | undefined]
1026
+ | null
1027
+ | undefined
1028
+ | NodePredicate<BSTNode<K, V>>,
1029
+ callback: C,
1030
+ iterationType?: IterationType
1031
+ ): ReturnType<C>;
1032
+
1033
+ floor<C extends NodeCallback<BSTNode<K, V>>>(
1034
+ keyNodeEntryOrPredicate:
1035
+ | K
1036
+ | BSTNode<K, V>
1037
+ | [K | null | undefined, V | undefined]
1038
+ | null
1039
+ | undefined
1040
+ | NodePredicate<BSTNode<K, V>>,
1041
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
1042
+ iterationType?: IterationType
1043
+ ): K | undefined | ReturnType<C> {
1044
+ if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined) {
1045
+ if (typeof callback === 'string' || !callback) {
1046
+ return undefined;
1047
+ }
1048
+ return undefined;
1049
+ }
1050
+
1051
+ let actualCallback: C | undefined = undefined;
1052
+ let actualIterationType: IterationType = this.iterationType;
1053
+
1054
+ if (typeof callback === 'string') {
1055
+ actualIterationType = callback;
1056
+ } else if (callback) {
1057
+ actualCallback = callback;
1058
+ if (iterationType) {
1059
+ actualIterationType = iterationType;
1060
+ }
1061
+ }
1062
+
1063
+ if (this._isPredicate(keyNodeEntryOrPredicate)) {
1064
+ const node = this._floorByPredicate(keyNodeEntryOrPredicate, actualIterationType);
1065
+
1066
+ if (!actualCallback) {
1067
+ return node?.key;
1068
+ }
1069
+
1070
+ return node ? actualCallback(node) : undefined;
1071
+ }
1072
+
1073
+ let targetKey: K | undefined;
1074
+ if (this.isNode(keyNodeEntryOrPredicate)) {
1075
+ targetKey = keyNodeEntryOrPredicate.key;
1076
+ } else if (this.isEntry(keyNodeEntryOrPredicate)) {
1077
+ const key = keyNodeEntryOrPredicate[0];
1078
+ if (key === null || key === undefined) {
1079
+ if (typeof callback === 'string' || !callback) {
1080
+ return undefined;
1081
+ }
1082
+ return undefined;
1083
+ }
1084
+ targetKey = key;
1085
+ } else {
1086
+ targetKey = keyNodeEntryOrPredicate;
1087
+ }
1088
+
1089
+ if (targetKey !== undefined) {
1090
+ const node = this._floorByKey(targetKey, actualIterationType);
1091
+
1092
+ if (!actualCallback) {
1093
+ return node?.key;
1094
+ }
1095
+
1096
+ return node ? actualCallback(node) : undefined;
1097
+ }
1098
+
1099
+ if (typeof callback === 'string' || !callback) {
1100
+ return undefined;
1101
+ }
1102
+ return undefined;
1103
+ }
1104
+
1105
+ /**
1106
+ * Returns the first key with a value < target.
1107
+ * Equivalent to Java TreeMap.lower.
1108
+ * Time Complexity: O(log n) average, O(h) worst case.
1109
+ * Space Complexity: O(h) for recursion, O(1) for iteration.
1110
+ */
1111
+ lower(
1112
+ keyNodeEntryOrPredicate:
1113
+ | K
1114
+ | BSTNode<K, V>
1115
+ | [K | null | undefined, V | undefined]
1116
+ | null
1117
+ | undefined
1118
+ | NodePredicate<BSTNode<K, V>>
1119
+ ): K | undefined;
1120
+
1121
+ /**
1122
+ * Returns the first node with a key < target and applies callback.
1123
+ * Time Complexity: O(log n) average, O(h) worst case.
1124
+ * Space Complexity: O(h) for recursion, O(1) for iteration.
1125
+ */
1126
+ lower<C extends NodeCallback<BSTNode<K, V>>>(
1127
+ keyNodeEntryOrPredicate:
1128
+ | K
1129
+ | BSTNode<K, V>
1130
+ | [K | null | undefined, V | undefined]
1131
+ | null
1132
+ | undefined
1133
+ | NodePredicate<BSTNode<K, V>>,
1134
+ callback: C,
1135
+ iterationType?: IterationType
1136
+ ): ReturnType<C>;
1137
+
1138
+ lower<C extends NodeCallback<BSTNode<K, V>>>(
1139
+ keyNodeEntryOrPredicate:
1140
+ | K
1141
+ | BSTNode<K, V>
1142
+ | [K | null | undefined, V | undefined]
1143
+ | null
1144
+ | undefined
1145
+ | NodePredicate<BSTNode<K, V>>,
1146
+ callback?: C | IterationType,
1147
+ iterationType?: IterationType
1148
+ ): K | undefined | ReturnType<C> {
1149
+ if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined) {
1150
+ if (typeof callback === 'string' || !callback) {
1151
+ return undefined;
1152
+ }
1153
+ return undefined;
1154
+ }
1155
+
1156
+ let actualCallback: C | undefined = undefined;
1157
+ let actualIterationType: IterationType = this.iterationType;
1158
+
1159
+ if (typeof callback === 'string') {
1160
+ actualIterationType = callback;
1161
+ } else if (callback) {
1162
+ actualCallback = callback;
1163
+ if (iterationType) {
1164
+ actualIterationType = iterationType;
1165
+ }
1166
+ }
1167
+
1168
+ if (this._isPredicate(keyNodeEntryOrPredicate)) {
1169
+ const node = this._lowerByPredicate(keyNodeEntryOrPredicate, actualIterationType);
1170
+
1171
+ if (!actualCallback) {
1172
+ return node?.key;
1173
+ }
1174
+
1175
+ return node ? actualCallback(node) : undefined;
1176
+ }
1177
+
1178
+ let targetKey: K | undefined;
1179
+ if (this.isNode(keyNodeEntryOrPredicate)) {
1180
+ targetKey = keyNodeEntryOrPredicate.key;
1181
+ } else if (this.isEntry(keyNodeEntryOrPredicate)) {
1182
+ const key = keyNodeEntryOrPredicate[0];
1183
+ if (key === null || key === undefined) {
1184
+ if (typeof callback === 'string' || !callback) {
1185
+ return undefined;
1186
+ }
1187
+ return undefined;
1188
+ }
1189
+ targetKey = key;
1190
+ } else {
1191
+ targetKey = keyNodeEntryOrPredicate;
1192
+ }
1193
+
1194
+ if (targetKey !== undefined) {
1195
+ const node = this._lowerByKey(targetKey, actualIterationType);
1196
+
1197
+ if (!actualCallback) {
1198
+ return node?.key;
1199
+ }
1200
+
1201
+ return node ? actualCallback(node) : undefined;
1202
+ }
1203
+
1204
+ if (typeof callback === 'string' || !callback) {
1205
+ return undefined;
1206
+ }
1207
+ return undefined;
1208
+ }
1209
+
1210
+ lesserOrGreaterTraverse(): (K | undefined)[];
1211
+
1212
+ lesserOrGreaterTraverse<C extends NodeCallback<BSTNode<K, V>>>(
1213
+ callback: C,
1214
+ lesserOrGreater?: number,
1215
+ targetNode?: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
1216
+ iterationType?: IterationType
1217
+ ): ReturnType<C>[];
1218
+
1219
+ /**
1220
+ * Traverses the tree and returns nodes that are lesser or greater than a target node.
1221
+ * @remarks Time O(N), as it performs a full traversal. Space O(log N) or O(N).
1222
+ *
1223
+ * @template C - The type of the callback function.
1224
+ * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on matching nodes.
1225
+ * @param [lesserOrGreater=-1] - -1 for lesser, 1 for greater, 0 for equal.
1226
+ * @param [targetNode=this._root] - The node to compare against.
1227
+ * @param [iterationType=this.iterationType] - The traversal method.
1228
+ * @returns An array of callback results.
1229
+ */
1230
+ lesserOrGreaterTraverse<C extends NodeCallback<BSTNode<K, V>>>(
1231
+ callback: C = this._DEFAULT_NODE_CALLBACK as C,
1232
+ lesserOrGreater: CP = -1,
1233
+ targetNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
1234
+ iterationType: IterationType = this.iterationType
1235
+ ): ReturnType<C>[] {
1236
+ const targetNodeEnsured = this.ensureNode(targetNode);
1237
+ const ans: ReturnType<NodeCallback<BSTNode<K, V>>>[] = [];
1238
+ if (!this._root || !targetNodeEnsured) return ans;
1239
+
1240
+ const targetKey = targetNodeEnsured.key;
1241
+
1242
+ if (iterationType === 'RECURSIVE') {
1243
+ const dfs = (cur: BSTNode<K, V>) => {
1244
+ const compared = this._compare(cur.key, targetKey);
1245
+ if (Math.sign(compared) == lesserOrGreater) ans.push(callback(cur));
1246
+
1247
+ if (this.isRealNode(cur.left)) dfs(cur.left);
1248
+ if (this.isRealNode(cur.right)) dfs(cur.right);
1249
+ };
1250
+ dfs(this._root);
1251
+ return ans;
1252
+ } else {
1253
+ const queue = new Queue<BSTNode<K, V>>([this._root]);
1254
+ while (queue.length > 0) {
1255
+ const cur = queue.shift();
1256
+ if (this.isRealNode(cur)) {
1257
+ const compared = this._compare(cur.key, targetKey);
1258
+ if (Math.sign(compared) == lesserOrGreater) ans.push(callback(cur));
1259
+ if (this.isRealNode(cur.left)) queue.push(cur.left);
1260
+ if (this.isRealNode(cur.right)) queue.push(cur.right);
1261
+ }
1262
+ }
1263
+ return ans;
1264
+ }
1265
+ }
1266
+
1267
+ /**
1268
+ * Rebuilds the tree to be perfectly balanced.
1269
+ * @remarks Time O(N) (O(N) for DFS, O(N) for sorted build). Space O(N) for node array and recursion stack.
1270
+ *
1271
+ * @param [iterationType=this.iterationType] - The traversal method for the initial node export.
1272
+ * @returns True if successful, false if the tree was empty.
1273
+ */
1274
+ perfectlyBalance(iterationType: IterationType = this.iterationType): boolean {
1275
+ const nodes = this.dfs(node => node, 'IN', false, this._root, iterationType);
1276
+ const n = nodes.length;
1277
+ this._clearNodes();
1278
+ if (n === 0) return false;
1279
+
1280
+ // Build balanced tree from sorted array
1281
+ const build = (l: number, r: number, parent?: BSTNode<K, V>): BSTNode<K, V> | undefined => {
1282
+ if (l > r) return undefined;
1283
+ const m = l + ((r - l) >> 1);
1284
+ const root = nodes[m]! as BSTNode<K, V>;
1285
+ const leftChild = build(l, m - 1, root);
1286
+ const rightChild = build(m + 1, r, root);
1287
+ root.left = leftChild;
1288
+ root.right = rightChild;
1289
+ root.parent = parent;
1290
+ return root;
1291
+ };
1292
+
1293
+ const newRoot = build(0, n - 1, undefined);
1294
+ this._setRoot(newRoot);
1295
+ this._size = n;
1296
+ return true;
1297
+ }
1298
+
1299
+ /**
1300
+ * Checks if the tree meets the AVL balance condition (height difference <= 1).
1301
+ * @remarks Time O(N), as it must visit every node to compute height. Space O(log N) for recursion or O(N) for iterative map.
1302
+ *
1303
+ * @param [iterationType=this.iterationType] - The traversal method.
1304
+ * @returns True if the tree is AVL balanced, false otherwise.
1305
+ */
1306
+ isAVLBalanced(iterationType: IterationType = this.iterationType): boolean {
1307
+ if (!this._root) return true;
1308
+ let balanced = true;
1309
+
1310
+ if (iterationType === 'RECURSIVE') {
1311
+ // Recursive height check
1312
+ const _height = (cur: BSTNode<K, V> | null | undefined): number => {
1313
+ if (!cur) return 0;
1314
+ const leftHeight = _height(cur.left);
1315
+ const rightHeight = _height(cur.right);
1316
+ if (Math.abs(leftHeight - rightHeight) > 1) balanced = false;
1317
+ return Math.max(leftHeight, rightHeight) + 1;
1318
+ };
1319
+ _height(this._root);
1320
+ } else {
1321
+ // Iterative post-order height check
1322
+ const stack: BSTNode<K, V>[] = [];
1323
+ let node: OptNode<BSTNode<K, V>> = this._root,
1324
+ last: OptNode<BSTNode<K, V>> = undefined;
1325
+ const depths: Map<BSTNode<K, V>, number> = new Map();
1326
+
1327
+ while (stack.length > 0 || node) {
1328
+ if (node) {
1329
+ stack.push(node);
1330
+ if (node.left !== null) node = node.left;
1331
+ } else {
1332
+ node = stack[stack.length - 1];
1333
+ if (!node.right || last === node.right) {
1334
+ node = stack.pop();
1335
+ if (node) {
1336
+ const left = node.left ? depths.get(node.left)! : -1;
1337
+ const right = node.right ? depths.get(node.right)! : -1;
1338
+ if (Math.abs(left - right) > 1) return false;
1339
+ depths.set(node, 1 + Math.max(left, right));
1340
+ last = node;
1341
+ node = undefined;
1342
+ }
1343
+ } else node = node.right;
1344
+ }
1345
+ }
1346
+ }
1347
+ return balanced;
1348
+ }
1349
+
1350
+ /**
1351
+ * Creates a new BST by mapping each [key, value] pair to a new entry.
1352
+ * @remarks Time O(N * H), where N is nodes in this tree, and H is height of the new tree during insertion.
1353
+ * Space O(N) for the new tree.
1354
+ *
1355
+ * @template MK - New key type.
1356
+ * @template MV - New value type.
1357
+ * @template MR - New raw type.
1358
+ * @param callback - A function to map each [key, value] pair.
1359
+ * @param [options] - Options for the new BST.
1360
+ * @param [thisArg] - `this` context for the callback.
1361
+ * @returns A new, mapped BST.
1362
+ */
1363
+ override map<MK = K, MV = V, MR = any>(
1364
+ callback: EntryCallback<K, V | undefined, [MK, MV]>,
1365
+ options?: Partial<BSTOptions<MK, MV, MR>>,
1366
+ thisArg?: unknown
1367
+ ): BST<MK, MV, MR> {
1368
+ const out = this._createLike<MK, MV, MR>([], options);
1369
+ let index = 0;
1370
+ // Iterates in-order
1371
+ for (const [key, value] of this) {
1372
+ out.set(callback.call(thisArg, value, key, index++, this));
1373
+ }
1374
+ return out;
1375
+ }
1376
+
1377
+ /**
1378
+ * Deletes nodes that match a key, node, entry, predicate, or range.
1379
+ *
1380
+ * @remarks
1381
+ * Time Complexity: O(N) for search + O(M log N) for M deletions, where N is tree size.
1382
+ * Space Complexity: O(M) for storing matched nodes and result map.
1383
+ *
1384
+ * @template K - The key type.
1385
+ * @template V - The value type.
1386
+ *
1387
+ * @param keyNodeEntryOrPredicate - The search criteria. Can be one of:
1388
+ * - A key (type K): searches for exact key match using the comparator.
1389
+ * - A BSTNode: searches for the matching node in the tree.
1390
+ * - An entry tuple: searches for the key-value pair.
1391
+ * - A NodePredicate function: tests each node and returns true for matches.
1392
+ * - A Range object: searches for nodes whose keys fall within the specified range (inclusive/exclusive based on range settings).
1393
+ * - null or undefined: treated as no match, returns empty results.
1394
+ *
1395
+ * @param onlyOne - If true, stops the search after finding the first match and only deletes that one node.
1396
+ * If false (default), searches for and deletes all matching nodes.
1397
+ *
1398
+ * @param startNode - The node to start the search from. Can be:
1399
+ * - A key, node, or entry: the method resolves it to a node and searches from that subtree.
1400
+ * - null or undefined: defaults to the root, searching the entire tree.
1401
+ * - Default value: this._root (the tree's root).
1402
+ *
1403
+ * @param iterationType - Controls the internal traversal implementation:
1404
+ * - 'RECURSIVE': uses recursive function calls for traversal.
1405
+ * - 'ITERATIVE': uses explicit stack-based iteration.
1406
+ * - Default: this.iterationType (the tree's default iteration mode).
1407
+ *
1408
+ * @returns A Map<K, boolean> containing the deletion results:
1409
+ * - Key: the matched node's key.
1410
+ * - Value: true if the deletion succeeded, false if it failed (e.g., key not found during deletion phase).
1411
+ * - If no nodes match the search criteria, the returned map is empty.
1412
+ */
1413
+ deleteWhere(
1414
+ keyNodeEntryOrPredicate:
1415
+ | K
1416
+ | BSTNode<K, V>
1417
+ | [K | null | undefined, V | undefined]
1418
+ | null
1419
+ | undefined
1420
+ | NodePredicate<BSTNode<K, V>>
1421
+ | Range<K>,
1422
+ onlyOne = false,
1423
+ startNode: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined = this._root,
1424
+ iterationType: IterationType = this.iterationType
1425
+ ): BinaryTreeDeleteResult<BSTNode<K, V>>[] {
1426
+ const toDelete = this.search(keyNodeEntryOrPredicate, onlyOne, node => node, startNode, iterationType);
1427
+
1428
+ let results: BinaryTreeDeleteResult<BSTNode<K, V>>[] = [];
1429
+ for (const node of toDelete) {
1430
+ const deleteInfo = this.delete(node);
1431
+ results = results.concat(deleteInfo);
1432
+ }
1433
+
1434
+ return results;
1435
+ }
1436
+
1437
+ /**
1438
+ * (Protected) Creates the default comparator function for keys that don't have a custom comparator.
1439
+ * @remarks Time O(1) Space O(1)
1440
+ * @returns The default comparator function.
1441
+ */
1442
+ protected _createDefaultComparator(): Comparator<K> {
1443
+ return (a: K, b: K): number => {
1444
+ // If both keys are comparable (primitive types), use direct comparison
1445
+ if (isComparable(a) && isComparable(b)) {
1446
+ if (a > b) return 1;
1447
+ if (a < b) return -1;
1448
+ return 0;
1449
+ }
1450
+
1451
+ // If keys are objects and no comparator is provided, throw an error
1452
+ if (typeof a === 'object' || typeof b === 'object') {
1453
+ throw TypeError(
1454
+ `When comparing object type keys, a custom comparator must be provided in the constructor's options!`
1455
+ );
1456
+ }
1457
+
1458
+ // Default: keys are equal (fallback case)
1459
+ return 0;
1460
+ };
1461
+ }
1462
+
1463
+ /**
1464
+ * (Protected) Binary search for floor by key with pruning optimization.
1465
+ * Performs standard BST binary search, choosing left or right subtree based on comparator result.
1466
+ * Finds first node where key <= target.
1467
+ * @remarks Time O(h) where h is tree height.
1468
+ *
1469
+ * @param key - The target key to search for.
1470
+ * @param iterationType - The iteration type (RECURSIVE or ITERATIVE).
1471
+ * @returns The first node with key <= target, or undefined if none exists.
1472
+ */
1473
+ protected _floorByKey(key: K, iterationType: IterationType): BSTNode<K, V> | undefined {
1474
+ if (iterationType === 'RECURSIVE') {
1475
+ // Recursive binary search implementation
1476
+ const dfs = (cur: BSTNode<K, V> | null | undefined): BSTNode<K, V> | undefined => {
1477
+ if (!this.isRealNode(cur)) return undefined;
1478
+
1479
+ const cmp = this.comparator(cur.key!, key);
1480
+
1481
+ if (cmp <= 0) {
1482
+ // Current node satisfies the floor condition (cur.key <= target).
1483
+ // Try to find a larger candidate in the right subtree.
1484
+ const rightResult = dfs(cur.right);
1485
+ return rightResult ?? cur;
1486
+ } else {
1487
+ // Current node is too large, move left to find smaller keys.
1488
+ return dfs(cur.left);
1489
+ }
1490
+ };
1491
+
1492
+ return dfs(this.root);
1493
+ } else {
1494
+ // Iterative binary search implementation
1495
+ let current: BSTNode<K, V> | undefined = this.root;
1496
+ let result: BSTNode<K, V> | undefined = undefined;
1497
+
1498
+ while (this.isRealNode(current)) {
1499
+ const cmp = this.comparator(current.key!, key);
1500
+
1501
+ if (cmp <= 0) {
1502
+ // Current node is a candidate. Save it and try right subtree for a larger key.
1503
+ result = current;
1504
+ current = current.right ?? undefined;
1505
+ } else {
1506
+ // Current node is too large, move left.
1507
+ current = current.left ?? undefined;
1508
+ }
1509
+ }
1510
+
1511
+ return result;
1512
+ }
1513
+ }
1514
+
1515
+ /**
1516
+ * (Protected) In-order traversal search for floor by predicate.
1517
+ * Falls back to linear in-order traversal when predicate-based search is required.
1518
+ * Returns the last node that satisfies the predicate function.
1519
+ * @remarks Time Complexity: O(n) since it may visit every node.
1520
+ * Space Complexity: O(h) for recursion, O(h) for iterative stack.
1521
+ *
1522
+ * @param predicate - The predicate function to test nodes.
1523
+ * @param iterationType - The iteration type (RECURSIVE or ITERATIVE).
1524
+ * @returns The last node satisfying predicate (highest key), or undefined if none found.
1525
+ */
1526
+ protected _floorByPredicate(
1527
+ predicate: NodePredicate<BSTNode<K, V>>,
1528
+ iterationType: IterationType
1529
+ ): BSTNode<K, V> | undefined {
1530
+ if (iterationType === 'RECURSIVE') {
1531
+ // Recursive in-order traversal
1532
+ let result: BSTNode<K, V> | undefined = undefined;
1533
+
1534
+ const dfs = (cur: BSTNode<K, V> | null | undefined): void => {
1535
+ if (!this.isRealNode(cur)) return;
1536
+
1537
+ // In-order: process left subtree first
1538
+ if (this.isRealNode(cur.left)) dfs(cur.left);
1539
+
1540
+ // Check current node
1541
+ if (predicate(cur)) {
1542
+ result = cur;
1543
+ }
1544
+
1545
+ // Process right subtree
1546
+ if (this.isRealNode(cur.right)) dfs(cur.right);
1547
+ };
1548
+
1549
+ dfs(this.root);
1550
+ return result;
1551
+ } else {
1552
+ // Iterative in-order traversal using explicit stack
1553
+ const stack: (BSTNode<K, V> | null | undefined)[] = [];
1554
+ let current: BSTNode<K, V> | null | undefined = this.root;
1555
+ let result: BSTNode<K, V> | undefined = undefined;
1556
+
1557
+ while (stack.length > 0 || this.isRealNode(current)) {
1558
+ if (this.isRealNode(current)) {
1559
+ // Go to the leftmost node
1560
+ stack.push(current);
1561
+ current = current.left;
1562
+ } else {
1563
+ // Pop from stack and process
1564
+ const node = stack.pop();
1565
+ if (!this.isRealNode(node)) break;
1566
+
1567
+ // Check if current node satisfies predicate
1568
+ if (predicate(node)) {
1569
+ result = node;
1570
+ }
1571
+
1572
+ // Visit right subtree
1573
+ current = node.right;
1574
+ }
1575
+ }
1576
+
1577
+ return result;
1578
+ }
1579
+ }
1580
+
1581
+ /**
1582
+ * (Protected) Binary search for lower by key with pruning optimization.
1583
+ * Performs standard BST binary search, choosing left or right subtree based on comparator result.
1584
+ * Finds first node where key < target.
1585
+ * @remarks Time O(h) where h is tree height.
1586
+ *
1587
+ * @param key - The target key to search for.
1588
+ * @param iterationType - The iteration type (RECURSIVE or ITERATIVE).
1589
+ * @returns The first node with key < target, or undefined if none exists.
1590
+ */
1591
+ protected _lowerByKey(key: K, iterationType: IterationType): BSTNode<K, V> | undefined {
1592
+ if (iterationType === 'RECURSIVE') {
1593
+ // Recursive binary search implementation
1594
+ const dfs = (cur: BSTNode<K, V> | null | undefined): BSTNode<K, V> | undefined => {
1595
+ if (!this.isRealNode(cur)) return undefined;
1596
+
1597
+ const cmp = this.comparator(cur.key!, key);
1598
+
1599
+ if (cmp < 0) {
1600
+ // Current node satisfies the lower condition (cur.key < target).
1601
+ // Try to find a larger candidate in the right subtree.
1602
+ const rightResult = dfs(cur.right);
1603
+ return rightResult ?? cur;
1604
+ } else {
1605
+ // Current node is too large or equal, move left to find smaller keys.
1606
+ return dfs(cur.left);
1607
+ }
1608
+ };
1609
+
1610
+ return dfs(this.root);
1611
+ } else {
1612
+ // Iterative binary search implementation
1613
+ let current: BSTNode<K, V> | undefined = this.root;
1614
+ let result: BSTNode<K, V> | undefined = undefined;
1615
+
1616
+ while (this.isRealNode(current)) {
1617
+ const cmp = this.comparator(current.key!, key);
1618
+
1619
+ if (cmp < 0) {
1620
+ // Current node is a candidate. Save it and try right subtree for a larger key.
1621
+ result = current;
1622
+ current = current.right ?? undefined;
1623
+ } else {
1624
+ // Current node is too large or equal, move left.
1625
+ current = current.left ?? undefined;
1626
+ }
1627
+ }
1628
+
1629
+ return result;
1630
+ }
1631
+ }
1632
+
1633
+ /**
1634
+ * (Protected) In-order traversal search for lower by predicate.
1635
+ * Falls back to linear in-order traversal when predicate-based search is required.
1636
+ * Returns the node that satisfies the predicate and appears last in in-order traversal.
1637
+ * @remarks Time Complexity: O(n) since it may visit every node.
1638
+ * Space Complexity: O(h) for recursion, O(h) for iterative stack.
1639
+ *
1640
+ * @param predicate - The predicate function to test nodes.
1641
+ * @param iterationType - The iteration type (RECURSIVE or ITERATIVE).
1642
+ * @returns The last node satisfying predicate (highest key < target), or undefined if none found.
1643
+ */
1644
+ protected _lowerByPredicate(
1645
+ predicate: NodePredicate<BSTNode<K, V>>,
1646
+ iterationType: IterationType
1647
+ ): BSTNode<K, V> | undefined {
1648
+ if (iterationType === 'RECURSIVE') {
1649
+ // Recursive in-order traversal
1650
+ let result: BSTNode<K, V> | undefined = undefined;
1651
+
1652
+ const dfs = (cur: BSTNode<K, V> | null | undefined): void => {
1653
+ if (!this.isRealNode(cur)) return;
1654
+
1655
+ // In-order: process left subtree first
1656
+ if (this.isRealNode(cur.left)) dfs(cur.left);
1657
+
1658
+ // Check current node
1659
+ if (predicate(cur)) {
1660
+ result = cur;
1661
+ }
1662
+
1663
+ // Process right subtree
1664
+ if (this.isRealNode(cur.right)) dfs(cur.right);
1665
+ };
1666
+
1667
+ dfs(this.root);
1668
+ return result;
1669
+ } else {
1670
+ // Iterative in-order traversal using explicit stack
1671
+ const stack: (BSTNode<K, V> | null | undefined)[] = [];
1672
+ let current: BSTNode<K, V> | null | undefined = this.root;
1673
+ let result: BSTNode<K, V> | undefined = undefined;
1674
+
1675
+ while (stack.length > 0 || this.isRealNode(current)) {
1676
+ if (this.isRealNode(current)) {
1677
+ // Go to the leftmost node
1678
+ stack.push(current);
1679
+ current = current.left;
1680
+ } else {
1681
+ // Pop from stack and process
1682
+ const node = stack.pop();
1683
+ if (!this.isRealNode(node)) break;
1684
+
1685
+ // Check if current node satisfies predicate
1686
+ if (predicate(node)) {
1687
+ result = node;
1688
+ }
1689
+
1690
+ // Visit right subtree
1691
+ current = node.right;
1692
+ }
1693
+ }
1694
+
1695
+ return result;
1696
+ }
1697
+ }
1698
+
1699
+ /**
1700
+ * (Protected) Core bound search implementation supporting all parameter types.
1701
+ * Unified logic for both lowerBound and upperBound.
1702
+ * Resolves various input types (Key, Node, Entry, Predicate) using parent class utilities.
1703
+ * @param keyNodeEntryOrPredicate - The key, node, entry, or predicate function to search for.
1704
+ * @param isLower - True for lowerBound (>=), false for upperBound (>).
1705
+ * @param iterationType - The iteration type (RECURSIVE or ITERATIVE).
1706
+ * @returns The first matching node, or undefined if no such node exists.
1707
+ */
1708
+ protected _bound(
1709
+ keyNodeEntryOrPredicate:
1710
+ | K
1711
+ | BSTNode<K, V>
1712
+ | [K | null | undefined, V | undefined]
1713
+ | null
1714
+ | undefined
1715
+ | NodePredicate<BSTNode<K, V>>,
1716
+ isLower: boolean,
1717
+ iterationType: IterationType
1718
+ ): BSTNode<K, V> | undefined {
1719
+ if (keyNodeEntryOrPredicate === null || keyNodeEntryOrPredicate === undefined) {
1720
+ return undefined;
1721
+ }
1722
+
1723
+ // Check if input is a predicate function first
1724
+ if (this._isPredicate(keyNodeEntryOrPredicate)) {
1725
+ return this._boundByPredicate(keyNodeEntryOrPredicate, iterationType);
1726
+ }
1727
+
1728
+ // Resolve input to a comparable key
1729
+ let targetKey: K | undefined;
1730
+
1731
+ if (this.isNode(keyNodeEntryOrPredicate)) {
1732
+ // Input is a BSTNode - extract its key
1733
+ targetKey = keyNodeEntryOrPredicate.key;
1734
+ } else if (this.isEntry(keyNodeEntryOrPredicate)) {
1735
+ // Input is a [key, value] entry - extract the key
1736
+ const key = keyNodeEntryOrPredicate[0];
1737
+ if (key === null || key === undefined) {
1738
+ return undefined;
1739
+ }
1740
+ targetKey = key;
1741
+ } else {
1742
+ // Input is a raw key
1743
+ targetKey = keyNodeEntryOrPredicate;
1744
+ }
1745
+
1746
+ // Execute key-based search with binary search optimization
1747
+ if (targetKey !== undefined) {
1748
+ return this._boundByKey(targetKey, isLower, iterationType);
1749
+ }
1750
+
1751
+ return undefined;
1752
+ }
1753
+
1754
+ /**
1755
+ * (Protected) Binary search for bound by key with pruning optimization.
1756
+ * Performs standard BST binary search, choosing left or right subtree based on comparator result.
1757
+ * For lowerBound: finds first node where key >= target.
1758
+ * For upperBound: finds first node where key > target.
1759
+ * @param key - The target key to search for.
1760
+ * @param isLower - True for lowerBound (>=), false for upperBound (>).
1761
+ * @param iterationType - The iteration type (RECURSIVE or ITERATIVE).
1762
+ * @returns The first node matching the bound condition, or undefined if none exists.
1763
+ */
1764
+ protected _boundByKey(key: K, isLower: boolean, iterationType: IterationType): BSTNode<K, V> | undefined {
1765
+ if (iterationType === 'RECURSIVE') {
1766
+ // Recursive binary search implementation
1767
+ const dfs = (cur: BSTNode<K, V> | null | undefined): BSTNode<K, V> | undefined => {
1768
+ if (!this.isRealNode(cur)) return undefined;
1769
+
1770
+ const cmp = this.comparator(cur.key!, key);
1771
+ const condition = isLower ? cmp >= 0 : cmp > 0;
1772
+
1773
+ if (condition) {
1774
+ // Current node satisfies the bound condition.
1775
+ // Try to find a closer (smaller key) candidate in the left subtree.
1776
+ const leftResult = dfs(cur.left);
1777
+ return leftResult ?? cur;
1778
+ } else {
1779
+ // Current node does not satisfy the condition.
1780
+ // Move right to find larger keys.
1781
+ return dfs(cur.right);
1782
+ }
1783
+ };
1784
+
1785
+ return dfs(this.root);
1786
+ } else {
1787
+ // Iterative binary search implementation
1788
+ let current: BSTNode<K, V> | undefined = this.root;
1789
+ let result: BSTNode<K, V> | undefined = undefined;
1790
+
1791
+ while (this.isRealNode(current)) {
1792
+ const cmp = this.comparator(current.key!, key);
1793
+ const condition = isLower ? cmp >= 0 : cmp > 0;
1794
+
1795
+ if (condition) {
1796
+ // Current node is a candidate. Save it and try left subtree for a closer match.
1797
+ result = current;
1798
+ current = current.left ?? undefined;
1799
+ } else {
1800
+ // Move right to find larger keys.
1801
+ current = current.right ?? undefined;
1802
+ }
1803
+ }
1804
+
1805
+ return result;
1806
+ }
1807
+ }
1808
+
1809
+ /**
1810
+ * (Protected) In-order traversal search by predicate.
1811
+ * Falls back to linear in-order traversal when predicate-based search is required.
1812
+ * Returns the first node that satisfies the predicate function.
1813
+ * Note: Predicate-based search cannot leverage BST's binary search optimization.
1814
+ * Time Complexity: O(n) since it may visit every node.
1815
+ * @param predicate - The predicate function to test nodes.
1816
+ * @param iterationType - The iteration type (RECURSIVE or ITERATIVE).
1817
+ * @returns The first node satisfying predicate, or undefined if none found.
1818
+ */
1819
+ protected _boundByPredicate(
1820
+ predicate: NodePredicate<BSTNode<K, V>>,
1821
+ iterationType: IterationType
1822
+ ): BSTNode<K, V> | undefined {
1823
+ if (iterationType === 'RECURSIVE') {
1824
+ // Recursive in-order traversal
1825
+ let result: BSTNode<K, V> | undefined = undefined;
1826
+
1827
+ const dfs = (cur: BSTNode<K, V> | null | undefined): void => {
1828
+ if (result || !this.isRealNode(cur)) return;
1829
+
1830
+ // In-order: process left subtree first
1831
+ if (this.isRealNode(cur.left)) dfs(cur.left);
1832
+
1833
+ // Check current node
1834
+ if (!result && predicate(cur)) {
1835
+ result = cur;
1836
+ }
1837
+
1838
+ // Process right subtree
1839
+ if (!result && this.isRealNode(cur.right)) dfs(cur.right);
1840
+ };
1841
+
1842
+ dfs(this.root);
1843
+ return result;
1844
+ } else {
1845
+ // Iterative in-order traversal using explicit stack
1846
+ const stack: (BSTNode<K, V> | null | undefined)[] = [];
1847
+ let current: BSTNode<K, V> | null | undefined = this.root;
1848
+
1849
+ while (stack.length > 0 || this.isRealNode(current)) {
1850
+ if (this.isRealNode(current)) {
1851
+ // Go to the leftmost node
1852
+ stack.push(current);
1853
+ current = current.left;
1854
+ } else {
1855
+ // Pop from stack and process
1856
+ const node = stack.pop();
1857
+ if (!this.isRealNode(node)) break;
1858
+
1859
+ // Check if current node satisfies predicate
1860
+ if (predicate(node)) {
1861
+ return node;
1862
+ }
1863
+
1864
+ // Visit right subtree
1865
+ current = node.right;
1866
+ }
1867
+ }
1868
+
1869
+ return undefined;
1870
+ }
1871
+ }
1872
+
1873
+ /**
1874
+ * (Protected) Creates a new, empty instance of the same BST constructor.
1875
+ * @remarks Time O(1)
1876
+ *
1877
+ * @template TK, TV, TR - Generic types for the new instance.
1878
+ * @param [options] - Options for the new BST.
1879
+ * @returns A new, empty BST.
1880
+ */
1881
+ protected override _createInstance<TK = K, TV = V, TR = R>(options?: Partial<BSTOptions<TK, TV, TR>>): this {
1882
+ const Ctor = this.constructor as unknown as new (
1883
+ iter?: Iterable<TK | BSTNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR>,
1884
+ opts?: BSTOptions<TK, TV, TR>
1885
+ ) => BST<TK, TV, TR>;
1886
+ return new Ctor([], { ...this._snapshotOptions<TK, TV, TR>(), ...(options ?? {}) }) as unknown as this;
1887
+ }
1888
+
1889
+ /**
1890
+ * (Protected) Creates a new instance of the same BST constructor, potentially with different generic types.
1891
+ * @remarks Time O(N log N) or O(N^2) (from constructor) due to processing the iterable.
1892
+ *
1893
+ * @template TK, TV, TR - Generic types for the new instance.
1894
+ * @param [iter=[]] - An iterable to populate the new BST.
1895
+ * @param [options] - Options for the new BST.
1896
+ * @returns A new BST.
1897
+ */
1898
+ protected override _createLike<TK = K, TV = V, TR = R>(
1899
+ iter: Iterable<TK | BSTNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR> = [],
1900
+ options?: Partial<BSTOptions<TK, TV, TR>>
1901
+ ): BST<TK, TV, TR> {
1902
+ const Ctor = this.constructor as unknown as new (
1903
+ iter?: Iterable<TK | BSTNode<TK, TV> | [TK | null | undefined, TV | undefined] | null | undefined | TR>,
1904
+ opts?: BSTOptions<TK, TV, TR>
1905
+ ) => BST<TK, TV, TR>;
1906
+ return new Ctor(iter, { ...this._snapshotOptions<TK, TV, TR>(), ...(options ?? {}) });
1907
+ }
1908
+
1909
+ /**
1910
+ * (Protected) Snapshots the current BST's configuration options.
1911
+ * @remarks Time O(1)
1912
+ *
1913
+ * @template TK, TV, TR - Generic types for the options.
1914
+ * @returns The options object.
1915
+ */
1916
+ protected override _snapshotOptions<TK = K, TV = V, TR = R>(): BSTOptions<TK, TV, TR> {
1917
+ return {
1918
+ ...super._snapshotOptions<TK, TV, TR>(),
1919
+ comparator: this._comparator as unknown as BSTOptions<TK, TV, TR>['comparator']
1920
+ };
1921
+ }
1922
+
1923
+ /**
1924
+ * (Protected) Converts a key, node, or entry into a standardized [node, value] tuple.
1925
+ * @remarks Time O(1)
1926
+ *
1927
+ * @param keyNodeOrEntry - The input item.
1928
+ * @param [value] - An optional value (used if input is just a key).
1929
+ * @returns A tuple of [node, value].
1930
+ */
1931
+ protected override _keyValueNodeOrEntryToNodeAndValue(
1932
+ keyNodeOrEntry: K | BSTNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
1933
+ value?: V
1934
+ ): [OptNode<BSTNode<K, V>>, V | undefined] {
1935
+ const [node, entryValue] = super._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value);
1936
+ if (node === null) return [undefined, undefined]; // BST handles null differently (as undefined)
1937
+ return [node, value ?? entryValue];
1938
+ }
1939
+
1940
+ /**
1941
+ * (Protected) Sets the root node and clears its parent reference.
1942
+ * @remarks Time O(1)
1943
+ *
1944
+ * @param v - The node to set as root.
1945
+ */
1946
+ protected override _setRoot(v: OptNode<BSTNode<K, V>>) {
1947
+ if (v) v.parent = undefined;
1948
+ this._root = v;
1949
+ }
1950
+
1951
+ /**
1952
+ * (Protected) Compares two keys using the tree's comparator and reverse setting.
1953
+ * @remarks Time O(1) Space O(1)
1954
+ *
1955
+ * @param a - The first key.
1956
+ * @param b - The second key.
1957
+ * @returns A number (1, -1, or 0) representing the comparison.
1958
+ */
1959
+ protected _compare(a: K, b: K) {
1960
+ return this._comparator(a, b);
1961
+ }
1962
+
1963
+ /**
1964
+ * (Private) Deletes a node by its key.
1965
+ * @remarks Standard BST deletion algorithm. Time O(log N), O(N) worst-case. Space O(1).
1966
+ *
1967
+ * @param key - The key of the node to delete.
1968
+ * @returns True if the node was found and deleted, false otherwise.
1969
+ */
1970
+ protected _deleteByKey(key: K): boolean {
1971
+ let node = this._root as BSTNode<K, V> | undefined;
1972
+
1973
+ // 1. Find the node
1974
+ while (node) {
1975
+ const cmp = this._compare(node.key, key);
1976
+ if (cmp === 0) break;
1977
+ node = cmp > 0 ? (node.left as BSTNode<K, V> | undefined) : (node.right as BSTNode<K, V> | undefined);
1978
+ }
1979
+ if (!node) return false; // Not found
1980
+
1981
+ // Helper to replace node `u` with node `v`
1982
+ const transplant = (u: BSTNode<K, V> | undefined, v: BSTNode<K, V> | undefined) => {
1983
+ const p = u?.parent as BSTNode<K, V> | undefined;
1984
+ if (!p) {
1985
+ this._setRoot(v);
1986
+ } else if (p.left === u) {
1987
+ p.left = v;
1988
+ } else {
1989
+ p.right = v;
1990
+ }
1991
+ if (v) v.parent = p;
1992
+ };
1993
+
1994
+ // Helper to find the minimum node in a subtree
1995
+ const minNode = (x: BSTNode<K, V> | undefined): BSTNode<K, V> | undefined => {
1996
+ if (!x) return undefined;
1997
+ while (x.left !== undefined && x.left !== null) x = x.left as BSTNode<K, V>;
1998
+ return x;
1999
+ };
2000
+
2001
+ // 2. Perform deletion
2002
+ if (node.left === undefined) {
2003
+ // Case 1: No left child
2004
+ transplant(node, node.right as BSTNode<K, V> | undefined);
2005
+ } else if (node.right === undefined) {
2006
+ // Case 2: No right child
2007
+ transplant(node, node.left as BSTNode<K, V> | undefined);
2008
+ } else {
2009
+ // Case 3: Two children
2010
+ const succ = minNode(node.right as BSTNode<K, V> | undefined)!; // Find successor
2011
+ if (succ.parent !== node) {
2012
+ transplant(succ, succ.right as BSTNode<K, V> | undefined);
2013
+ succ.right = node.right as BSTNode<K, V> | undefined;
2014
+ if (succ.right) (succ.right as BSTNode<K, V>).parent = succ;
2015
+ }
2016
+ transplant(node, succ);
2017
+ succ.left = node.left as BSTNode<K, V> | undefined;
2018
+ if (succ.left) (succ.left as BSTNode<K, V>).parent = succ;
2019
+ }
2020
+
2021
+ this._size = Math.max(0, ((this as any)._size ?? 0) - 1);
2022
+ return true;
2023
+ }
2024
+ }