data-structure-typed 1.54.2 → 1.54.3

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 (91) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/LICENSE +2 -2
  3. package/README.md +14 -1
  4. package/README_zh-CN.md +1 -1
  5. package/benchmark/report.html +4 -1
  6. package/benchmark/report.json +76 -17
  7. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.d.ts +21 -20
  8. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js +8 -7
  9. package/dist/cjs/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
  10. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.d.ts +12 -12
  11. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js +2 -2
  12. package/dist/cjs/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  13. package/dist/cjs/data-structures/binary-tree/avl-tree.d.ts +25 -21
  14. package/dist/cjs/data-structures/binary-tree/avl-tree.js +12 -8
  15. package/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
  16. package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +111 -225
  17. package/dist/cjs/data-structures/binary-tree/binary-tree.js +177 -144
  18. package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
  19. package/dist/cjs/data-structures/binary-tree/bst.d.ts +59 -53
  20. package/dist/cjs/data-structures/binary-tree/bst.js +75 -119
  21. package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
  22. package/dist/cjs/data-structures/binary-tree/red-black-tree.d.ts +18 -18
  23. package/dist/cjs/data-structures/binary-tree/red-black-tree.js +6 -6
  24. package/dist/cjs/data-structures/binary-tree/red-black-tree.js.map +1 -1
  25. package/dist/cjs/data-structures/binary-tree/tree-counter.d.ts +19 -19
  26. package/dist/cjs/data-structures/binary-tree/tree-counter.js +12 -12
  27. package/dist/cjs/data-structures/binary-tree/tree-counter.js.map +1 -1
  28. package/dist/cjs/data-structures/binary-tree/tree-multi-map.d.ts +12 -12
  29. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js +2 -2
  30. package/dist/cjs/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  31. package/dist/cjs/types/data-structures/binary-tree/binary-tree.d.ts +1 -0
  32. package/dist/cjs/types/data-structures/binary-tree/bst.d.ts +1 -1
  33. package/dist/cjs/utils/utils.d.ts +2 -2
  34. package/dist/esm/data-structures/binary-tree/avl-tree-counter.d.ts +21 -20
  35. package/dist/esm/data-structures/binary-tree/avl-tree-counter.js +9 -8
  36. package/dist/esm/data-structures/binary-tree/avl-tree-counter.js.map +1 -1
  37. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.d.ts +12 -12
  38. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js +3 -3
  39. package/dist/esm/data-structures/binary-tree/avl-tree-multi-map.js.map +1 -1
  40. package/dist/esm/data-structures/binary-tree/avl-tree.d.ts +25 -21
  41. package/dist/esm/data-structures/binary-tree/avl-tree.js +13 -9
  42. package/dist/esm/data-structures/binary-tree/avl-tree.js.map +1 -1
  43. package/dist/esm/data-structures/binary-tree/binary-tree.d.ts +111 -225
  44. package/dist/esm/data-structures/binary-tree/binary-tree.js +181 -148
  45. package/dist/esm/data-structures/binary-tree/binary-tree.js.map +1 -1
  46. package/dist/esm/data-structures/binary-tree/bst.d.ts +59 -53
  47. package/dist/esm/data-structures/binary-tree/bst.js +76 -120
  48. package/dist/esm/data-structures/binary-tree/bst.js.map +1 -1
  49. package/dist/esm/data-structures/binary-tree/red-black-tree.d.ts +18 -18
  50. package/dist/esm/data-structures/binary-tree/red-black-tree.js +7 -7
  51. package/dist/esm/data-structures/binary-tree/red-black-tree.js.map +1 -1
  52. package/dist/esm/data-structures/binary-tree/tree-counter.d.ts +19 -19
  53. package/dist/esm/data-structures/binary-tree/tree-counter.js +13 -13
  54. package/dist/esm/data-structures/binary-tree/tree-counter.js.map +1 -1
  55. package/dist/esm/data-structures/binary-tree/tree-multi-map.d.ts +12 -12
  56. package/dist/esm/data-structures/binary-tree/tree-multi-map.js +3 -3
  57. package/dist/esm/data-structures/binary-tree/tree-multi-map.js.map +1 -1
  58. package/dist/esm/types/data-structures/binary-tree/binary-tree.d.ts +1 -0
  59. package/dist/esm/types/data-structures/binary-tree/bst.d.ts +1 -1
  60. package/dist/esm/utils/utils.d.ts +2 -2
  61. package/dist/umd/data-structure-typed.js +296 -279
  62. package/dist/umd/data-structure-typed.min.js +5 -12
  63. package/dist/umd/data-structure-typed.min.js.map +1 -1
  64. package/package.json +7 -7
  65. package/src/data-structures/binary-tree/avl-tree-counter.ts +30 -23
  66. package/src/data-structures/binary-tree/avl-tree-multi-map.ts +25 -15
  67. package/src/data-structures/binary-tree/avl-tree.ts +35 -29
  68. package/src/data-structures/binary-tree/binary-tree.ts +469 -252
  69. package/src/data-structures/binary-tree/bst.ts +141 -143
  70. package/src/data-structures/binary-tree/red-black-tree.ts +27 -35
  71. package/src/data-structures/binary-tree/tree-counter.ts +33 -27
  72. package/src/data-structures/binary-tree/tree-multi-map.ts +25 -17
  73. package/src/types/data-structures/binary-tree/binary-tree.ts +1 -0
  74. package/src/types/data-structures/binary-tree/bst.ts +1 -1
  75. package/src/utils/utils.ts +2 -2
  76. package/test/integration/compile.mjs +21 -21
  77. package/test/performance/data-structures/binary-tree/avl-tree.test.mjs +71 -0
  78. package/test/performance/data-structures/binary-tree/red-black-tree.test.mjs +81 -0
  79. package/test/performance/{reportor.js → reportor.mjs} +264 -8
  80. package/test/performance/reportor.ts +1 -1
  81. package/test/unit/data-structures/binary-tree/avl-tree-counter.test.ts +7 -7
  82. package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +4 -5
  83. package/test/unit/data-structures/binary-tree/avl-tree.test.ts +72 -5
  84. package/test/unit/data-structures/binary-tree/binary-tree.test.ts +132 -82
  85. package/test/unit/data-structures/binary-tree/bst.test.ts +12 -12
  86. package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +4 -12
  87. package/test/unit/data-structures/binary-tree/tree-counter.test.ts +4 -4
  88. package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +5 -5
  89. package/test/utils/json2html.ts +0 -154
  90. package/test/performance/data-structures/binary-tree/avl-tree.test.js +0 -45
  91. /package/test/performance/data-structures/binary-tree/{rb-tree.test.ts → red-black-tree.test.ts} +0 -0
@@ -0,0 +1,71 @@
1
+ import { AVLTree } from 'data-structure-typed';
2
+ import Benchmark from 'benchmark';
3
+
4
+ const magnitude = {
5
+ THOUSAND: 1000,
6
+ TEN_THOUSAND: 10000,
7
+ HUNDRED_THOUSAND: 100000,
8
+ MILLION: 1000000,
9
+ TEN_MILLION: 10000000,
10
+ BILLION: 100000000
11
+ };
12
+
13
+ function getRandomIntArray(length = 1000, min = -1000, max = 1000, unique = true) {
14
+ if (unique) {
15
+ if (max - min + 1 < length) {
16
+ throw new Error('Range too small for unique values with the specified length');
17
+ }
18
+ const allNumbers = Array.from({ length: max - min + 1 }, (_, i) => i + min);
19
+ for (let i = allNumbers.length - 1; i > 0; i--) {
20
+ const j = Math.floor(Math.random() * (i + 1));
21
+ [allNumbers[i], allNumbers[j]] = [allNumbers[j], allNumbers[i]];
22
+ }
23
+ return allNumbers.slice(0, length);
24
+ }
25
+ else {
26
+ return Array.from({ length }, () => Math.floor(Math.random() * (max - min + 1)) + min);
27
+ }
28
+ }
29
+
30
+ const suite = new Benchmark.Suite();
31
+ const avlTree = new AVLTree();
32
+ const { HUNDRED_THOUSAND } = magnitude;
33
+ const randomArray = getRandomIntArray(HUNDRED_THOUSAND, 0, HUNDRED_THOUSAND - 1, true);
34
+ suite
35
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} add randomly`, () => {
36
+ avlTree.clear();
37
+ for (let i = 0; i < randomArray.length; i++)
38
+ avlTree.add(randomArray[i]);
39
+ })
40
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} add`, () => {
41
+ avlTree.clear();
42
+ for (let i = 0; i < randomArray.length; i++)
43
+ avlTree.add(i);
44
+ })
45
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} get`, () => {
46
+ for (let i = 0; i < randomArray.length; i++)
47
+ avlTree.get(randomArray[i]);
48
+ })
49
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} getNode`, () => {
50
+ for (let i = 0; i < randomArray.length; i++)
51
+ avlTree.getNode(randomArray[i]);
52
+ })
53
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} iterator`, () => {
54
+ const entries = [...avlTree];
55
+ return entries.length === HUNDRED_THOUSAND;
56
+ })
57
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} add & delete orderly`, () => {
58
+ avlTree.clear();
59
+ for (let i = 0; i < randomArray.length; i++)
60
+ avlTree.add(i);
61
+ for (let i = 0; i < randomArray.length; i++)
62
+ avlTree.delete(i);
63
+ })
64
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} add & delete randomly`, () => {
65
+ avlTree.clear();
66
+ for (let i = 0; i < randomArray.length; i++)
67
+ avlTree.add(randomArray[i]);
68
+ for (let i = 0; i < randomArray.length; i++)
69
+ avlTree.delete(randomArray[i]);
70
+ });
71
+ export { suite };
@@ -0,0 +1,81 @@
1
+ import { RedBlackTree } from 'data-structure-typed';
2
+ import Benchmark from 'benchmark';
3
+
4
+ const magnitude = {
5
+ THOUSAND: 1000,
6
+ TEN_THOUSAND: 10000,
7
+ HUNDRED_THOUSAND: 100000,
8
+ MILLION: 1000000,
9
+ TEN_MILLION: 10000000,
10
+ BILLION: 100000000
11
+ };
12
+
13
+ function getRandomIntArray(length = 1000, min = -1000, max = 1000, unique = true) {
14
+ if (unique) {
15
+ if (max - min + 1 < length) {
16
+ throw new Error('Range too small for unique values with the specified length');
17
+ }
18
+ const allNumbers = Array.from({ length: max - min + 1 }, (_, i) => i + min);
19
+ for (let i = allNumbers.length - 1; i > 0; i--) {
20
+ const j = Math.floor(Math.random() * (i + 1));
21
+ [allNumbers[i], allNumbers[j]] = [allNumbers[j], allNumbers[i]];
22
+ }
23
+ return allNumbers.slice(0, length);
24
+ }
25
+ else {
26
+ return Array.from({ length }, () => Math.floor(Math.random() * (max - min + 1)) + min);
27
+ }
28
+ }
29
+ const suite = new Benchmark.Suite();
30
+ const rbTree = new RedBlackTree();
31
+ const rbTreeNodeMode = new RedBlackTree([], { isMapMode: false });
32
+ const { HUNDRED_THOUSAND } = magnitude;
33
+ const randomArray = getRandomIntArray(HUNDRED_THOUSAND, 0, HUNDRED_THOUSAND - 1, true);
34
+ suite
35
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} add randomly`, () => {
36
+ rbTree.clear();
37
+ for (let i = 0; i < randomArray.length; i++)
38
+ rbTree.add(randomArray[i]);
39
+ })
40
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} add`, () => {
41
+ rbTree.clear();
42
+ for (let i = 0; i < randomArray.length; i++)
43
+ rbTree.add(i);
44
+ })
45
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} get`, () => {
46
+ for (let i = 0; i < randomArray.length; i++)
47
+ rbTree.get(randomArray[i]);
48
+ })
49
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} getNode`, () => {
50
+ for (let i = 0; i < randomArray.length; i++)
51
+ rbTree.getNode(randomArray[i]);
52
+ })
53
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} node mode add randomly`, () => {
54
+ rbTreeNodeMode.clear();
55
+ for (let i = 0; i < randomArray.length; i++)
56
+ rbTreeNodeMode.add(randomArray[i]);
57
+ })
58
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} node mode get`, () => {
59
+ for (let i = 0; i < randomArray.length; i++)
60
+ rbTreeNodeMode.get(randomArray[i]);
61
+ })
62
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} iterator`, () => {
63
+ const entries = [...rbTree];
64
+ return entries.length === HUNDRED_THOUSAND;
65
+ })
66
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} add & delete orderly`, () => {
67
+ rbTree.clear();
68
+ for (let i = 0; i < randomArray.length; i++)
69
+ rbTree.add(i);
70
+ for (let i = 0; i < randomArray.length; i++)
71
+ rbTree.delete(i);
72
+ })
73
+ .add(`${HUNDRED_THOUSAND.toLocaleString()} add & delete randomly`, () => {
74
+ rbTree.clear();
75
+ for (let i = 0; i < randomArray.length; i++)
76
+ rbTree.add(randomArray[i]);
77
+ for (let i = 0; i < randomArray.length; i++)
78
+ rbTree.delete(randomArray[i]);
79
+ });
80
+
81
+ export { suite };
@@ -1,15 +1,268 @@
1
1
  import * as path from 'path';
2
2
  import * as fs from 'fs';
3
- import * as fastGlob from 'fast-glob';
4
- import { ConsoleColor, numberFix, render } from '../utils';
3
+ import fastGlob from 'fast-glob';
4
+ import { fileURLToPath } from 'url';
5
5
 
6
+ const isNumber = (value) => {
7
+ return typeof value === 'number';
8
+ };
9
+ const isString = (value) => {
10
+ return typeof value === 'string';
11
+ };
12
+ const isBoolean = (value) => {
13
+ return typeof value === 'boolean';
14
+ };
15
+ const isDate = (value) => {
16
+ return value instanceof Date;
17
+ };
18
+ const isNull = (value) => {
19
+ return value === null;
20
+ };
21
+ const isUndefined = (value) => {
22
+ return typeof value === 'undefined';
23
+ };
24
+ const isFunction = (value) => {
25
+ return typeof value === 'function';
26
+ };
27
+ const isObject = (value) => {
28
+ return typeof value === 'object';
29
+ };
30
+ const isArray = (value) => {
31
+ return Array.isArray(value);
32
+ };
33
+ const isEqual = (objA, objB) => {
34
+ if (objA === objB) {
35
+ return true;
36
+ }
37
+ if (typeof objA !== 'object' || typeof objB !== 'object' || objA === null || objB === null) {
38
+ return false;
39
+ }
40
+ const keysA = Object.keys(objA);
41
+ const keysB = Object.keys(objB);
42
+ if (keysA.length !== keysB.length) {
43
+ return false;
44
+ }
45
+ for (const key of keysA) {
46
+ if (!keysB.includes(key)) {
47
+ return false;
48
+ }
49
+ if (!isEqual(objA[key], objB[key])) {
50
+ return false;
51
+ }
52
+ }
53
+ return true;
54
+ };
55
+
56
+ function toggleJS(options) {
57
+ if (options === null || options === void 0 ? void 0 : options.plainHtml) {
58
+ return '';
59
+ }
60
+ else {
61
+ return 'onclick="json-to-html.toggleVisibility(this);return false"';
62
+ }
63
+ }
64
+ function makeLabelDiv(options, level, keyName, datatype) {
65
+ if (typeof keyName === 'number') {
66
+ return `<div class='index'><span class='json-to-html-label'>${keyName}&nbsp;</span></div>`;
67
+ }
68
+ else if (typeof keyName === 'string') {
69
+ if (datatype === 'array') {
70
+ return `<div class='collapsible level${level}' ${toggleJS(options)}><span class='json-to-html-label'>${keyName}</span></div>`;
71
+ }
72
+ else if (datatype === 'object') {
73
+ return `<div class='attribute collapsible level${level}' ${toggleJS(options)}><span class='json-to-html-label'>${keyName}:</span></div>`;
74
+ }
75
+ else {
76
+ return `<div class='leaf level${level}'><span class='json-to-html-label'>${keyName}:</span></div>`;
77
+ }
78
+ }
79
+ else {
80
+ return '';
81
+ }
82
+ }
83
+ function getContentClass(keyName) {
84
+ if (typeof keyName === 'string') {
85
+ return 'content';
86
+ }
87
+ else {
88
+ return '';
89
+ }
90
+ }
91
+ function isPlainObject(val) {
92
+ let lastKey;
93
+ let lastOwnKey;
94
+ for (const key in val) {
95
+ if (val.hasOwnProperty(key)) {
96
+ lastOwnKey = key;
97
+ }
98
+ }
99
+ for (const key in val) {
100
+ lastKey = key;
101
+ }
102
+ return lastOwnKey === lastKey;
103
+ }
104
+ function isLeafValue(val) {
105
+ return (isNumber(val) ||
106
+ isString(val) ||
107
+ isBoolean(val) ||
108
+ isDate(val) ||
109
+ isNull(val) ||
110
+ isUndefined(val) ||
111
+ isNaN(val) ||
112
+ isFunction(val) ||
113
+ !isPlainObject(val));
114
+ }
115
+ function isLeafObject(obj) {
116
+ if (!isObject(obj)) {
117
+ return false;
118
+ }
119
+ for (const key in obj) {
120
+ const val = obj[key];
121
+ if (!isLeafValue(val)) {
122
+ return false;
123
+ }
124
+ }
125
+ return true;
126
+ }
127
+ function isTable(arr) {
128
+ if (!isArray(arr)) {
129
+ return false;
130
+ }
131
+ if (arr.length === 0 || !isObject(arr[0])) {
132
+ return false;
133
+ }
134
+ else {
135
+ let nonCompliant = arr.find(row => !isLeafObject(row));
136
+ if (nonCompliant) {
137
+ return false;
138
+ }
139
+ else {
140
+ const cols = Object.keys(arr[0]);
141
+ nonCompliant = arr.find((row) => !isEqual(cols, Object.keys(row)));
142
+ return !nonCompliant;
143
+ }
144
+ }
145
+ }
146
+ function drawTable(arr) {
147
+ function drawRow(headers, rowObj) {
148
+ return '<td>' + headers.map(header => rowObj[header]).join('</td><td>') + '</td>';
149
+ }
150
+ const cols = Object.keys(arr[0]);
151
+ const content = arr.map(rowObj => drawRow(cols, rowObj));
152
+ const headingHtml = '<tr><th>' + cols.join('</th><th>') + '</th></tr>';
153
+ const contentHtml = '<tr>' + content.join('</tr><tr>') + '</tr>';
154
+ return '<table style="display: table; width:100%; table-layout: fixed;">' + headingHtml + contentHtml + '</table>';
155
+ }
156
+ function _render(name, data, options, level, altRow) {
157
+ const contentClass = getContentClass(name);
158
+ if (isArray(data)) {
159
+ const title = makeLabelDiv(options, level, `${name}`, 'array');
160
+ let subs;
161
+ if (isTable(data)) {
162
+ subs = drawTable(data);
163
+ }
164
+ else {
165
+ subs =
166
+ "<div class='altRows'>" +
167
+ data
168
+ .map((val, idx) => _render(idx.toString(), val, options, level + 1, idx % 2))
169
+ .join("</div><div class='altRows'>") +
170
+ '</div>';
171
+ }
172
+ return `<div class="json-to-html-collapse clearfix ${altRow}">
173
+ ${title}
174
+ <div class="${contentClass}">${subs}</div>
175
+ </div>`;
176
+ }
177
+ else if (isLeafValue(data)) {
178
+ const title = makeLabelDiv(options, level, name);
179
+ if (isFunction(data)) {
180
+ return `${title}<span class='json-to-html-value'>&nbsp;&nbsp;-function() can't _render-</span>`;
181
+ }
182
+ else if (!isPlainObject(data)) {
183
+ if (isFunction(data.toString)) {
184
+ return `${title}<span class='json-to-html-value'>&nbsp;&nbsp;${data.toString()}</span>`;
185
+ }
186
+ else {
187
+ return `${title}<span class='json-to-html-value'>&nbsp;&nbsp;-instance object, can't render-</span>`;
188
+ }
189
+ }
190
+ else {
191
+ return `${title}<span class='json-to-html-value'>&nbsp;&nbsp;${data}</span>`;
192
+ }
193
+ }
194
+ else {
195
+ const title = makeLabelDiv(options, level, name, 'object');
196
+ let count = 0;
197
+ const subs = '<div>' +
198
+ Object.entries(data)
199
+ .map(([key, val]) => _render(key, val, options, level + 1, count++ % 2))
200
+ .join('</div><div>') +
201
+ '</div>';
202
+ const inner = `<div class="json-to-html-expand clearfix ${altRow}">
203
+ ${title}
204
+ <div class="${contentClass}">${subs}</div>
205
+ </div>`;
206
+ return `${level === 0 ? "<div id='json-to-html'>" : ''}
207
+ ${inner}
208
+ ${level === 0 ? '</div>' : ''}`;
209
+ }
210
+ }
211
+ export function render(name, json, options) {
212
+ return `${_render(name, json, options, 0, 0)}`;
213
+ }
214
+
215
+
216
+ const __filename = fileURLToPath(import.meta.url);
217
+ const __dirname = path.dirname(__filename);
218
+
219
+ function numberFix(num, decimalPlaces) {
220
+ if (num > 10000 || num < 0.001) {
221
+ const [mantissa, exponent] = num.toExponential().split('e');
222
+ const formattedMantissa = Number(mantissa).toFixed(decimalPlaces);
223
+ return `${formattedMantissa}e${exponent}`;
224
+ } else {
225
+ return num.toFixed(decimalPlaces);
226
+ }
227
+ }
228
+ const ConsoleColor = {
229
+ END: '\x1b[0m',
230
+ BOLD: '\x1b[1m',
231
+ DIM: '\x1b[2m',
232
+ ITALIC: '\x1b[3m',
233
+ UNDERLINE: '\x1b[4m',
234
+ INVERSE: '\x1b[7m',
235
+ STRIKETHROUGH: '\x1b[9m',
236
+ NO_BOLD: '\x1b[22m',
237
+ NO_ITALIC: '\x1b[23m',
238
+ NO_UNDERLINE: '\x1b[24m',
239
+ NO_INVERSE: '\x1b[27m',
240
+ NO_STRIKETHROUGH: '\x1b[29m',
241
+ BLACK: '\x1b[30m',
242
+ RED: '\x1b[31m',
243
+ GREEN: '\x1b[32m',
244
+ YELLOW: '\x1b[33m',
245
+ BLUE: '\x1b[34m',
246
+ MAGENTA: '\x1b[35m',
247
+ GRAY: '\x1b[90m',
248
+ CYAN: '\x1b[36m',
249
+ WHITE: '\x1b[37m',
250
+ BG_BLACK: '\x1b[40m',
251
+ BG_RED: '\x1b[41m',
252
+ BG_GREEN: '\x1b[42m',
253
+ BG_YELLOW: '\x1b[43m',
254
+ BG_BLUE: '\x1b[44m',
255
+ BG_MAGENTA: '\x1b[45m',
256
+ BG_CYAN: '\x1b[46m',
257
+ BG_WHITE: '\x1b[47m'
258
+ };
6
259
  const args = process.argv.slice(2);
7
260
  const { GREEN, BOLD, END, YELLOW, GRAY, CYAN, BG_YELLOW } = ConsoleColor;
8
261
  const isOnlyOrdered = true;
9
262
  const runOrder = [
10
263
  'heap',
11
264
  'avl-tree',
12
- 'rb-tree',
265
+ 'red-black-tree',
13
266
  'doubly-linked-list',
14
267
  'directed-graph',
15
268
  'queue',
@@ -25,6 +278,7 @@ const getRelativePath = file => {
25
278
  return path.relative(__dirname, file);
26
279
  };
27
280
  const coloredLabeled = (label, file) => {
281
+
28
282
  const relativeFilePath = getRelativePath(file);
29
283
  const directory = path.dirname(relativeFilePath);
30
284
  const fileName = path.basename(relativeFilePath);
@@ -33,7 +287,8 @@ const coloredLabeled = (label, file) => {
33
287
  const parentDirectory = path.resolve(__dirname, '../..');
34
288
  const reportDistPath = path.join(parentDirectory, 'benchmark');
35
289
  const testDir = path.join(__dirname, 'data-structures');
36
- const allFiles = fastGlob.sync(path.join(testDir, '**', '*.test.js'));
290
+ let allFiles = fastGlob.sync(path.join(testDir, '**', '*.test.mjs'));
291
+
37
292
  let testFiles;
38
293
  let isIndividual = false;
39
294
  if (args.length > 0) {
@@ -51,9 +306,9 @@ if (args.length > 0) {
51
306
  const report = {};
52
307
  let completedCount = 0;
53
308
  const performanceTests = [];
54
- testFiles.forEach(file => {
55
- const testName = path.basename(file, '.test.ts');
56
- const testFunction = require(file);
309
+ for (const file of testFiles) {
310
+ const testName = path.basename(file, '.test.mjs');
311
+ const testFunction = await import(file);
57
312
  const { suite } = testFunction;
58
313
  if (suite)
59
314
  performanceTests.push({
@@ -61,7 +316,8 @@ testFiles.forEach(file => {
61
316
  suite,
62
317
  file
63
318
  });
64
- });
319
+ }
320
+
65
321
  const composeReport = () => {
66
322
  if (!fs.existsSync(reportDistPath))
67
323
  fs.mkdirSync(reportDistPath, {
@@ -12,7 +12,7 @@ const isOnlyOrdered = true;
12
12
  const runOrder = [
13
13
  'heap',
14
14
  'avl-tree',
15
- 'rb-tree',
15
+ 'red-black-tree',
16
16
  'doubly-linked-list',
17
17
  'directed-graph',
18
18
  'queue',
@@ -91,7 +91,7 @@ describe('AVLTreeCounter operations test1', () => {
91
91
  expect(minNodeBySpecificNode?.key).toBe(15);
92
92
 
93
93
  let subTreeSum = 0;
94
- if (node15) avlCounter.dfs(node => (subTreeSum += node.key), 'PRE', 15);
94
+ if (node15) avlCounter.dfs(node => (subTreeSum += node.key), 'PRE', false, 15);
95
95
  expect(subTreeSum).toBe(31);
96
96
  let lesserSum = 0;
97
97
  avlCounter.lesserOrGreaterTraverse((node: AVLTreeCounterNode<number>) => (lesserSum += node.key), -1, 10);
@@ -99,7 +99,7 @@ describe('AVLTreeCounter operations test1', () => {
99
99
 
100
100
  expect(node15 instanceof AVLTreeCounterNode);
101
101
  if (node15 instanceof AVLTreeCounterNode) {
102
- const subTreeAdd = avlCounter.dfs(node => (node.count += 1), 'PRE', 15);
102
+ const subTreeAdd = avlCounter.dfs(node => (node.count += 1), 'PRE', false, 15);
103
103
  expect(subTreeAdd);
104
104
  }
105
105
  const node11 = avlCounter.getNode(11);
@@ -347,7 +347,7 @@ describe('AVLTreeCounter operations test recursively1', () => {
347
347
  expect(minNodeBySpecificNode?.key).toBe(15);
348
348
 
349
349
  let subTreeSum = 0;
350
- if (node15) avlCounter.dfs(node => (subTreeSum += node.key), 'PRE', 15);
350
+ if (node15) avlCounter.dfs(node => (subTreeSum += node.key), 'PRE', false, 15);
351
351
  expect(subTreeSum).toBe(31);
352
352
  let lesserSum = 0;
353
353
  avlCounter.lesserOrGreaterTraverse((node: AVLTreeCounterNode<number>) => (lesserSum += node.key), -1, 10);
@@ -355,7 +355,7 @@ describe('AVLTreeCounter operations test recursively1', () => {
355
355
 
356
356
  expect(node15 instanceof AVLTreeCounterNode);
357
357
  if (node15 instanceof AVLTreeCounterNode) {
358
- const subTreeAdd = avlCounter.dfs(node => (node.count += 1), 'PRE', 15);
358
+ const subTreeAdd = avlCounter.dfs(node => (node.count += 1), 'PRE', false, 15);
359
359
  expect(subTreeAdd);
360
360
  }
361
361
  const node11 = avlCounter.getNode(11);
@@ -709,7 +709,7 @@ describe('AVLTreeCounter toEntryFn', () => {
709
709
 
710
710
  expect(avlCounter.morris(node => node.key, 'IN')).toEqual(expected);
711
711
  expect(avlCounter.dfs(node => node.key, 'IN')).toEqual(expected);
712
- expect(avlCounter.dfs(node => node.key, 'IN', avlCounter.root, 'RECURSIVE')).toEqual(expected);
712
+ expect(avlCounter.dfs(node => node.key, 'IN', false, avlCounter.root, 'RECURSIVE')).toEqual(expected);
713
713
  });
714
714
 
715
715
  it('should toEntryFn 2', () => {
@@ -724,7 +724,7 @@ describe('AVLTreeCounter toEntryFn', () => {
724
724
 
725
725
  expect(avlCounter.morris(node => node.key, 'IN')).toEqual(expected);
726
726
  expect(avlCounter.dfs(node => node.key, 'IN')).toEqual(expected);
727
- expect(avlCounter.dfs(node => node.key, 'IN', avlCounter.root, 'RECURSIVE')).toEqual(expected);
727
+ expect(avlCounter.dfs(node => node.key, 'IN', false, avlCounter.root, 'RECURSIVE')).toEqual(expected);
728
728
  });
729
729
 
730
730
  it('should toEntryFn throw error', () => {
@@ -760,7 +760,7 @@ describe('AVLTreeCounter toEntryFn', () => {
760
760
 
761
761
  expect(avlCounter.morris(node => node.key, 'IN')).toEqual(expected);
762
762
  expect(avlCounter.dfs(node => node.key, 'IN')).toEqual(expected);
763
- expect(avlCounter.dfs(node => node.key, 'IN', avlCounter.root, 'RECURSIVE')).toEqual(expected);
763
+ expect(avlCounter.dfs(node => node.key, 'IN', false, avlCounter.root, 'RECURSIVE')).toEqual(expected);
764
764
  });
765
765
  });
766
766
 
@@ -50,7 +50,7 @@ describe('AVLTreeMultiMap Test', () => {
50
50
  expect(getMinNodeBySpecificNode?.key).toBe(12);
51
51
 
52
52
  let subTreeSum = 0;
53
- if (node15) avlTmm.dfs(node => (subTreeSum += node.key), 'PRE', node15);
53
+ if (node15) avlTmm.dfs(node => (subTreeSum += node.key), 'PRE', false, node15);
54
54
  expect(subTreeSum).toBe(70);
55
55
 
56
56
  let lesserSum = 0;
@@ -176,7 +176,7 @@ describe('AVLTreeMultiMap Test recursively', () => {
176
176
  expect(getMinNodeBySpecificNode?.key).toBe(12);
177
177
 
178
178
  let subTreeSum = 0;
179
- if (node15) avlTmm.dfs(node => (subTreeSum += node.key), 'PRE', node15);
179
+ if (node15) avlTmm.dfs(node => (subTreeSum += node.key), 'PRE', false, node15);
180
180
  expect(subTreeSum).toBe(70);
181
181
 
182
182
  let lesserSum = 0;
@@ -509,7 +509,7 @@ describe('AVLTreeMultiMap not map mode', () => {
509
509
  expect(getMinNodeBySpecificNode?.key).toBe(12);
510
510
 
511
511
  let subTreeSum = 0;
512
- if (node15) avlTmm.dfs(node => (subTreeSum += node.key), 'PRE', node15);
512
+ if (node15) avlTmm.dfs(node => (subTreeSum += node.key), 'PRE', false, node15);
513
513
  expect(subTreeSum).toBe(70);
514
514
 
515
515
  let lesserSum = 0;
@@ -527,7 +527,6 @@ describe('AVLTreeMultiMap not map mode test recursively', () => {
527
527
  const avlTmm = new AVLTreeMultiMap<number>([], { iterationType: 'RECURSIVE' });
528
528
 
529
529
  for (const i of arr) avlTmm.add([i, [i]]);
530
-
531
530
  const node6 = avlTmm.getNode(6);
532
531
 
533
532
  expect(node6 && avlTmm.getHeight(node6)).toBe(3);
@@ -544,7 +543,7 @@ describe('AVLTreeMultiMap not map mode test recursively', () => {
544
543
  expect(getMinNodeBySpecificNode?.key).toBe(12);
545
544
 
546
545
  let subTreeSum = 0;
547
- if (node15) avlTmm.dfs(node => (subTreeSum += node.key), 'PRE', node15);
546
+ if (node15) avlTmm.dfs(node => (subTreeSum += node.key), 'PRE', false, node15);
548
547
  expect(subTreeSum).toBe(70);
549
548
 
550
549
  let lesserSum = 0;
@@ -1,4 +1,4 @@
1
- import { AVLTree, AVLTreeNode, BinaryTreeNode, BSTNode } from '../../../../src';
1
+ import { AVLTree, AVLTreeNode, BinaryTreeNode, BSTNode, Range } from '../../../../src';
2
2
 
3
3
  describe('AVL Tree Test', () => {
4
4
  it('should perform various operations on a AVL Tree', () => {
@@ -24,7 +24,7 @@ describe('AVL Tree Test', () => {
24
24
  expect(getMinNodeBySpecificNode?.key).toBe(12);
25
25
 
26
26
  let subTreeSum = 0;
27
- if (node15) avlTree.dfs(node => (subTreeSum += node.key), 'PRE', node15);
27
+ if (node15) avlTree.dfs(node => (subTreeSum += node.key), 'PRE', false, node15);
28
28
  expect(subTreeSum).toBe(70);
29
29
 
30
30
  let lesserSum = 0;
@@ -150,7 +150,7 @@ describe('AVL Tree Test recursively', () => {
150
150
  expect(getMinNodeBySpecificNode?.key).toBe(12);
151
151
 
152
152
  let subTreeSum = 0;
153
- if (node15) avlTree.dfs(node => (subTreeSum += node.key), 'PRE', node15);
153
+ if (node15) avlTree.dfs(node => (subTreeSum += node.key), 'PRE', false, node15);
154
154
  expect(subTreeSum).toBe(70);
155
155
 
156
156
  let lesserSum = 0;
@@ -480,7 +480,7 @@ describe('AVL Tree not map mode', () => {
480
480
  expect(getMinNodeBySpecificNode?.key).toBe(12);
481
481
 
482
482
  let subTreeSum = 0;
483
- if (node15) avlTree.dfs(node => (subTreeSum += node.key), 'PRE', node15);
483
+ if (node15) avlTree.dfs(node => (subTreeSum += node.key), 'PRE', false, node15);
484
484
  expect(subTreeSum).toBe(70);
485
485
 
486
486
  let lesserSum = 0;
@@ -515,7 +515,7 @@ describe('AVL Tree not map mode test recursively', () => {
515
515
  expect(getMinNodeBySpecificNode?.key).toBe(12);
516
516
 
517
517
  let subTreeSum = 0;
518
- if (node15) avlTree.dfs(node => (subTreeSum += node.key), 'PRE', node15);
518
+ if (node15) avlTree.dfs(node => (subTreeSum += node.key), 'PRE', false, node15);
519
519
  expect(subTreeSum).toBe(70);
520
520
 
521
521
  let lesserSum = 0;
@@ -542,3 +542,70 @@ describe('AVLTree iterative methods not map mode', () => {
542
542
  expect(cloned.get(cloned.root?.right?.key)).toBe('c');
543
543
  });
544
544
  });
545
+
546
+ describe('classic use', () => {
547
+ // Test case for finding elements in a given range
548
+ it('@example Find elements in a range', () => {
549
+ type Datum = { timestamp: Date; temperature: number };
550
+ // Fixed dataset of CPU temperature readings
551
+ const cpuData: Datum[] = [
552
+ { timestamp: new Date('2024-12-02T00:00:00'), temperature: 55.1 },
553
+ { timestamp: new Date('2024-12-02T00:01:00'), temperature: 56.3 },
554
+ { timestamp: new Date('2024-12-02T00:02:00'), temperature: 54.8 },
555
+ { timestamp: new Date('2024-12-02T00:03:00'), temperature: 57.2 },
556
+ { timestamp: new Date('2024-12-02T00:04:00'), temperature: 58.0 },
557
+ { timestamp: new Date('2024-12-02T00:05:00'), temperature: 59.4 },
558
+ { timestamp: new Date('2024-12-02T00:06:00'), temperature: 60.1 },
559
+ { timestamp: new Date('2024-12-02T00:07:00'), temperature: 61.3 },
560
+ { timestamp: new Date('2024-12-02T00:08:00'), temperature: 62.0 },
561
+ { timestamp: new Date('2024-12-02T00:09:00'), temperature: 63.5 },
562
+ { timestamp: new Date('2024-12-02T00:10:00'), temperature: 64.0 },
563
+ { timestamp: new Date('2024-12-02T00:11:00'), temperature: 62.8 },
564
+ { timestamp: new Date('2024-12-02T00:12:00'), temperature: 61.5 },
565
+ { timestamp: new Date('2024-12-02T00:13:00'), temperature: 60.2 },
566
+ { timestamp: new Date('2024-12-02T00:14:00'), temperature: 59.8 },
567
+ { timestamp: new Date('2024-12-02T00:15:00'), temperature: 58.6 },
568
+ { timestamp: new Date('2024-12-02T00:16:00'), temperature: 57.4 },
569
+ { timestamp: new Date('2024-12-02T00:17:00'), temperature: 56.2 },
570
+ { timestamp: new Date('2024-12-02T00:18:00'), temperature: 55.7 },
571
+ { timestamp: new Date('2024-12-02T00:19:00'), temperature: 54.5 },
572
+ { timestamp: new Date('2024-12-02T00:20:00'), temperature: 53.2 },
573
+ { timestamp: new Date('2024-12-02T00:21:00'), temperature: 52.8 },
574
+ { timestamp: new Date('2024-12-02T00:22:00'), temperature: 51.9 },
575
+ { timestamp: new Date('2024-12-02T00:23:00'), temperature: 50.5 },
576
+ { timestamp: new Date('2024-12-02T00:24:00'), temperature: 49.8 },
577
+ { timestamp: new Date('2024-12-02T00:25:00'), temperature: 48.7 },
578
+ { timestamp: new Date('2024-12-02T00:26:00'), temperature: 47.5 },
579
+ { timestamp: new Date('2024-12-02T00:27:00'), temperature: 46.3 },
580
+ { timestamp: new Date('2024-12-02T00:28:00'), temperature: 45.9 },
581
+ { timestamp: new Date('2024-12-02T00:29:00'), temperature: 45.0 }
582
+ ];
583
+
584
+ // Create an AVL tree to store CPU temperature data
585
+ const cpuTemperatureTree = new AVLTree<Date, number, Datum>(cpuData, {
586
+ toEntryFn: ({ timestamp, temperature }) => [timestamp, temperature]
587
+ });
588
+
589
+ // Query a specific time range (e.g., from 00:05 to 00:15)
590
+ const rangeStart = new Date('2024-12-02T00:05:00');
591
+ const rangeEnd = new Date('2024-12-02T00:15:00');
592
+ const rangeResults = cpuTemperatureTree.rangeSearch([rangeStart, rangeEnd], node => ({
593
+ minute: node ? node.key.getMinutes() : 0,
594
+ temperature: cpuTemperatureTree.get(node ? node.key : undefined)
595
+ }));
596
+
597
+ expect(rangeResults).toEqual( [
598
+ { minute: 5, temperature: 59.4 },
599
+ { minute: 6, temperature: 60.1 },
600
+ { minute: 7, temperature: 61.3 },
601
+ { minute: 8, temperature: 62 },
602
+ { minute: 9, temperature: 63.5 },
603
+ { minute: 10, temperature: 64 },
604
+ { minute: 11, temperature: 62.8 },
605
+ { minute: 12, temperature: 61.5 },
606
+ { minute: 13, temperature: 60.2 },
607
+ { minute: 14, temperature: 59.8 },
608
+ { minute: 15, temperature: 58.6 }
609
+ ]);
610
+ });
611
+ });