data-structure-typed 1.41.6 → 1.41.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.
- package/CHANGELOG.md +1 -1
- package/README.md +14 -11
- package/benchmark/report.html +14 -11
- package/benchmark/report.json +153 -202
- package/dist/cjs/src/data-structures/binary-tree/rb-tree.d.ts +5 -2
- package/dist/cjs/src/data-structures/binary-tree/rb-tree.js +15 -2
- package/dist/cjs/src/data-structures/binary-tree/rb-tree.js.map +1 -1
- package/dist/cjs/src/data-structures/graph/abstract-graph.js +5 -5
- package/dist/cjs/src/data-structures/graph/abstract-graph.js.map +1 -1
- package/dist/mjs/src/data-structures/binary-tree/rb-tree.d.ts +5 -2
- package/dist/mjs/src/data-structures/binary-tree/rb-tree.js +15 -2
- package/dist/mjs/src/data-structures/graph/abstract-graph.js +5 -5
- package/dist/umd/data-structure-typed.min.js +1 -1
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +5 -5
- package/src/data-structures/binary-tree/binary-tree.ts +1 -1
- package/src/data-structures/binary-tree/bst.ts +1 -1
- package/src/data-structures/binary-tree/rb-tree.ts +18 -2
- package/src/data-structures/graph/abstract-graph.ts +6 -6
- package/test/config.ts +1 -0
- package/test/integration/avl-tree.test.ts +110 -0
- package/test/integration/bst.test.ts +385 -0
- package/test/integration/heap.test.js +16 -0
- package/test/integration/index.html +51 -0
- package/test/performance/data-structures/binary-tree/avl-tree.test.ts +36 -0
- package/test/performance/data-structures/binary-tree/binary-index-tree.test.ts +0 -0
- package/test/performance/data-structures/binary-tree/binary-tree.test.ts +45 -0
- package/test/performance/data-structures/binary-tree/bst.test.ts +36 -0
- package/test/performance/data-structures/binary-tree/overall.test.ts +0 -0
- package/test/performance/data-structures/binary-tree/rb-tree.test.ts +32 -0
- package/test/performance/data-structures/binary-tree/segment-tree.test.ts +0 -0
- package/test/performance/data-structures/binary-tree/tree-multiset.test.ts +0 -0
- package/test/performance/data-structures/graph/abstract-graph.test.ts +0 -0
- package/test/performance/data-structures/graph/directed-graph.test.ts +49 -0
- package/test/performance/data-structures/graph/map-graph.test.ts +0 -0
- package/test/performance/data-structures/graph/overall.test.ts +0 -0
- package/test/performance/data-structures/graph/undirected-graph.test.ts +0 -0
- package/test/performance/data-structures/hash/coordinate-map.test.ts +0 -0
- package/test/performance/data-structures/hash/coordinate-set.test.ts +0 -0
- package/test/performance/data-structures/hash/hash-map.test.ts +0 -0
- package/test/performance/data-structures/hash/hash-table.test.ts +0 -0
- package/test/performance/data-structures/heap/heap.test.ts +30 -0
- package/test/performance/data-structures/heap/max-heap.test.ts +0 -0
- package/test/performance/data-structures/heap/min-heap.test.ts +0 -0
- package/test/performance/data-structures/linked-list/doubly-linked-list.test.ts +40 -0
- package/test/performance/data-structures/linked-list/linked-list.test.ts +0 -0
- package/test/performance/data-structures/linked-list/singly-linked-list.test.ts +34 -0
- package/test/performance/data-structures/linked-list/skip-linked-list.test.ts +0 -0
- package/test/performance/data-structures/linked-list/skip-list.test.ts +0 -0
- package/test/performance/data-structures/matrix/matrix.test.ts +0 -0
- package/test/performance/data-structures/matrix/matrix2d.test.ts +0 -0
- package/test/performance/data-structures/matrix/navigator.test.ts +0 -0
- package/test/performance/data-structures/matrix/vector2d.test.ts +0 -0
- package/test/performance/data-structures/priority-queue/max-priority-queue.test.ts +19 -0
- package/test/performance/data-structures/priority-queue/min-priority-queue.test.ts +0 -0
- package/test/performance/data-structures/priority-queue/priority-queue.test.ts +0 -0
- package/test/performance/data-structures/queue/deque.test.ts +21 -0
- package/test/performance/data-structures/queue/queue.test.ts +25 -0
- package/test/performance/data-structures/stack/stack.test.ts +0 -0
- package/test/performance/data-structures/tree/tree.test.ts +0 -0
- package/test/performance/data-structures/trie/trie.test.ts +22 -0
- package/test/performance/reportor.ts +185 -0
- package/test/performance/types/index.ts +1 -0
- package/test/performance/types/reportor.ts +3 -0
- package/test/types/index.ts +1 -0
- package/test/types/utils/big-o.ts +1 -0
- package/test/types/utils/index.ts +2 -0
- package/test/types/utils/json2html.ts +1 -0
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +269 -0
- package/test/unit/data-structures/binary-tree/binary-index-tree.test.ts +320 -0
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +486 -0
- package/test/unit/data-structures/binary-tree/bst.test.ts +840 -0
- package/test/unit/data-structures/binary-tree/overall.test.ts +66 -0
- package/test/unit/data-structures/binary-tree/rb-tree.test.ts +435 -0
- package/test/unit/data-structures/binary-tree/segment-tree.test.ts +50 -0
- package/test/unit/data-structures/binary-tree/tree-multiset.test.ts +542 -0
- package/test/unit/data-structures/graph/abstract-graph.test.ts +100 -0
- package/test/unit/data-structures/graph/directed-graph.test.ts +564 -0
- package/test/unit/data-structures/graph/map-graph.test.ts +126 -0
- package/test/unit/data-structures/graph/overall.test.ts +49 -0
- package/test/unit/data-structures/graph/salty-edges.json +1 -0
- package/test/unit/data-structures/graph/salty-vertexes.json +1 -0
- package/test/unit/data-structures/graph/undirected-graph.test.ts +167 -0
- package/test/unit/data-structures/hash/coordinate-map.test.ts +74 -0
- package/test/unit/data-structures/hash/coordinate-set.test.ts +66 -0
- package/test/unit/data-structures/hash/hash-map.test.ts +103 -0
- package/test/unit/data-structures/hash/hash-table.test.ts +186 -0
- package/test/unit/data-structures/heap/heap.test.ts +254 -0
- package/test/unit/data-structures/heap/max-heap.test.ts +52 -0
- package/test/unit/data-structures/heap/min-heap.test.ts +52 -0
- package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +400 -0
- package/test/unit/data-structures/linked-list/linked-list.test.ts +8 -0
- package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +474 -0
- package/test/unit/data-structures/linked-list/skip-linked-list.test.ts +13 -0
- package/test/unit/data-structures/linked-list/skip-list.test.ts +86 -0
- package/test/unit/data-structures/matrix/matrix.test.ts +54 -0
- package/test/unit/data-structures/matrix/matrix2d.test.ts +345 -0
- package/test/unit/data-structures/matrix/navigator.test.ts +244 -0
- package/test/unit/data-structures/matrix/vector2d.test.ts +171 -0
- package/test/unit/data-structures/priority-queue/max-priority-queue.test.ts +73 -0
- package/test/unit/data-structures/priority-queue/min-priority-queue.test.ts +63 -0
- package/test/unit/data-structures/priority-queue/priority-queue.test.ts +53 -0
- package/test/unit/data-structures/queue/deque.test.ts +410 -0
- package/test/unit/data-structures/queue/queue.test.ts +207 -0
- package/test/unit/data-structures/stack/stack.test.ts +67 -0
- package/test/unit/data-structures/tree/tree.test.ts +39 -0
- package/test/unit/data-structures/trie/trie.test.ts +825 -0
- package/test/utils/array.ts +5514 -0
- package/test/utils/big-o.ts +207 -0
- package/test/utils/console.ts +31 -0
- package/test/utils/index.ts +7 -0
- package/test/utils/is.ts +56 -0
- package/test/utils/json2html.ts +322 -0
- package/test/utils/number.ts +13 -0
- package/test/utils/string.ts +1 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import * as Benchmark from 'benchmark';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as fastGlob from 'fast-glob';
|
|
5
|
+
import {Color, numberFix, render} from '../utils';
|
|
6
|
+
import {PerformanceTest} from './types';
|
|
7
|
+
|
|
8
|
+
const reportDistPath = 'benchmark';
|
|
9
|
+
const testDir = path.join(__dirname, 'data-structures');
|
|
10
|
+
const testFiles = fastGlob.sync(path.join(testDir, '**', '*.test.ts'));
|
|
11
|
+
|
|
12
|
+
const report: {[key: string]: any} = {};
|
|
13
|
+
|
|
14
|
+
let completedCount = 0;
|
|
15
|
+
|
|
16
|
+
const performanceTests: PerformanceTest[] = [];
|
|
17
|
+
const {GREEN, BOLD, END, YELLOW, GRAY, CYAN, BG_YELLOW} = Color;
|
|
18
|
+
|
|
19
|
+
testFiles.forEach((file: string) => {
|
|
20
|
+
const testName = path.basename(file, '.test.ts');
|
|
21
|
+
const testFunction = require(file);
|
|
22
|
+
const {suite} = testFunction;
|
|
23
|
+
if (suite) performanceTests.push({testName, suite, file});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const composeReport = () => {
|
|
27
|
+
if (!fs.existsSync(reportDistPath)) fs.mkdirSync(reportDistPath, {recursive: true});
|
|
28
|
+
|
|
29
|
+
const filePath = path.join(reportDistPath, 'report.json');
|
|
30
|
+
const htmlFilePath = path.join(reportDistPath, 'report.html');
|
|
31
|
+
fs.writeFileSync(filePath, JSON.stringify(report, null, 2));
|
|
32
|
+
let html = `<!DOCTYPE html>
|
|
33
|
+
<html lang="en">
|
|
34
|
+
<head>
|
|
35
|
+
<meta charset="UTF-8">
|
|
36
|
+
<title>performance of data-structure-typed</title>
|
|
37
|
+
<style>
|
|
38
|
+
*{
|
|
39
|
+
box-sizing: border-box;
|
|
40
|
+
}
|
|
41
|
+
#json-to-html {
|
|
42
|
+
padding: 0 10px 20px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.json-to-html-label {
|
|
46
|
+
font-size: 2rem;
|
|
47
|
+
margin: 2rem 0 0 3px;
|
|
48
|
+
}
|
|
49
|
+
.content table {
|
|
50
|
+
width: 100%;
|
|
51
|
+
table-layout: fixed;
|
|
52
|
+
border-collapse: collapse;
|
|
53
|
+
margin-top: 10px;
|
|
54
|
+
font-size: 16px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.content table th,
|
|
58
|
+
.content table td {
|
|
59
|
+
padding: 8px 12px;
|
|
60
|
+
text-align: left;
|
|
61
|
+
border: 1px solid #ddd;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.content table th {
|
|
65
|
+
background-color: #f2f2f2;
|
|
66
|
+
font-weight: bold;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.content table tr:nth-child(odd) {
|
|
70
|
+
background-color: #ffffff;
|
|
71
|
+
}
|
|
72
|
+
</style>
|
|
73
|
+
</head>
|
|
74
|
+
<body>
|
|
75
|
+
<div id="json-to-html">`;
|
|
76
|
+
let htmlTables = '';
|
|
77
|
+
for (const r in report) {
|
|
78
|
+
if (report.hasOwnProperty(r)) {
|
|
79
|
+
htmlTables += render(report[r].testName, report[r].benchmarks, {
|
|
80
|
+
plainHtml: true,
|
|
81
|
+
'<>': 'table',
|
|
82
|
+
html: [
|
|
83
|
+
{
|
|
84
|
+
'<>': 'tr',
|
|
85
|
+
html: [
|
|
86
|
+
{'<>': 'td', html: '${name}'},
|
|
87
|
+
{'<>': 'td', html: '${periodMS}'},
|
|
88
|
+
{'<>': 'td', html: '${mean}'}
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
htmlTables += `
|
|
96
|
+
|
|
97
|
+
`;
|
|
98
|
+
html += htmlTables;
|
|
99
|
+
html += `</div>
|
|
100
|
+
</body>
|
|
101
|
+
</html>`;
|
|
102
|
+
replaceMarkdownContent(
|
|
103
|
+
'[//]: # (Start of Replace Section)', // Start tag
|
|
104
|
+
'[//]: # (End of Replace Section)', // end identifier
|
|
105
|
+
htmlTables // New content to be inserted
|
|
106
|
+
);
|
|
107
|
+
fs.writeFileSync(htmlFilePath, html);
|
|
108
|
+
console.log(`Performance ${BOLD}${GREEN}report${END} file generated`);
|
|
109
|
+
};
|
|
110
|
+
function replaceMarkdownContent(startMarker: string, endMarker: string, newText: string) {
|
|
111
|
+
const parentDirectory = path.resolve(__dirname, '../..'); // The path to the parent directory
|
|
112
|
+
const filePath = path.join(parentDirectory, 'README.md'); // Path to README.md file
|
|
113
|
+
fs.readFile(filePath, 'utf8', (err, data) => {
|
|
114
|
+
if (err) {
|
|
115
|
+
console.error(`Unable to read ${filePath}:`, err);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Find the start and end markers in the content
|
|
120
|
+
const startIndex = data.indexOf(startMarker);
|
|
121
|
+
const endIndex = data.indexOf(endMarker, startIndex + 1);
|
|
122
|
+
|
|
123
|
+
if (startIndex === -1 || endIndex === -1) {
|
|
124
|
+
console.error('Unable to find start or end marker');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Replace the old content with the new text
|
|
129
|
+
const updatedMarkdown = data.slice(0, startIndex + startMarker.length) + '\n' + newText + data.slice(endIndex);
|
|
130
|
+
|
|
131
|
+
// Try writing the modified content back to the file
|
|
132
|
+
fs.writeFile(filePath, updatedMarkdown, 'utf8', err => {
|
|
133
|
+
if (err) {
|
|
134
|
+
console.error(`Unable to write to ${filePath}:`, err);
|
|
135
|
+
} else {
|
|
136
|
+
console.log(`The content has been successfully replaced in ${filePath}!`);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
performanceTests.forEach(item => {
|
|
143
|
+
const {suite, testName, file} = item;
|
|
144
|
+
const relativeFilePath = path.relative(__dirname, file);
|
|
145
|
+
const directory = path.dirname(relativeFilePath);
|
|
146
|
+
const fileName = path.basename(relativeFilePath);
|
|
147
|
+
console.log(`${BG_YELLOW} Running ${END} ${GRAY}${directory}/${END}${CYAN}${fileName}${END}`);
|
|
148
|
+
|
|
149
|
+
if (suite) {
|
|
150
|
+
let runTime = 0;
|
|
151
|
+
suite
|
|
152
|
+
.on('complete', function (this: Benchmark.Suite) {
|
|
153
|
+
completedCount++;
|
|
154
|
+
report[testName] = {};
|
|
155
|
+
report[testName].benchmarks = this.map((benchmark: Benchmark) => {
|
|
156
|
+
runTime += benchmark.times.elapsed;
|
|
157
|
+
return {
|
|
158
|
+
'test name': benchmark.name,
|
|
159
|
+
'time taken (ms)': numberFix(benchmark.times.period * 1000, 2),
|
|
160
|
+
'executions per sec': numberFix(benchmark.hz, 2),
|
|
161
|
+
// 'executed times': numberFix(benchmark.count, 0),
|
|
162
|
+
// 'sample mean (secs)': numberFix(benchmark.stats.mean, 2),
|
|
163
|
+
'sample deviation': numberFix(benchmark.stats.deviation, 2)
|
|
164
|
+
};
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
report[testName].testName = testName;
|
|
168
|
+
const isDone = completedCount === performanceTests.length;
|
|
169
|
+
runTime = Number(runTime.toFixed(2));
|
|
170
|
+
const isTimeWarn = runTime > 120;
|
|
171
|
+
console.log(
|
|
172
|
+
// `Files: ${GREEN}${testFileCount}${END} `,
|
|
173
|
+
// `Suites: ${GREEN}${performanceTests.length}${END} `,
|
|
174
|
+
`Suites Progress: ${isDone ? GREEN : YELLOW}${completedCount}${END}/${isDone ? GREEN : YELLOW}${
|
|
175
|
+
performanceTests.length
|
|
176
|
+
}${END}`,
|
|
177
|
+
`Time: ${isTimeWarn ? YELLOW : GREEN}${runTime}s${END}`
|
|
178
|
+
);
|
|
179
|
+
if (isDone) {
|
|
180
|
+
composeReport();
|
|
181
|
+
}
|
|
182
|
+
})
|
|
183
|
+
.run({async: false});
|
|
184
|
+
}
|
|
185
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './reportor';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './utils';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type AnyFunction = (...args: any[]) => any;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type Json2htmlOptions = {plainHtml?: boolean} & Partial<{[key: string]: any}>;
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import {AVLTree, AVLTreeNode, CP, IterationType} from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('AVL Tree Test', () => {
|
|
4
|
+
it('should perform various operations on a AVL Tree', () => {
|
|
5
|
+
const arr = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5];
|
|
6
|
+
const tree = new AVLTree<number>();
|
|
7
|
+
|
|
8
|
+
for (const i of arr) tree.add(i, i);
|
|
9
|
+
|
|
10
|
+
const node6 = tree.getNode(6);
|
|
11
|
+
|
|
12
|
+
expect(node6 && tree.getHeight(node6)).toBe(3);
|
|
13
|
+
expect(node6 && tree.getDepth(node6)).toBe(1);
|
|
14
|
+
|
|
15
|
+
const getNodeById = tree.getNode(10);
|
|
16
|
+
expect(getNodeById?.key).toBe(10);
|
|
17
|
+
|
|
18
|
+
const getMinNodeByRoot = tree.getLeftMost();
|
|
19
|
+
expect(getMinNodeByRoot?.key).toBe(1);
|
|
20
|
+
|
|
21
|
+
const node15 = tree.getNode(15);
|
|
22
|
+
const getMinNodeBySpecificNode = node15 && tree.getLeftMost(node15);
|
|
23
|
+
expect(getMinNodeBySpecificNode?.key).toBe(12);
|
|
24
|
+
|
|
25
|
+
let subTreeSum = 0;
|
|
26
|
+
node15 && tree.subTreeTraverse(node => (subTreeSum += node.key), node15);
|
|
27
|
+
expect(subTreeSum).toBe(70);
|
|
28
|
+
|
|
29
|
+
let lesserSum = 0;
|
|
30
|
+
tree.lesserOrGreaterTraverse(node => (lesserSum += node.key), CP.lt, 10);
|
|
31
|
+
expect(lesserSum).toBe(45);
|
|
32
|
+
|
|
33
|
+
// node15 has type problem. After the uniform design, the generics of containers (DirectedGraph, BST) are based on the type of value. However, this design has a drawback: when I attempt to inherit from the Vertex or BSTNode classes, the types of the results obtained by all methods are those of the parent class.
|
|
34
|
+
expect(node15?.value).toBe(15);
|
|
35
|
+
|
|
36
|
+
const dfs = tree.dfs(node => node, 'in');
|
|
37
|
+
expect(dfs[0].key).toBe(1);
|
|
38
|
+
expect(dfs[dfs.length - 1].key).toBe(16);
|
|
39
|
+
|
|
40
|
+
tree.perfectlyBalance();
|
|
41
|
+
const bfs = tree.bfs(node => node);
|
|
42
|
+
expect(tree.isPerfectlyBalanced()).toBe(true);
|
|
43
|
+
expect(bfs[0].key).toBe(8);
|
|
44
|
+
expect(bfs[bfs.length - 1].key).toBe(16);
|
|
45
|
+
|
|
46
|
+
expect(tree.delete(11)[0].deleted?.key).toBe(11);
|
|
47
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
48
|
+
expect(node15 && tree.getHeight(node15)).toBe(2);
|
|
49
|
+
|
|
50
|
+
expect(tree.delete(1)[0].deleted?.key).toBe(1);
|
|
51
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
52
|
+
expect(tree.getHeight()).toBe(4);
|
|
53
|
+
|
|
54
|
+
expect(tree.delete(4)[0].deleted?.key).toBe(4);
|
|
55
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
56
|
+
expect(tree.getHeight()).toBe(4);
|
|
57
|
+
|
|
58
|
+
expect(tree.delete(10)[0].deleted?.key).toBe(10);
|
|
59
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
60
|
+
expect(tree.getHeight()).toBe(3);
|
|
61
|
+
|
|
62
|
+
expect(tree.delete(15)[0].deleted?.key).toBe(15);
|
|
63
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
64
|
+
|
|
65
|
+
expect(tree.getHeight()).toBe(3);
|
|
66
|
+
|
|
67
|
+
expect(tree.delete(5)[0].deleted?.key).toBe(5);
|
|
68
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
69
|
+
expect(tree.getHeight()).toBe(3);
|
|
70
|
+
|
|
71
|
+
expect(tree.delete(13)[0].deleted?.key).toBe(13);
|
|
72
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
73
|
+
expect(tree.getHeight()).toBe(3);
|
|
74
|
+
|
|
75
|
+
expect(tree.delete(3)[0].deleted?.key).toBe(3);
|
|
76
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
77
|
+
expect(tree.getHeight()).toBe(3);
|
|
78
|
+
|
|
79
|
+
expect(tree.delete(8)[0].deleted?.key).toBe(8);
|
|
80
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
81
|
+
expect(tree.getHeight()).toBe(3);
|
|
82
|
+
|
|
83
|
+
expect(tree.delete(6)[0].deleted?.key).toBe(6);
|
|
84
|
+
expect(tree.delete(6).length).toBe(0);
|
|
85
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
86
|
+
expect(tree.getHeight()).toBe(2);
|
|
87
|
+
|
|
88
|
+
expect(tree.delete(7)[0].deleted?.key).toBe(7);
|
|
89
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
90
|
+
expect(tree.getHeight()).toBe(2);
|
|
91
|
+
|
|
92
|
+
expect(tree.delete(9)[0].deleted?.key).toBe(9);
|
|
93
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
94
|
+
expect(tree.getHeight()).toBe(2);
|
|
95
|
+
expect(tree.delete(14)[0].deleted?.key).toBe(14);
|
|
96
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
97
|
+
expect(tree.getHeight()).toBe(1);
|
|
98
|
+
|
|
99
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
100
|
+
const lastBFSIds = tree.bfs();
|
|
101
|
+
expect(lastBFSIds[0]).toBe(12);
|
|
102
|
+
expect(lastBFSIds[1]).toBe(2);
|
|
103
|
+
expect(lastBFSIds[2]).toBe(16);
|
|
104
|
+
|
|
105
|
+
const lastBFSNodes = tree.bfs(node => node);
|
|
106
|
+
expect(lastBFSNodes[0].key).toBe(12);
|
|
107
|
+
expect(lastBFSNodes[1].key).toBe(2);
|
|
108
|
+
expect(lastBFSNodes[2].key).toBe(16);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe('AVL Tree Test recursively', () => {
|
|
113
|
+
it('should perform various operations on a AVL Tree', () => {
|
|
114
|
+
const arr = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5];
|
|
115
|
+
const tree = new AVLTree<number>({iterationType: IterationType.RECURSIVE});
|
|
116
|
+
|
|
117
|
+
for (const i of arr) tree.add(i, i);
|
|
118
|
+
|
|
119
|
+
const node6 = tree.getNode(6);
|
|
120
|
+
|
|
121
|
+
expect(node6 && tree.getHeight(node6)).toBe(3);
|
|
122
|
+
expect(node6 && tree.getDepth(node6)).toBe(1);
|
|
123
|
+
|
|
124
|
+
const getNodeById = tree.getNode(10);
|
|
125
|
+
expect(getNodeById?.key).toBe(10);
|
|
126
|
+
|
|
127
|
+
const getMinNodeByRoot = tree.getLeftMost();
|
|
128
|
+
expect(getMinNodeByRoot?.key).toBe(1);
|
|
129
|
+
|
|
130
|
+
const node15 = tree.getNode(15);
|
|
131
|
+
const getMinNodeBySpecificNode = node15 && tree.getLeftMost(node15);
|
|
132
|
+
expect(getMinNodeBySpecificNode?.key).toBe(12);
|
|
133
|
+
|
|
134
|
+
let subTreeSum = 0;
|
|
135
|
+
node15 && tree.subTreeTraverse(node => (subTreeSum += node.key), node15);
|
|
136
|
+
expect(subTreeSum).toBe(70);
|
|
137
|
+
|
|
138
|
+
let lesserSum = 0;
|
|
139
|
+
tree.lesserOrGreaterTraverse(node => (lesserSum += node.key), CP.lt, 10);
|
|
140
|
+
expect(lesserSum).toBe(45);
|
|
141
|
+
|
|
142
|
+
// node15 has type problem. After the uniform design, the generics of containers (DirectedGraph, BST) are based on the type of value. However, this design has a drawback: when I attempt to inherit from the Vertex or BSTNode classes, the types of the results obtained by all methods are those of the parent class.
|
|
143
|
+
expect(node15?.value).toBe(15);
|
|
144
|
+
|
|
145
|
+
const dfs = tree.dfs(node => node, 'in');
|
|
146
|
+
expect(dfs[0].key).toBe(1);
|
|
147
|
+
expect(dfs[dfs.length - 1].key).toBe(16);
|
|
148
|
+
|
|
149
|
+
tree.perfectlyBalance();
|
|
150
|
+
const bfs = tree.bfs(node => node);
|
|
151
|
+
expect(tree.isPerfectlyBalanced()).toBe(true);
|
|
152
|
+
expect(bfs[0].key).toBe(8);
|
|
153
|
+
expect(bfs[bfs.length - 1].key).toBe(16);
|
|
154
|
+
|
|
155
|
+
expect(tree.delete(11)[0].deleted?.key).toBe(11);
|
|
156
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
157
|
+
expect(node15 && tree.getHeight(node15)).toBe(2);
|
|
158
|
+
|
|
159
|
+
expect(tree.delete(1)[0].deleted?.key).toBe(1);
|
|
160
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
161
|
+
expect(tree.getHeight()).toBe(4);
|
|
162
|
+
|
|
163
|
+
expect(tree.delete(4)[0].deleted?.key).toBe(4);
|
|
164
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
165
|
+
expect(tree.getHeight()).toBe(4);
|
|
166
|
+
|
|
167
|
+
expect(tree.delete(10)[0].deleted?.key).toBe(10);
|
|
168
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
169
|
+
expect(tree.getHeight()).toBe(3);
|
|
170
|
+
|
|
171
|
+
expect(tree.delete(15)[0].deleted?.key).toBe(15);
|
|
172
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
173
|
+
|
|
174
|
+
expect(tree.getHeight()).toBe(3);
|
|
175
|
+
|
|
176
|
+
expect(tree.delete(5)[0].deleted?.key).toBe(5);
|
|
177
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
178
|
+
expect(tree.getHeight()).toBe(3);
|
|
179
|
+
|
|
180
|
+
expect(tree.delete(13)[0].deleted?.key).toBe(13);
|
|
181
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
182
|
+
expect(tree.getHeight()).toBe(3);
|
|
183
|
+
|
|
184
|
+
expect(tree.delete(3)[0].deleted?.key).toBe(3);
|
|
185
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
186
|
+
expect(tree.getHeight()).toBe(3);
|
|
187
|
+
|
|
188
|
+
expect(tree.delete(8)[0].deleted?.key).toBe(8);
|
|
189
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
190
|
+
expect(tree.getHeight()).toBe(3);
|
|
191
|
+
|
|
192
|
+
expect(tree.delete(6)[0].deleted?.key).toBe(6);
|
|
193
|
+
expect(tree.delete(6).length).toBe(0);
|
|
194
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
195
|
+
expect(tree.getHeight()).toBe(2);
|
|
196
|
+
|
|
197
|
+
expect(tree.delete(7)[0].deleted?.key).toBe(7);
|
|
198
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
199
|
+
expect(tree.getHeight()).toBe(2);
|
|
200
|
+
|
|
201
|
+
expect(tree.delete(9)[0].deleted?.key).toBe(9);
|
|
202
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
203
|
+
expect(tree.getHeight()).toBe(2);
|
|
204
|
+
expect(tree.delete(14)[0].deleted?.key).toBe(14);
|
|
205
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
206
|
+
expect(tree.getHeight()).toBe(1);
|
|
207
|
+
|
|
208
|
+
expect(tree.isAVLBalanced()).toBe(true);
|
|
209
|
+
const lastBFSIds = tree.bfs();
|
|
210
|
+
expect(lastBFSIds[0]).toBe(12);
|
|
211
|
+
expect(lastBFSIds[1]).toBe(2);
|
|
212
|
+
expect(lastBFSIds[2]).toBe(16);
|
|
213
|
+
|
|
214
|
+
const lastBFSNodes = tree.bfs(node => node);
|
|
215
|
+
expect(lastBFSNodes[0].key).toBe(12);
|
|
216
|
+
expect(lastBFSNodes[1].key).toBe(2);
|
|
217
|
+
expect(lastBFSNodes[2].key).toBe(16);
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
describe('AVLTree APIs test', () => {
|
|
222
|
+
const avl = new AVLTree<{id: number; text: string}>();
|
|
223
|
+
beforeEach(() => {
|
|
224
|
+
avl.clear();
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('add', () => {
|
|
228
|
+
avl.add(1);
|
|
229
|
+
const node2 = new AVLTreeNode(2);
|
|
230
|
+
avl.add(node2);
|
|
231
|
+
const node3 = new AVLTreeNode(3, {id: 3, text: 'text3'});
|
|
232
|
+
avl.add(node3);
|
|
233
|
+
avl.add(node3, {id: 3, text: 'text33'});
|
|
234
|
+
|
|
235
|
+
const bfsRes = avl.bfs(node => node.key);
|
|
236
|
+
expect(bfsRes[0]).toBe(2);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
describe('AVLTree', () => {
|
|
241
|
+
it('should balance the tree using _balanceLR when nodes are added', () => {
|
|
242
|
+
const avlTree = new AVLTree();
|
|
243
|
+
avlTree.add(10, 'A');
|
|
244
|
+
avlTree.add(5, 'B');
|
|
245
|
+
avlTree.add(15, 'C');
|
|
246
|
+
avlTree.add(3, 'D');
|
|
247
|
+
avlTree.add(7, 'E');
|
|
248
|
+
|
|
249
|
+
// Adding nodes to trigger _balanceLR
|
|
250
|
+
avlTree.add(12, 'F');
|
|
251
|
+
|
|
252
|
+
// You can add more specific assertions to check the tree's balance and structure.
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('should balance the tree using _balanceLR when nodes are deleted', () => {
|
|
256
|
+
const avlTree = new AVLTree();
|
|
257
|
+
avlTree.add(10, 'A');
|
|
258
|
+
avlTree.add(5, 'B');
|
|
259
|
+
avlTree.add(15, 'C');
|
|
260
|
+
avlTree.add(3, 'D');
|
|
261
|
+
avlTree.add(7, 'E');
|
|
262
|
+
avlTree.add(12, 'F');
|
|
263
|
+
|
|
264
|
+
// Deleting nodes to trigger _balanceLR
|
|
265
|
+
avlTree.delete(3);
|
|
266
|
+
|
|
267
|
+
// You can add more specific assertions to check the tree's balance and structure.
|
|
268
|
+
});
|
|
269
|
+
});
|