data-structure-typed 1.53.5 → 1.53.7

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 (119) 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 +24 -0
  7. package/dist/cjs/common/index.js.map +1 -0
  8. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +7 -10
  9. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  10. package/dist/cjs/data-structures/binary-tree/avl-tree.js +2 -2
  11. package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
  12. package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +54 -19
  13. package/dist/cjs/data-structures/binary-tree/binary-tree.js +100 -66
  14. package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  15. package/dist/cjs/data-structures/binary-tree/bst.d.ts +100 -36
  16. package/dist/cjs/data-structures/binary-tree/bst.js +185 -66
  17. package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
  18. package/dist/cjs/data-structures/binary-tree/rb-tree.d.ts +4 -0
  19. package/dist/cjs/data-structures/binary-tree/rb-tree.js +6 -2
  20. package/dist/cjs/data-structures/binary-tree/rb-tree.js.map +1 -1
  21. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +2 -2
  22. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  23. package/dist/cjs/data-structures/heap/heap.d.ts +6 -6
  24. package/dist/cjs/data-structures/heap/heap.js +6 -6
  25. package/dist/cjs/data-structures/linked-list/doubly-linked-list.d.ts +31 -19
  26. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js +49 -34
  27. package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  28. package/dist/cjs/data-structures/linked-list/singly-linked-list.d.ts +144 -62
  29. package/dist/cjs/data-structures/linked-list/singly-linked-list.js +201 -97
  30. package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
  31. package/dist/cjs/data-structures/trie/trie.d.ts +110 -4
  32. package/dist/cjs/data-structures/trie/trie.js +122 -12
  33. package/dist/cjs/data-structures/trie/trie.js.map +1 -1
  34. package/dist/cjs/index.d.ts +1 -1
  35. package/dist/cjs/index.js +1 -1
  36. package/dist/cjs/index.js.map +1 -1
  37. package/dist/cjs/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
  38. package/dist/cjs/types/data-structures/binary-tree/bst.d.ts +3 -2
  39. package/dist/cjs/types/data-structures/binary-tree/rb-tree.d.ts +1 -1
  40. package/dist/cjs/types/utils/utils.d.ts +10 -6
  41. package/dist/cjs/utils/utils.js +4 -2
  42. package/dist/cjs/utils/utils.js.map +1 -1
  43. package/dist/mjs/common/index.d.ts +12 -0
  44. package/dist/mjs/common/index.js +24 -0
  45. package/dist/mjs/common/index.js.map +1 -0
  46. package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.js +8 -10
  47. package/dist/mjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  48. package/dist/mjs/data-structures/binary-tree/avl-tree.js +3 -2
  49. package/dist/mjs/data-structures/binary-tree/avl-tree.js.map +1 -1
  50. package/dist/mjs/data-structures/binary-tree/binary-tree.d.ts +54 -19
  51. package/dist/mjs/data-structures/binary-tree/binary-tree.js +95 -61
  52. package/dist/mjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  53. package/dist/mjs/data-structures/binary-tree/bst.d.ts +100 -36
  54. package/dist/mjs/data-structures/binary-tree/bst.js +187 -66
  55. package/dist/mjs/data-structures/binary-tree/bst.js.map +1 -1
  56. package/dist/mjs/data-structures/binary-tree/rb-tree.d.ts +4 -0
  57. package/dist/mjs/data-structures/binary-tree/rb-tree.js +6 -2
  58. package/dist/mjs/data-structures/binary-tree/rb-tree.js.map +1 -1
  59. package/dist/mjs/data-structures/binary-tree/tree-multi-map.js +2 -2
  60. package/dist/mjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  61. package/dist/mjs/data-structures/heap/heap.d.ts +6 -6
  62. package/dist/mjs/data-structures/heap/heap.js +6 -6
  63. package/dist/mjs/data-structures/linked-list/doubly-linked-list.d.ts +31 -19
  64. package/dist/mjs/data-structures/linked-list/doubly-linked-list.js +49 -34
  65. package/dist/mjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
  66. package/dist/mjs/data-structures/linked-list/singly-linked-list.d.ts +144 -62
  67. package/dist/mjs/data-structures/linked-list/singly-linked-list.js +201 -97
  68. package/dist/mjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
  69. package/dist/mjs/data-structures/trie/trie.d.ts +110 -4
  70. package/dist/mjs/data-structures/trie/trie.js +122 -12
  71. package/dist/mjs/data-structures/trie/trie.js.map +1 -1
  72. package/dist/mjs/index.d.ts +1 -1
  73. package/dist/mjs/index.js +1 -1
  74. package/dist/mjs/index.js.map +1 -1
  75. package/dist/mjs/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
  76. package/dist/mjs/types/data-structures/binary-tree/bst.d.ts +3 -2
  77. package/dist/mjs/types/data-structures/binary-tree/rb-tree.d.ts +1 -1
  78. package/dist/mjs/types/utils/utils.d.ts +10 -6
  79. package/dist/mjs/utils/utils.js +4 -2
  80. package/dist/mjs/utils/utils.js.map +1 -1
  81. package/dist/umd/data-structure-typed.js +512 -266
  82. package/dist/umd/data-structure-typed.min.js +2 -2
  83. package/dist/umd/data-structure-typed.min.js.map +1 -1
  84. package/package.json +8 -8
  85. package/src/common/index.ts +19 -0
  86. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +7 -9
  87. package/src/data-structures/binary-tree/avl-tree.ts +3 -2
  88. package/src/data-structures/binary-tree/binary-tree.ts +108 -64
  89. package/src/data-structures/binary-tree/bst.ts +190 -69
  90. package/src/data-structures/binary-tree/rb-tree.ts +6 -2
  91. package/src/data-structures/binary-tree/tree-multi-map.ts +3 -3
  92. package/src/data-structures/heap/heap.ts +39 -39
  93. package/src/data-structures/linked-list/doubly-linked-list.ts +139 -121
  94. package/src/data-structures/linked-list/singly-linked-list.ts +219 -98
  95. package/src/data-structures/trie/trie.ts +116 -11
  96. package/src/index.ts +1 -1
  97. package/src/types/data-structures/binary-tree/binary-tree.ts +1 -1
  98. package/src/types/data-structures/binary-tree/bst.ts +3 -2
  99. package/src/types/data-structures/binary-tree/rb-tree.ts +1 -1
  100. package/src/types/utils/utils.ts +16 -10
  101. package/src/utils/utils.ts +4 -2
  102. package/test/performance/data-structures/binary-tree/avl-tree.test.ts +3 -0
  103. package/test/performance/data-structures/binary-tree/rb-tree.test.ts +4 -1
  104. package/test/performance/reportor.ts +38 -33
  105. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +2 -2
  106. package/test/unit/data-structures/binary-tree/binary-tree.test.ts +12 -12
  107. package/test/unit/data-structures/binary-tree/bst.test.ts +79 -3
  108. package/test/unit/data-structures/binary-tree/overall.test.ts +14 -22
  109. package/test/unit/data-structures/binary-tree/rb-tree.test.ts +100 -1
  110. package/test/unit/data-structures/trie/trie.test.ts +151 -0
  111. package/test/unit/utils/utils.test.ts +6 -6
  112. package/dist/cjs/constants/index.d.ts +0 -4
  113. package/dist/cjs/constants/index.js +0 -9
  114. package/dist/cjs/constants/index.js.map +0 -1
  115. package/dist/mjs/constants/index.d.ts +0 -4
  116. package/dist/mjs/constants/index.js +0 -6
  117. package/dist/mjs/constants/index.js.map +0 -1
  118. package/src/constants/index.ts +0 -4
  119. package/testToExample.ts +0 -215
@@ -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', () => {
@@ -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;
@@ -974,7 +974,7 @@ describe('BST operations test recursively', () => {
974
974
 
975
975
  if (isTestStackOverflow) {
976
976
  it('should getLeftMost', () => {
977
- const bst = new BST<number>([], { comparator: (a, b) => b - a });
977
+ const bst = new BST<number>([], { extractComparable: key => key });
978
978
  for (let i = 1; i <= SYSTEM_MAX_CALL_STACK; i++) bst.add(i);
979
979
 
980
980
  expect(() => {
@@ -1009,7 +1009,7 @@ describe('BST isBST', function () {
1009
1009
 
1010
1010
  it('isBST when variant is Max', () => {
1011
1011
  const bst = new BST<number, number>([1, 2, 3, 9, 8, 5, 6, 7, 4], {
1012
- comparator: (a, b) => b - a
1012
+ isReverse: true
1013
1013
  });
1014
1014
  bst.addMany([1, 2, 3, 9, 8, 5, 6, 7, 4]);
1015
1015
  expect(bst.isBST()).toBe(true);
@@ -1529,3 +1529,79 @@ describe('BST iterative methods not map mode test', () => {
1529
1529
  expect(balanced.leaves(node => balanced.get(node?.key))).toEqual(['a', 'f', 'd', 'i']);
1530
1530
  });
1531
1531
  });
1532
+
1533
+ describe('classic use', () => {
1534
+ // Test case for finding the kth smallest element
1535
+ it('@example Find kth smallest element', () => {
1536
+ // Create a BST with some elements
1537
+ const bst = new BST<number>([5, 3, 7, 1, 4, 6, 8]);
1538
+ const sortedKeys = bst.dfs(node => node.key, 'IN');
1539
+
1540
+ // Helper function to find kth smallest
1541
+ const findKthSmallest = (k: number): number | undefined => {
1542
+ return sortedKeys[k - 1];
1543
+ };
1544
+
1545
+ // Assertions
1546
+ expect(findKthSmallest(1)).toBe(1);
1547
+ expect(findKthSmallest(3)).toBe(4);
1548
+ expect(findKthSmallest(7)).toBe(8);
1549
+ });
1550
+
1551
+ // Test case for finding elements in a given range
1552
+ it('@example Find elements in a range', () => {
1553
+ const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);
1554
+ expect(bst.search(new Range(5, 10))).toEqual([10, 5, 7]);
1555
+ expect(bst.search(new Range(4, 12))).toEqual([10, 12, 5, 7]);
1556
+ expect(bst.search(new Range(4, 12, true, false))).toEqual([10, 5, 7]);
1557
+ expect(bst.search(new Range(15, 20))).toEqual([15, 18]);
1558
+ expect(bst.search(new Range(15, 20, false))).toEqual([18]);
1559
+ });
1560
+
1561
+ // Test case for Huffman coding simulation
1562
+ it('Huffman coding frequency simulation', () => {
1563
+ // Create a BST to simulate Huffman tree
1564
+ const frequencyBST = new BST<string, number>([
1565
+ ['a', 5],
1566
+ ['b', 9],
1567
+ ['c', 12],
1568
+ ['d', 13],
1569
+ ['e', 16],
1570
+ ['f', 45]
1571
+ ]);
1572
+
1573
+ // Sort nodes by frequency
1574
+ const sortedFrequencies = frequencyBST.dfs(node => ({ char: node.key, freq: node.value }), 'IN');
1575
+
1576
+ // Build Huffman tree simulation
1577
+ expect(sortedFrequencies[0].char).toBe('a');
1578
+ expect(sortedFrequencies[5].char).toBe('f');
1579
+ });
1580
+
1581
+ // Test case for Lowest Common Ancestor (LCA)
1582
+ it('@example Find lowest common ancestor', () => {
1583
+ const bst = new BST<number>([20, 10, 30, 5, 15, 25, 35, 3, 7, 12, 18]);
1584
+
1585
+ function findFirstCommon(arr1: number[], arr2: number[]): number | undefined {
1586
+ for (const num of arr1) {
1587
+ if (arr2.indexOf(num) !== -1) {
1588
+ return num;
1589
+ }
1590
+ }
1591
+ return undefined;
1592
+ }
1593
+
1594
+ // LCA helper function
1595
+ const findLCA = (num1: number, num2: number): number | undefined => {
1596
+ const path1 = bst.getPathToRoot(num1);
1597
+ const path2 = bst.getPathToRoot(num2);
1598
+ // Find the first common ancestor
1599
+ return findFirstCommon(path1, path2);
1600
+ };
1601
+
1602
+ // Assertions
1603
+ expect(findLCA(3, 10)).toBe(7);
1604
+ expect(findLCA(5, 35)).toBe(15);
1605
+ expect(findLCA(20, 30)).toBe(25);
1606
+ });
1607
+ });
@@ -58,11 +58,7 @@ describe('Overall BinaryTree Test', () => {
58
58
  it('Should clone a BST works fine', () => {
59
59
  const bst = new BST<number>([3, 6, 7, 1, 9], {
60
60
  iterationType: 'RECURSIVE',
61
- comparator: (a, b) => {
62
- if (a > b) return -1;
63
- if (a < b) return 1;
64
- return 0;
65
- }
61
+ isReverse: true
66
62
  });
67
63
  expect(bst.size).toBe(5);
68
64
  expect(bst.root?.key).toBe(6);
@@ -70,7 +66,7 @@ describe('Overall BinaryTree Test', () => {
70
66
  expect(bst.root?.left?.right?.key).toBe(7);
71
67
  expect(bst.root?.right?.key).toBe(3);
72
68
  expect(bst.root?.right?.right?.key).toBe(1);
73
- expect(bst.getNodeByKey(9)?.right?.key).toBe(7);
69
+ expect(bst.getNode(9)?.right?.key).toBe(7);
74
70
  expect(bst.getHeight()).toBe(2);
75
71
  expect(bst.has(9)).toBe(true);
76
72
  expect(bst.has(7)).toBe(true);
@@ -81,7 +77,7 @@ describe('Overall BinaryTree Test', () => {
81
77
  expect(bst.root?.left?.key).toBe(9);
82
78
  expect(bst.root?.right?.key).toBe(3);
83
79
  expect(bst.root?.right?.right?.key).toBe(1);
84
- expect(bst.getNodeByKey(6)?.left?.key).toBe(9);
80
+ expect(bst.getNode(6)?.left?.key).toBe(9);
85
81
  expect(bst.getHeight()).toBe(2);
86
82
  expect(bst.has(9)).toBe(true);
87
83
  expect(bst.has(7)).toBe(false);
@@ -92,7 +88,7 @@ describe('Overall BinaryTree Test', () => {
92
88
  expect(clonedBST.root?.left?.key).toBe(9);
93
89
  expect(clonedBST.root?.right?.key).toBe(3);
94
90
  expect(clonedBST.root?.right?.right?.key).toBe(1);
95
- expect(clonedBST.getNodeByKey(6)?.left?.key).toBe(9);
91
+ expect(clonedBST.getNode(6)?.left?.key).toBe(9);
96
92
  expect(clonedBST.getHeight()).toBe(2);
97
93
  expect(clonedBST.has(9)).toBe(true);
98
94
  expect(clonedBST.has(7)).toBe(false);
@@ -102,11 +98,7 @@ describe('Overall BinaryTree Test', () => {
102
98
  it('Should clone a AVLTree works fine', () => {
103
99
  const avl = new AVLTree<number>([3, 6, 7, 1, 9], {
104
100
  iterationType: 'RECURSIVE',
105
- comparator: (a, b) => {
106
- if (a > b) return -1;
107
- if (a < b) return 1;
108
- return 0;
109
- }
101
+ isReverse: true
110
102
  });
111
103
  expect(avl.size).toBe(5);
112
104
  avl.add(2);
@@ -117,7 +109,7 @@ describe('Overall BinaryTree Test', () => {
117
109
  expect(avl.root?.left?.left?.key).toBe(9);
118
110
  expect(avl.root?.right?.key).toBe(1);
119
111
  expect(avl.root?.right?.left?.key).toBe(2);
120
- expect(avl.getNodeByKey(7)?.left?.key).toBe(9);
112
+ expect(avl.getNode(7)?.left?.key).toBe(9);
121
113
  expect(avl.getHeight()).toBe(3);
122
114
  expect(avl.has(9)).toBe(true);
123
115
  expect(avl.has(7)).toBe(true);
@@ -128,7 +120,7 @@ describe('Overall BinaryTree Test', () => {
128
120
  expect(avl.root?.left?.key).toBe(5);
129
121
  expect(avl.root?.right?.key).toBe(1);
130
122
  expect(avl.root?.right?.left?.key).toBe(2);
131
- expect(avl.getNodeByKey(6)?.left?.key).toBe(undefined);
123
+ expect(avl.getNode(6)?.left?.key).toBe(undefined);
132
124
  expect(avl.getHeight()).toBe(3);
133
125
  expect(avl.has(9)).toBe(true);
134
126
  expect(avl.has(7)).toBe(false);
@@ -139,7 +131,7 @@ describe('Overall BinaryTree Test', () => {
139
131
  expect(clonedAVL.root?.left?.key).toBe(5);
140
132
  expect(clonedAVL.root?.right?.key).toBe(1);
141
133
  expect(clonedAVL.root?.right?.left?.key).toBe(2);
142
- expect(clonedAVL.getNodeByKey(6)?.left?.key).toBe(undefined);
134
+ expect(clonedAVL.getNode(6)?.left?.key).toBe(undefined);
143
135
  expect(clonedAVL.getHeight()).toBe(3);
144
136
  expect(clonedAVL.has(9)).toBe(true);
145
137
  expect(clonedAVL.has(7)).toBe(false);
@@ -162,7 +154,7 @@ describe('Overall BinaryTree Test', () => {
162
154
  expect(tmm.root?.left?.left?.key).toBe(NaN);
163
155
  expect(tmm.root?.right?.key).toBe(7);
164
156
  expect(tmm.root?.right?.left?.key).toBe(5);
165
- expect(tmm.getNodeByKey(7)?.left?.key).toBe(5);
157
+ expect(tmm.getNode(7)?.left?.key).toBe(5);
166
158
  expect(tmm.getHeight()).toBe(3);
167
159
  expect(tmm.has(9)).toBe(true);
168
160
  expect(tmm.has(7)).toBe(true);
@@ -174,7 +166,7 @@ describe('Overall BinaryTree Test', () => {
174
166
  expect(tmm.root?.left?.key).toBe(1);
175
167
  expect(tmm.root?.right?.key).toBe(9);
176
168
  expect(tmm.root?.right?.left?.key).toBe(5);
177
- expect(tmm.getNodeByKey(6)?.left?.key).toBe(NaN);
169
+ expect(tmm.getNode(6)?.left?.key).toBe(NaN);
178
170
  expect(tmm.getHeight()).toBe(3);
179
171
  expect(tmm.has(9)).toBe(true);
180
172
  expect(tmm.has(7)).toBe(false);
@@ -187,7 +179,7 @@ describe('Overall BinaryTree Test', () => {
187
179
  expect(clonedTMM.root?.left?.key).toBe(1);
188
180
  expect(clonedTMM.root?.right?.key).toBe(5);
189
181
  expect(clonedTMM.root?.right?.left?.key).toBe(4);
190
- expect(clonedTMM.getNodeByKey(6)?.left?.key).toBe(NaN);
182
+ expect(clonedTMM.getNode(6)?.left?.key).toBe(NaN);
191
183
  expect(clonedTMM.getHeight()).toBe(3);
192
184
  expect(clonedTMM.has(9)).toBe(true);
193
185
  expect(clonedTMM.has(7)).toBe(false);
@@ -209,7 +201,7 @@ describe('Overall BinaryTree Test', () => {
209
201
  expect(rbTree.root?.left?.left?.key).toBe(NaN);
210
202
  expect(rbTree.root?.right?.key).toBe(7);
211
203
  expect(rbTree.root?.right?.left?.key).toBe(5);
212
- expect(rbTree.getNodeByKey(7)?.left?.key).toBe(5);
204
+ expect(rbTree.getNode(7)?.left?.key).toBe(5);
213
205
  expect(rbTree.getHeight()).toBe(3);
214
206
  expect(rbTree.has(9)).toBe(true);
215
207
  expect(rbTree.has(7)).toBe(true);
@@ -220,7 +212,7 @@ describe('Overall BinaryTree Test', () => {
220
212
  expect(rbTree.root?.left?.key).toBe(1);
221
213
  expect(rbTree.root?.right?.key).toBe(9);
222
214
  expect(rbTree.root?.right?.left?.key).toBe(5);
223
- expect(rbTree.getNodeByKey(6)?.left?.key).toBe(NaN);
215
+ expect(rbTree.getNode(6)?.left?.key).toBe(NaN);
224
216
  expect(rbTree.getHeight()).toBe(3);
225
217
  expect(rbTree.has(9)).toBe(true);
226
218
  expect(rbTree.has(7)).toBe(false);
@@ -232,7 +224,7 @@ describe('Overall BinaryTree Test', () => {
232
224
  expect(clonedRbTree.root?.left?.key).toBe(1);
233
225
  expect(clonedRbTree.root?.right?.key).toBe(5);
234
226
  expect(clonedRbTree.root?.right?.left?.key).toBe(4);
235
- expect(clonedRbTree.getNodeByKey(6)?.left?.key).toBe(NaN);
227
+ expect(clonedRbTree.getNode(6)?.left?.key).toBe(NaN);
236
228
  expect(clonedRbTree.getHeight()).toBe(3);
237
229
  expect(clonedRbTree.has(9)).toBe(true);
238
230
  expect(clonedRbTree.has(7)).toBe(false);
@@ -1,4 +1,4 @@
1
- import { BinaryTreeNode, BSTNode, RedBlackTree, RedBlackTreeNode } from '../../../../src';
1
+ import { BinaryTreeNode, BSTNode, Range, RedBlackTree, RedBlackTreeNode } from '../../../../src';
2
2
  import { getRandomInt, getRandomIntArray, magnitude } from '../../../utils';
3
3
  import { OrderedMap } from 'js-sdsl';
4
4
 
@@ -819,3 +819,102 @@ describe('RedBlackTree - _deleteFixup', () => {
819
819
  ]);
820
820
  });
821
821
  });
822
+
823
+ describe('classic use', () => {
824
+ it('Database Index: Add, Search, and Delete Records', () => {
825
+ const dbIndex = new RedBlackTree<number, string>();
826
+
827
+ // Insert records
828
+ dbIndex.add(1, 'Alice');
829
+ dbIndex.add(2, 'Bob');
830
+ dbIndex.add(3, 'Charlie');
831
+
832
+ // Search for records
833
+ expect(dbIndex.get(1)).toBe('Alice');
834
+ expect(dbIndex.get(2)).toBe('Bob');
835
+ expect(dbIndex.get(3)).toBe('Charlie');
836
+
837
+ // Delete a record
838
+ dbIndex.delete(2);
839
+ expect(dbIndex.get(2)).toBeUndefined();
840
+ });
841
+
842
+ it('@example Merge 3 sorted datasets', () => {
843
+ const dataset1 = new RedBlackTree<number, string>([
844
+ [1, 'A'],
845
+ [7, 'G']
846
+ ]);
847
+ const dataset2 = [
848
+ [2, 'B'],
849
+ [6, 'F']
850
+ ];
851
+ const dataset3 = new RedBlackTree<number, string>([
852
+ [3, 'C'],
853
+ [5, 'E'],
854
+ [4, 'D']
855
+ ]);
856
+
857
+ // Merge datasets into a single Red-Black Tree
858
+ const merged = new RedBlackTree<number, string>(dataset1);
859
+ merged.addMany(dataset2);
860
+ merged.merge(dataset3);
861
+
862
+ // Verify merged dataset is in sorted order
863
+ expect([...merged.values()]).toEqual(['A', 'B', 'C', 'D', 'E', 'F', 'G']);
864
+ });
865
+
866
+ // Test case for finding elements in a given range
867
+ it('Find elements in a range', () => {
868
+ const bst = new RedBlackTree<number>([10, 5, 15, 3, 7, 12, 18]);
869
+ expect(bst.search(new Range(5, 10))).toEqual([5, 10, 7]);
870
+ expect(bst.search(new Range(4, 12))).toEqual([5, 10, 12, 7]);
871
+ expect(bst.search(new Range(15, 20))).toEqual([15, 18]);
872
+ });
873
+
874
+ it('Timer List: Manage Timed Tasks', () => {
875
+ const timerList = new RedBlackTree<number, string>(); // Key: Time in ms, Value: Task Name
876
+
877
+ // Schedule tasks
878
+ timerList.add(100, 'Task A');
879
+ timerList.add(200, 'Task B');
880
+ timerList.add(50, 'Task C');
881
+
882
+ // Verify the order of tasks by retrieval
883
+ expect([...timerList.values()]).toEqual(['Task C', 'Task A', 'Task B']); // Sorted by key (time)
884
+
885
+ // Remove the earliest task
886
+ timerList.delete(50);
887
+ expect([...timerList.values()]).toEqual(['Task A', 'Task B']);
888
+ });
889
+
890
+ it('Scheduler: Manage Tasks by Priority', () => {
891
+ const scheduler = new RedBlackTree<number, string>(); // Key: Priority, Value: Task Name
892
+
893
+ // Add tasks with different priorities
894
+ scheduler.add(3, 'Low Priority Task');
895
+ scheduler.add(1, 'High Priority Task');
896
+ scheduler.add(2, 'Medium Priority Task');
897
+
898
+ // Verify the order of tasks by retrieval
899
+ expect([...scheduler.values()]).toEqual(['High Priority Task', 'Medium Priority Task', 'Low Priority Task']);
900
+
901
+ // Remove the highest priority task
902
+ scheduler.delete(1);
903
+ expect([...scheduler.values()]).toEqual(['Medium Priority Task', 'Low Priority Task']);
904
+ });
905
+
906
+ it('Routing Table: Manage IP Routes', () => {
907
+ const routingTable = new RedBlackTree<number, string>(); // Key: IP Address, Value: Route
908
+
909
+ // Add routes
910
+ routingTable.add(1921680101, 'Route A');
911
+ routingTable.add(1921680102, 'Route B');
912
+ routingTable.add(1921680100, 'Route C');
913
+
914
+ // Search for a specific route
915
+ expect(routingTable.get(1921680101)).toBe('Route A');
916
+
917
+ // Verify all routes in sorted order
918
+ expect([...routingTable.values()]).toEqual(['Route C', 'Route A', 'Route B']);
919
+ });
920
+ });