data-structure-typed 1.53.6 → 1.53.8

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 (161) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +16 -25
  3. package/benchmark/report.html +32 -5
  4. package/benchmark/report.json +326 -23
  5. package/dist/cjs/common/index.d.ts +12 -0
  6. package/dist/cjs/common/index.js +29 -0
  7. package/dist/cjs/common/index.js.map +1 -0
  8. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +1 -1
  9. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +9 -12
  10. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  11. package/dist/cjs/data-structures/binary-tree/avl-tree.js +2 -2
  12. package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
  13. package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +55 -20
  14. package/dist/cjs/data-structures/binary-tree/binary-tree.js +102 -68
  15. package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  16. package/dist/cjs/data-structures/binary-tree/bst.d.ts +131 -37
  17. package/dist/cjs/data-structures/binary-tree/bst.js +222 -69
  18. package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
  19. package/dist/cjs/data-structures/binary-tree/index.d.ts +1 -1
  20. package/dist/cjs/data-structures/binary-tree/index.js +1 -1
  21. package/dist/cjs/data-structures/binary-tree/index.js.map +1 -1
  22. package/dist/{mjs/data-structures/binary-tree/rb-tree.d.ts → cjs/data-structures/binary-tree/red-black-tree.d.ts} +56 -0
  23. package/dist/cjs/data-structures/binary-tree/{rb-tree.js → red-black-tree.js} +60 -4
  24. package/dist/cjs/data-structures/binary-tree/red-black-tree.js.map +1 -0
  25. package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
  26. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +7 -7
  27. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  28. package/dist/cjs/data-structures/hash/hash-map.d.ts +30 -0
  29. package/dist/cjs/data-structures/hash/hash-map.js +30 -0
  30. package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
  31. package/dist/cjs/data-structures/heap/heap.d.ts +26 -9
  32. package/dist/cjs/data-structures/heap/heap.js +37 -17
  33. package/dist/cjs/data-structures/heap/heap.js.map +1 -1
  34. package/dist/cjs/data-structures/linked-list/doubly-linked-list.d.ts +54 -9
  35. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js +80 -19
  36. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  37. package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +35 -2
  38. package/dist/cjs/data-structures/linked-list/singly-linked-list.js +55 -11
  39. package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
  40. package/dist/cjs/data-structures/queue/deque.d.ts +37 -8
  41. package/dist/cjs/data-structures/queue/deque.js +73 -29
  42. package/dist/cjs/data-structures/queue/deque.js.map +1 -1
  43. package/dist/cjs/data-structures/queue/queue.d.ts +41 -1
  44. package/dist/cjs/data-structures/queue/queue.js +51 -9
  45. package/dist/cjs/data-structures/queue/queue.js.map +1 -1
  46. package/dist/cjs/data-structures/stack/stack.d.ts +27 -10
  47. package/dist/cjs/data-structures/stack/stack.js +39 -20
  48. package/dist/cjs/data-structures/stack/stack.js.map +1 -1
  49. package/dist/cjs/data-structures/trie/trie.d.ts +111 -6
  50. package/dist/cjs/data-structures/trie/trie.js +123 -14
  51. package/dist/cjs/data-structures/trie/trie.js.map +1 -1
  52. package/dist/cjs/index.d.ts +1 -1
  53. package/dist/cjs/index.js +1 -1
  54. package/dist/cjs/index.js.map +1 -1
  55. package/dist/cjs/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
  56. package/dist/cjs/types/data-structures/binary-tree/bst.d.ts +3 -2
  57. package/dist/cjs/types/data-structures/binary-tree/rb-tree.d.ts +1 -1
  58. package/dist/cjs/types/utils/utils.d.ts +10 -6
  59. package/dist/cjs/utils/utils.js +4 -2
  60. package/dist/cjs/utils/utils.js.map +1 -1
  61. package/dist/mjs/common/index.d.ts +12 -0
  62. package/dist/mjs/common/index.js +29 -0
  63. package/dist/mjs/common/index.js.map +1 -0
  64. package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +1 -1
  65. package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.js +10 -12
  66. package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  67. package/dist/mjs/data-structures/binary-tree/avl-tree.js +3 -2
  68. package/dist/mjs/data-structures/binary-tree/avl-tree.js.map +1 -1
  69. package/dist/mjs/data-structures/binary-tree/binary-tree.d.ts +55 -20
  70. package/dist/mjs/data-structures/binary-tree/binary-tree.js +97 -63
  71. package/dist/mjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  72. package/dist/mjs/data-structures/binary-tree/bst.d.ts +131 -37
  73. package/dist/mjs/data-structures/binary-tree/bst.js +224 -69
  74. package/dist/mjs/data-structures/binary-tree/bst.js.map +1 -1
  75. package/dist/mjs/data-structures/binary-tree/index.d.ts +1 -1
  76. package/dist/mjs/data-structures/binary-tree/index.js +1 -1
  77. package/dist/mjs/data-structures/binary-tree/index.js.map +1 -1
  78. package/dist/{cjs/data-structures/binary-tree/rb-tree.d.ts → mjs/data-structures/binary-tree/red-black-tree.d.ts} +56 -0
  79. package/dist/mjs/data-structures/binary-tree/{rb-tree.js → red-black-tree.js} +60 -4
  80. package/dist/mjs/data-structures/binary-tree/red-black-tree.js.map +1 -0
  81. package/dist/mjs/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
  82. package/dist/mjs/data-structures/binary-tree/tree-multi-map.js +5 -5
  83. package/dist/mjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  84. package/dist/mjs/data-structures/hash/hash-map.d.ts +30 -0
  85. package/dist/mjs/data-structures/hash/hash-map.js +30 -0
  86. package/dist/mjs/data-structures/hash/hash-map.js.map +1 -1
  87. package/dist/mjs/data-structures/heap/heap.d.ts +26 -9
  88. package/dist/mjs/data-structures/heap/heap.js +37 -17
  89. package/dist/mjs/data-structures/heap/heap.js.map +1 -1
  90. package/dist/mjs/data-structures/linked-list/doubly-linked-list.d.ts +54 -9
  91. package/dist/mjs/data-structures/linked-list/doubly-linked-list.js +80 -19
  92. package/dist/mjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  93. package/dist/mjs/data-structures/linked-list/singly-linked-list.d.ts +35 -2
  94. package/dist/mjs/data-structures/linked-list/singly-linked-list.js +55 -11
  95. package/dist/mjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
  96. package/dist/mjs/data-structures/queue/deque.d.ts +37 -8
  97. package/dist/mjs/data-structures/queue/deque.js +73 -29
  98. package/dist/mjs/data-structures/queue/deque.js.map +1 -1
  99. package/dist/mjs/data-structures/queue/queue.d.ts +41 -1
  100. package/dist/mjs/data-structures/queue/queue.js +51 -9
  101. package/dist/mjs/data-structures/queue/queue.js.map +1 -1
  102. package/dist/mjs/data-structures/stack/stack.d.ts +27 -10
  103. package/dist/mjs/data-structures/stack/stack.js +39 -20
  104. package/dist/mjs/data-structures/stack/stack.js.map +1 -1
  105. package/dist/mjs/data-structures/trie/trie.d.ts +111 -6
  106. package/dist/mjs/data-structures/trie/trie.js +123 -14
  107. package/dist/mjs/data-structures/trie/trie.js.map +1 -1
  108. package/dist/mjs/index.d.ts +1 -1
  109. package/dist/mjs/index.js +1 -1
  110. package/dist/mjs/index.js.map +1 -1
  111. package/dist/mjs/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
  112. package/dist/mjs/types/data-structures/binary-tree/bst.d.ts +3 -2
  113. package/dist/mjs/types/data-structures/binary-tree/rb-tree.d.ts +1 -1
  114. package/dist/mjs/types/utils/utils.d.ts +10 -6
  115. package/dist/mjs/utils/utils.js +4 -2
  116. package/dist/mjs/utils/utils.js.map +1 -1
  117. package/dist/umd/data-structure-typed.js +671 -246
  118. package/dist/umd/data-structure-typed.min.js +3 -3
  119. package/dist/umd/data-structure-typed.min.js.map +1 -1
  120. package/package.json +7 -7
  121. package/src/common/index.ts +25 -0
  122. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +9 -11
  123. package/src/data-structures/binary-tree/avl-tree.ts +3 -2
  124. package/src/data-structures/binary-tree/binary-tree.ts +110 -66
  125. package/src/data-structures/binary-tree/bst.ts +232 -72
  126. package/src/data-structures/binary-tree/index.ts +1 -1
  127. package/src/data-structures/binary-tree/{rb-tree.ts → red-black-tree.ts} +56 -3
  128. package/src/data-structures/binary-tree/tree-multi-map.ts +6 -6
  129. package/src/data-structures/hash/hash-map.ts +30 -0
  130. package/src/data-structures/heap/heap.ts +72 -49
  131. package/src/data-structures/linked-list/doubly-linked-list.ts +173 -105
  132. package/src/data-structures/linked-list/singly-linked-list.ts +61 -11
  133. package/src/data-structures/queue/deque.ts +72 -28
  134. package/src/data-structures/queue/queue.ts +50 -7
  135. package/src/data-structures/stack/stack.ts +39 -20
  136. package/src/data-structures/trie/trie.ts +123 -13
  137. package/src/index.ts +1 -1
  138. package/src/types/data-structures/binary-tree/binary-tree.ts +1 -1
  139. package/src/types/data-structures/binary-tree/bst.ts +3 -2
  140. package/src/types/data-structures/binary-tree/rb-tree.ts +1 -1
  141. package/src/types/utils/utils.ts +16 -10
  142. package/src/utils/utils.ts +4 -2
  143. package/test/performance/data-structures/binary-tree/avl-tree.test.ts +3 -0
  144. package/test/performance/data-structures/binary-tree/rb-tree.test.ts +4 -1
  145. package/test/performance/reportor.ts +38 -33
  146. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +2 -2
  147. package/test/unit/data-structures/binary-tree/binary-tree.test.ts +47 -47
  148. package/test/unit/data-structures/binary-tree/bst.test.ts +114 -44
  149. package/test/unit/data-structures/binary-tree/overall.test.ts +14 -22
  150. package/test/unit/data-structures/binary-tree/{rb-tree.test.ts → red-black-tree.test.ts} +55 -1
  151. package/test/unit/data-structures/trie/trie.test.ts +151 -0
  152. package/test/unit/utils/utils.test.ts +6 -6
  153. package/dist/cjs/constants/index.d.ts +0 -4
  154. package/dist/cjs/constants/index.js +0 -9
  155. package/dist/cjs/constants/index.js.map +0 -1
  156. package/dist/cjs/data-structures/binary-tree/rb-tree.js.map +0 -1
  157. package/dist/mjs/constants/index.d.ts +0 -4
  158. package/dist/mjs/constants/index.js +0 -6
  159. package/dist/mjs/constants/index.js.map +0 -1
  160. package/dist/mjs/data-structures/binary-tree/rb-tree.js.map +0 -1
  161. package/src/constants/index.ts +0 -4
@@ -7,17 +7,23 @@ export type SpecifyOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T,
7
7
 
8
8
  export type Any = string | number | bigint | boolean | symbol | undefined | object;
9
9
 
10
+ export type Arithmetic = number | bigint;
11
+
10
12
  export type ComparablePrimitive = number | bigint | string | boolean;
11
13
 
12
- // TODO type safety looks not strict
13
- export type ComparableObject = { [key in string]: any } & (
14
- | {
15
- valueOf: () => ComparablePrimitive | ComparableObject;
16
- toString?: () => string;
17
- }
18
- | {
19
- toString: () => string;
20
- }
21
- );
14
+ export interface BaseComparableObject {
15
+ [key: string]: unknown;
16
+ }
17
+
18
+ export interface ValueComparableObject extends BaseComparableObject {
19
+ valueOf: () => ComparablePrimitive | ValueComparableObject;
20
+ toString?: () => string;
21
+ }
22
+
23
+ export interface StringComparableObject extends BaseComparableObject {
24
+ toString: () => string;
25
+ }
26
+
27
+ export type ComparableObject = ValueComparableObject | StringComparableObject;
22
28
 
23
29
  export type Comparable = ComparablePrimitive | Date | ComparableObject;
@@ -226,7 +226,8 @@ export const roundFixed = (num: number, digit: number = 10) => {
226
226
  */
227
227
  function isPrimitiveComparable(value: unknown): value is ComparablePrimitive {
228
228
  const valueType = typeof value;
229
- if (valueType === 'number') return !Number.isNaN(value);
229
+ if (valueType === 'number') return true;
230
+ // if (valueType === 'number') return !Number.isNaN(value);
230
231
  return valueType === 'bigint' || valueType === 'string' || valueType === 'boolean';
231
232
  }
232
233
 
@@ -274,7 +275,8 @@ export function isComparable(value: unknown, isForceObjectComparable = false): v
274
275
  if (isPrimitiveComparable(value)) return true;
275
276
 
276
277
  if (typeof value !== 'object') return false;
277
- if (value instanceof Date) return !Number.isNaN(value.getTime());
278
+ if (value instanceof Date) return true;
279
+ // if (value instanceof Date) return !Number.isNaN(value.getTime());
278
280
  if (isForceObjectComparable) return true;
279
281
  const comparableValue = tryObjectToPrimitive(value);
280
282
  if (comparableValue === null || comparableValue === undefined) return false;
@@ -19,6 +19,9 @@ suite
19
19
  .add(`${HUNDRED_THOUSAND.toLocaleString()} get`, () => {
20
20
  for (let i = 0; i < randomArray.length; i++) avlTree.get(randomArray[i]);
21
21
  })
22
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} getNode`, () => {
23
+ for (let i = 0; i < randomArray.length; i++) avlTree.getNode(randomArray[i]);
24
+ })
22
25
  .add(`${HUNDRED_THOUSAND.toLocaleString()} iterator`, () => {
23
26
  const entries = [...avlTree];
24
27
  return entries.length === HUNDRED_THOUSAND;
@@ -23,9 +23,12 @@ suite
23
23
  .add(`${HUNDRED_THOUSAND.toLocaleString()} get`, () => {
24
24
  for (let i = 0; i < randomArray.length; i++) rbTree.get(randomArray[i]);
25
25
  })
26
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} getNode`, () => {
27
+ for (let i = 0; i < randomArray.length; i++) rbTree.getNode(randomArray[i]);
28
+ })
26
29
  .add(`${HUNDRED_THOUSAND.toLocaleString()} node mode add randomly`, () => {
27
30
  rbTreeNodeMode.clear();
28
- for (let i = 0; i < randomArray.length; i++) rbTree.add(randomArray[i]);
31
+ for (let i = 0; i < randomArray.length; i++) rbTreeNodeMode.add(randomArray[i]);
29
32
  })
30
33
  .add(`${HUNDRED_THOUSAND.toLocaleString()} node mode get`, () => {
31
34
  for (let i = 0; i < randomArray.length; i++) rbTreeNodeMode.get(randomArray[i]);
@@ -8,6 +8,22 @@ import { PerformanceTest } from './types';
8
8
  const args = process.argv.slice(2);
9
9
 
10
10
  const { GREEN, BOLD, END, YELLOW, GRAY, CYAN, BG_YELLOW } = ConsoleColor;
11
+ const isOnlyOrdered = true;
12
+ const runOrder = [
13
+ 'heap',
14
+ 'avl-tree',
15
+ 'rb-tree',
16
+ 'doubly-linked-list',
17
+ 'directed-graph',
18
+ 'queue',
19
+ 'deque',
20
+ 'hash-map',
21
+ 'trie',
22
+ 'stack'
23
+ // 'singly-linked-list',
24
+ // 'priority-queue',
25
+ // 'binary-tree-overall'
26
+ ];
11
27
 
12
28
  const getRelativePath = (file: string) => {
13
29
  return path.relative(__dirname, file);
@@ -80,7 +96,7 @@ const composeReport = () => {
80
96
  #json-to-html {
81
97
  padding: 0 10px 20px;
82
98
  }
83
-
99
+
84
100
  .json-to-html-label {
85
101
  font-size: 2rem;
86
102
  margin: 2rem 0 0 3px;
@@ -92,19 +108,19 @@ const composeReport = () => {
92
108
  margin-top: 10px;
93
109
  font-size: 16px;
94
110
  }
95
-
111
+
96
112
  .content table th,
97
113
  .content table td {
98
114
  padding: 8px 12px;
99
115
  text-align: left;
100
116
  border: 1px solid #ddd;
101
117
  }
102
-
118
+
103
119
  .content table th {
104
120
  background-color: #f2f2f2;
105
121
  font-weight: bold;
106
122
  }
107
-
123
+
108
124
  .content table tr:nth-child(odd) {
109
125
  background-color: #ffffff;
110
126
  }
@@ -188,46 +204,35 @@ function replaceMarkdownContent(startMarker: string, endMarker: string, newText:
188
204
  });
189
205
  }
190
206
 
191
- const order = [
192
- 'heap',
193
- 'rb-tree',
194
- 'queue',
195
- 'deque',
196
- 'hash-map',
197
- 'trie',
198
- 'avl-tree',
199
- 'binary-tree-overall',
200
- 'directed-graph',
201
- 'doubly-linked-list',
202
- 'singly-linked-list',
203
- 'priority-queue',
204
- 'stack'
205
- ];
206
-
207
- const sortedPerformanceTests = [...performanceTests].sort((a, b) => {
208
- const indexA = order.indexOf(a.testName);
209
- const indexB = order.indexOf(b.testName);
207
+ const sortedPerformanceTests = (
208
+ isOnlyOrdered ? [...performanceTests].filter(test => runOrder.includes(test.testName)) : [...performanceTests]
209
+ ).sort((a, b) => {
210
+ const indexA = runOrder.indexOf(a.testName);
211
+ const indexB = runOrder.indexOf(b.testName);
210
212
 
211
- // If both a and b are in the order, sort them according to their indices in the order.
213
+ // If both a and b are in the runOrder, sort them according to their indices in the runOrder.
212
214
  if (indexA !== -1 && indexB !== -1) {
213
215
  return indexA - indexB;
214
216
  }
215
217
 
216
- // If there is only 'a' in the order, then place 'b' in front.
218
+ // If there is only 'a' in the runOrder, then place 'b' in front.
217
219
  if (indexA !== -1) {
218
220
  return 1;
219
221
  }
220
222
 
221
- // If only b is in the order, then a should be placed before it.
223
+ // If only b is in the runOrder, then a should be placed before it.
222
224
  if (indexB !== -1) {
223
225
  return -1;
224
226
  }
225
227
 
226
- // If neither a nor b are in order, keep their original order
228
+ // If neither a nor b are in runOrder, keep their original runOrder
227
229
  return 0;
228
230
  });
229
231
 
230
- console.log(`${GREEN} Found tests${END}: ${sortedPerformanceTests.map(test => test.testName)}`);
232
+ console.log(`${GREEN} Found tests (${performanceTests.length})${END}: ${performanceTests.map(test => test.testName)}`);
233
+ console.log(
234
+ `${GREEN} Running tests (${sortedPerformanceTests.length})${END}: ${sortedPerformanceTests.map(test => test.testName)}`
235
+ );
231
236
 
232
237
  sortedPerformanceTests.forEach(item => {
233
238
  const { suite, testName, file } = item;
@@ -245,22 +250,22 @@ sortedPerformanceTests.forEach(item => {
245
250
  return {
246
251
  'test name': benchmark.name,
247
252
  'time taken (ms)': numberFix(benchmark.times.period * 1000, 2),
248
- 'executions per sec': numberFix(benchmark.hz, 2),
253
+ // 'executions per sec': numberFix(benchmark.hz, 2),
249
254
  // 'executed times': numberFix(benchmark.count, 0),
250
- // 'sample mean (secs)': numberFix(benchmark.stats.mean, 2),
255
+ 'sample mean (secs)': numberFix(benchmark.stats.mean, 2),
251
256
  'sample deviation': numberFix(benchmark.stats.deviation, 2)
252
257
  };
253
258
  });
254
259
 
255
260
  report[testName].testName = testName;
256
- const isDone = completedCount === performanceTests.length;
261
+ const isDone = completedCount === sortedPerformanceTests.length;
257
262
  runTime = Number(runTime.toFixed(2));
258
263
  const isTimeWarn = runTime > 120;
259
264
  console.log(
260
265
  // `Files: ${GREEN}${testFileCount}${END} `,
261
266
  // `Suites: ${GREEN}${performanceTests.length}${END} `,
262
- `Suites Progress: ${isDone ? GREEN : YELLOW}${completedCount}${END}/${isDone ? GREEN : YELLOW}${performanceTests.length}${END}`,
263
- `Time: ${isTimeWarn ? YELLOW : GREEN}${runTime}s${END}`
267
+ `Suites Progress: ${isDone ? GREEN : YELLOW}${completedCount}${END}/${isDone ? GREEN : YELLOW}${sortedPerformanceTests.length}${END}`,
268
+ `Time Costs: ${isTimeWarn ? YELLOW : GREEN}${runTime}s${END}`
264
269
  );
265
270
  if (isDone) {
266
271
  composeReport();
@@ -736,7 +736,7 @@ describe('AVLTree toEntryFn', () => {
736
736
  { obj: { id: 5 } }
737
737
  ])
738
738
  ).toThrowError(
739
- `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
739
+ `When comparing object types, a custom extractComparable must be defined in the constructor's options parameter.`
740
740
  );
741
741
  });
742
742
 
@@ -744,7 +744,7 @@ describe('AVLTree toEntryFn', () => {
744
744
  const tree = new AVLTreeMultiMap<{ obj: { id: number } }, number>(
745
745
  [{ obj: { id: 1 } }, { obj: { id: 2 } }, { obj: { id: 3 } }, { obj: { id: 4 } }, { obj: { id: 5 } }],
746
746
  {
747
- comparator: (a, b) => a.obj.id - b.obj.id
747
+ extractComparable: key => key.obj.id
748
748
  }
749
749
  );
750
750
 
@@ -103,9 +103,9 @@ describe('BinaryTree addMany', () => {
103
103
  [undefined, 22, 44, 33]
104
104
  );
105
105
  expect(tree.get(2)).toBe(22);
106
- expect(tree.get(tree.getNodeByKey(3))).toBe(33);
107
- expect(tree.get(tree.getNodeByKey(4))).toBe(44);
108
- expect(tree.get(tree.getNodeByKey(1))).toBe(1);
106
+ expect(tree.get(tree.getNode(3))).toBe(33);
107
+ expect(tree.get(tree.getNode(4))).toBe(44);
108
+ expect(tree.get(tree.getNode(1))).toBe(1);
109
109
  });
110
110
 
111
111
  it('should addMany undefined and null', () => {
@@ -349,7 +349,7 @@ describe('BinaryTree', () => {
349
349
  expect(tree.isBST(tree.getNode(4), 'ITERATIVE')).toBe(true);
350
350
  expect(tree.getNodes(2, false, null)).toEqual([]);
351
351
  expect(tree.getNodes(undefined)).toEqual([]);
352
- expect(tree.getNodes(tree.getNodeByKey(2), false, tree.root)).toEqual([tree.getNodeByKey(2)]);
352
+ expect(tree.getNodes(tree.getNode(2), false, tree.root)).toEqual([tree.getNode(2)]);
353
353
  });
354
354
 
355
355
  describe('should isKey', () => {
@@ -362,9 +362,9 @@ describe('BinaryTree', () => {
362
362
  expect(tree.isKey(-Infinity)).toBe(true);
363
363
  });
364
364
 
365
- it('NaN should not be a key', () => {
366
- expect(tree.isKey(NaN)).toBe(false);
367
- });
365
+ // it('NaN should not be a key', () => {
366
+ // expect(tree.isKey(NaN)).toBe(false);
367
+ // });
368
368
 
369
369
  it('strings should be a key', () => {
370
370
  expect(tree.isKey('hello')).toBe(true);
@@ -400,9 +400,9 @@ describe('BinaryTree', () => {
400
400
  expect(tree.isKey(new Date('2024-01-01'))).toBe(true);
401
401
  });
402
402
 
403
- it('invalid Date objects should not be a key', () => {
404
- expect(tree.isKey(new Date('invalid'))).toBe(false);
405
- });
403
+ // it('invalid Date objects should not be a key', () => {
404
+ // expect(tree.isKey(new Date('invalid'))).toBe(false);
405
+ // });
406
406
  });
407
407
 
408
408
  describe('arrays', () => {
@@ -733,41 +733,41 @@ describe('BinaryTree', () => {
733
733
  ]);
734
734
  });
735
735
 
736
- it('should keyValueNodeEntryRawToNodeAndValue', () => {
737
- const tree = new BinaryTree<number>();
738
- const node0 = tree.keyValueNodeEntryRawToNodeAndValue(0);
739
- expect(node0).toEqual([
740
- {
741
- _left: undefined,
742
- _right: undefined,
743
- key: 0,
744
- parent: undefined,
745
- value: undefined
746
- },
747
- undefined
748
- ]);
749
-
750
- const nodeUndefined = tree.keyValueNodeEntryRawToNodeAndValue(undefined);
751
- expect(nodeUndefined).toEqual([undefined, undefined]);
752
-
753
- const nodeNull = tree.keyValueNodeEntryRawToNodeAndValue(null);
754
- expect(nodeNull).toEqual([null, undefined]);
755
-
756
- const [, nodeWithSeparateValue] = tree.keyValueNodeEntryRawToNodeAndValue(7, 77);
757
- expect(nodeWithSeparateValue).toBe(77);
758
-
759
- expect(tree.keyValueNodeEntryRawToNodeAndValue([undefined, 2])).toEqual([undefined, undefined]);
760
-
761
- expect(tree.keyValueNodeEntryRawToNodeAndValue(Symbol('test') as unknown as number)).toEqual([
762
- undefined,
763
- undefined
764
- ]);
765
-
766
- const bTree = new BinaryTree<number, number, { obj: { id: number } }>([], {
767
- toEntryFn: (ele: { obj: { id: number } }) => [Symbol('test') as unknown as number, ele.obj.id]
768
- });
769
- expect(bTree.keyValueNodeEntryRawToNodeAndValue({ obj: { id: 1 } })).toEqual([undefined, undefined]);
770
- });
736
+ // it('should keyValueNodeEntryRawToNodeAndValue', () => {
737
+ // const tree = new BinaryTree<number>();
738
+ // const node0 = tree.keyValueNodeEntryRawToNodeAndValue(0);
739
+ // expect(node0).toEqual([
740
+ // {
741
+ // _left: undefined,
742
+ // _right: undefined,
743
+ // key: 0,
744
+ // parent: undefined,
745
+ // value: undefined
746
+ // },
747
+ // undefined
748
+ // ]);
749
+ //
750
+ // const nodeUndefined = tree.keyValueNodeEntryRawToNodeAndValue(undefined);
751
+ // expect(nodeUndefined).toEqual([undefined, undefined]);
752
+ //
753
+ // const nodeNull = tree.keyValueNodeEntryRawToNodeAndValue(null);
754
+ // expect(nodeNull).toEqual([null, undefined]);
755
+ //
756
+ // const [, nodeWithSeparateValue] = tree.keyValueNodeEntryRawToNodeAndValue(7, 77);
757
+ // expect(nodeWithSeparateValue).toBe(77);
758
+ //
759
+ // expect(tree.keyValueNodeEntryRawToNodeAndValue([undefined, 2])).toEqual([undefined, undefined]);
760
+ //
761
+ // expect(tree.keyValueNodeEntryRawToNodeAndValue(Symbol('test') as unknown as number)).toEqual([
762
+ // undefined,
763
+ // undefined
764
+ // ]);
765
+ //
766
+ // const bTree = new BinaryTree<number, number, { obj: { id: number } }>([], {
767
+ // toEntryFn: (ele: { obj: { id: number } }) => [Symbol('test') as unknown as number, ele.obj.id]
768
+ // });
769
+ // expect(bTree.keyValueNodeEntryRawToNodeAndValue({ obj: { id: 1 } })).toEqual([undefined, undefined]);
770
+ // });
771
771
 
772
772
  it('should replace value', () => {
773
773
  const tree = new BinaryTree<number, string>([4, 5, [1, '1'], 2, 3], { isMapMode: false });
@@ -1155,8 +1155,8 @@ describe('BinaryTree', () => {
1155
1155
  tree.add([3, 'B']);
1156
1156
  tree.add([7, 'C']);
1157
1157
 
1158
- expect(tree.getPathToRoot(undefined, 7)).toEqual([5, 7]);
1159
- expect(tree.getPathToRoot(undefined, 1)).toEqual([]);
1158
+ expect(tree.getPathToRoot(7)).toEqual([7, 5]);
1159
+ expect(tree.getPathToRoot(1)).toEqual([]);
1160
1160
  });
1161
1161
 
1162
1162
  it('should check if the tree is perfectly balanced', () => {
@@ -1,4 +1,4 @@
1
- import { BinaryTreeNode, BST, BSTNode } from '../../../../src';
1
+ import { BinaryTreeNode, BST, BSTNode, Range } from '../../../../src';
2
2
  import { isDebugTest, isTestStackOverflow, SYSTEM_MAX_CALL_STACK } from '../../../config';
3
3
 
4
4
  const isDebug = isDebugTest;
@@ -58,7 +58,7 @@ describe('BST operations test', () => {
58
58
  [10, 10],
59
59
  [5, 5]
60
60
  ];
61
- bst.addMany(idsAndValues, undefined, false);
61
+ bst.addMany(idsAndValues, [], false);
62
62
  expect(bst.root).toBeInstanceOf(BSTNode);
63
63
 
64
64
  if (bst.root) expect(bst.root.key).toBe(11);
@@ -450,26 +450,26 @@ describe('BST operations test', () => {
450
450
  expect(bfsNodes[2].key).toBe(16);
451
451
  });
452
452
 
453
- it('should keyValueNodeEntryRawToNodeAndValue', () => {
454
- const bst = new BST<number>();
455
- const node0 = bst.keyValueNodeEntryRawToNodeAndValue(0);
456
- expect(node0).toEqual([
457
- {
458
- _left: undefined,
459
- _right: undefined,
460
- key: 0,
461
- parent: undefined,
462
- value: undefined
463
- },
464
- undefined
465
- ]);
466
-
467
- const nodeUndefined = bst.keyValueNodeEntryRawToNodeAndValue(undefined);
468
- expect(nodeUndefined).toEqual([undefined, undefined]);
469
-
470
- const nodeNull = bst.keyValueNodeEntryRawToNodeAndValue(null);
471
- expect(nodeNull).toEqual([undefined, undefined]);
472
- });
453
+ // it('should keyValueNodeEntryRawToNodeAndValue', () => {
454
+ // const bst = new BST<number>();
455
+ // const node0 = bst.keyValueNodeEntryRawToNodeAndValue(0);
456
+ // expect(node0).toEqual([
457
+ // {
458
+ // _left: undefined,
459
+ // _right: undefined,
460
+ // key: 0,
461
+ // parent: undefined,
462
+ // value: undefined
463
+ // },
464
+ // undefined
465
+ // ]);
466
+ //
467
+ // const nodeUndefined = bst.keyValueNodeEntryRawToNodeAndValue(undefined);
468
+ // expect(nodeUndefined).toEqual([undefined, undefined]);
469
+ //
470
+ // const nodeNull = bst.keyValueNodeEntryRawToNodeAndValue(null);
471
+ // expect(nodeNull).toEqual([undefined, undefined]);
472
+ // });
473
473
 
474
474
  it('should replace value', () => {
475
475
  const tree = new BST<number, string>([4, 5, [1, '1'], 2, 3], { isMapMode: false });
@@ -489,6 +489,13 @@ describe('BST operations test', () => {
489
489
  expect(treeMap.getNode(1)?.value).toBe(undefined);
490
490
  expect(treeMap.get(1)).toBe('b');
491
491
  });
492
+
493
+ it('should search in range', () => {
494
+ const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);
495
+ expect(bst.rangeSearch([4, 12])).toEqual([10, 12, 5, 7]);
496
+ expect(() => bst.rangeSearch([12, 4])).toThrow('low must be less than or equal to high');
497
+ expect(bst.rangeSearch([12, 12])).toEqual([12]);
498
+ });
492
499
  });
493
500
 
494
501
  describe('BST operations test recursively', () => {
@@ -974,7 +981,7 @@ describe('BST operations test recursively', () => {
974
981
 
975
982
  if (isTestStackOverflow) {
976
983
  it('should getLeftMost', () => {
977
- const bst = new BST<number>([], { comparator: (a, b) => b - a });
984
+ const bst = new BST<number>([], { extractComparable: key => key });
978
985
  for (let i = 1; i <= SYSTEM_MAX_CALL_STACK; i++) bst.add(i);
979
986
 
980
987
  expect(() => {
@@ -1009,7 +1016,7 @@ describe('BST isBST', function () {
1009
1016
 
1010
1017
  it('isBST when variant is Max', () => {
1011
1018
  const bst = new BST<number, number>([1, 2, 3, 9, 8, 5, 6, 7, 4], {
1012
- comparator: (a, b) => b - a
1019
+ isReverse: true
1013
1020
  });
1014
1021
  bst.addMany([1, 2, 3, 9, 8, 5, 6, 7, 4]);
1015
1022
  expect(bst.isBST()).toBe(true);
@@ -1340,26 +1347,26 @@ describe('BST operations not map mode test', () => {
1340
1347
  });
1341
1348
  });
1342
1349
 
1343
- it('should keyValueNodeEntryRawToNodeAndValue', () => {
1344
- const bst = new BST<number>([], { isMapMode: false });
1345
- const node0 = bst.keyValueNodeEntryRawToNodeAndValue(0);
1346
- expect(node0).toEqual([
1347
- {
1348
- _left: undefined,
1349
- _right: undefined,
1350
- key: 0,
1351
- parent: undefined,
1352
- value: undefined
1353
- },
1354
- undefined
1355
- ]);
1356
-
1357
- const nodeUndefined = bst.keyValueNodeEntryRawToNodeAndValue(undefined);
1358
- expect(nodeUndefined).toEqual([undefined, undefined]);
1359
-
1360
- const nodeNull = bst.keyValueNodeEntryRawToNodeAndValue(null);
1361
- expect(nodeNull).toEqual([undefined, undefined]);
1362
- });
1350
+ // it('should keyValueNodeEntryRawToNodeAndValue', () => {
1351
+ // const bst = new BST<number>([], { isMapMode: false });
1352
+ // const node0 = bst.keyValueNodeEntryRawToNodeAndValue(0);
1353
+ // expect(node0).toEqual([
1354
+ // {
1355
+ // _left: undefined,
1356
+ // _right: undefined,
1357
+ // key: 0,
1358
+ // parent: undefined,
1359
+ // value: undefined
1360
+ // },
1361
+ // undefined
1362
+ // ]);
1363
+ //
1364
+ // const nodeUndefined = bst.keyValueNodeEntryRawToNodeAndValue(undefined);
1365
+ // expect(nodeUndefined).toEqual([undefined, undefined]);
1366
+ //
1367
+ // const nodeNull = bst.keyValueNodeEntryRawToNodeAndValue(null);
1368
+ // expect(nodeNull).toEqual([undefined, undefined]);
1369
+ // });
1363
1370
  });
1364
1371
 
1365
1372
  describe('BST operations not map mode test recursively', () => {
@@ -1529,3 +1536,66 @@ describe('BST iterative methods not map mode test', () => {
1529
1536
  expect(balanced.leaves(node => balanced.get(node?.key))).toEqual(['a', 'f', 'd', 'i']);
1530
1537
  });
1531
1538
  });
1539
+
1540
+ describe('classic use', () => {
1541
+ it('@example Merge 3 sorted datasets', () => {
1542
+ const dataset1 = new BST<number, string>([
1543
+ [1, 'A'],
1544
+ [7, 'G']
1545
+ ]);
1546
+ const dataset2 = [
1547
+ [2, 'B'],
1548
+ [6, 'F']
1549
+ ];
1550
+ const dataset3 = new BST<number, string>([
1551
+ [3, 'C'],
1552
+ [5, 'E'],
1553
+ [4, 'D']
1554
+ ]);
1555
+
1556
+ // Merge datasets into a single BinarySearchTree
1557
+ const merged = new BST<number, string>(dataset1);
1558
+ merged.addMany(dataset2);
1559
+ merged.merge(dataset3);
1560
+
1561
+ // Verify merged dataset is in sorted order
1562
+ expect([...merged.values()]).toEqual(['A', 'B', 'C', 'D', 'E', 'F', 'G']);
1563
+ });
1564
+
1565
+ // Test case for finding elements in a given range
1566
+ it('@example Find elements in a range', () => {
1567
+ const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);
1568
+ expect(bst.search(new Range(5, 10))).toEqual([10, 5, 7]);
1569
+ expect(bst.rangeSearch([4, 12], node => node.key.toString())).toEqual(['10', '12', '5', '7']);
1570
+ expect(bst.search(new Range(4, 12, true, false))).toEqual([10, 5, 7]);
1571
+ expect(bst.rangeSearch([15, 20])).toEqual([15, 18]);
1572
+ expect(bst.search(new Range(15, 20, false))).toEqual([18]);
1573
+ });
1574
+
1575
+ // Test case for Lowest Common Ancestor (LCA)
1576
+ it('@example Find lowest common ancestor', () => {
1577
+ const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);
1578
+
1579
+ // LCA helper function
1580
+ const findLCA = (num1: number, num2: number): number | undefined => {
1581
+ const path1 = bst.getPathToRoot(num1);
1582
+ const path2 = bst.getPathToRoot(num2);
1583
+ // Find the first common ancestor
1584
+ return findFirstCommon(path1, path2);
1585
+ };
1586
+
1587
+ function findFirstCommon(arr1: number[], arr2: number[]): number | undefined {
1588
+ for (const num of arr1) {
1589
+ if (arr2.indexOf(num) !== -1) {
1590
+ return num;
1591
+ }
1592
+ }
1593
+ return undefined;
1594
+ }
1595
+
1596
+ // Assertions
1597
+ expect(findLCA(3, 10)).toBe(7);
1598
+ expect(findLCA(5, 35)).toBe(15);
1599
+ expect(findLCA(20, 30)).toBe(25);
1600
+ });
1601
+ });