data-structure-typed 1.41.0 → 1.41.2
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/dist/cjs/data-structures/binary-tree/avl-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/binary-indexed-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/binary-tree.d.ts +9 -6
- package/dist/cjs/data-structures/binary-tree/binary-tree.js +29 -10
- package/dist/cjs/data-structures/binary-tree/binary-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/bst.d.ts +1 -1
- package/dist/cjs/data-structures/binary-tree/bst.js +2 -2
- package/dist/cjs/data-structures/binary-tree/bst.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/rb-tree.d.ts +20 -4
- package/dist/cjs/data-structures/binary-tree/rb-tree.js +109 -44
- package/dist/cjs/data-structures/binary-tree/rb-tree.js.map +1 -1
- package/dist/cjs/data-structures/binary-tree/tree-multiset.js +2 -2
- package/dist/cjs/data-structures/binary-tree/tree-multiset.js.map +1 -1
- package/dist/cjs/data-structures/graph/abstract-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/directed-graph.js.map +1 -1
- package/dist/cjs/data-structures/graph/undirected-graph.js.map +1 -1
- package/dist/cjs/data-structures/hash/hash-map.js.map +1 -1
- package/dist/cjs/data-structures/hash/tree-map.js.map +1 -1
- package/dist/cjs/data-structures/hash/tree-set.js.map +1 -1
- package/dist/cjs/data-structures/heap/heap.js.map +1 -1
- package/dist/cjs/data-structures/heap/max-heap.js.map +1 -1
- package/dist/cjs/data-structures/heap/min-heap.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/doubly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/linked-list/singly-linked-list.js.map +1 -1
- package/dist/cjs/data-structures/matrix/matrix.js.map +1 -1
- package/dist/cjs/data-structures/matrix/vector2d.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/max-priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/min-priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/priority-queue/priority-queue.js.map +1 -1
- package/dist/cjs/data-structures/queue/deque.js.map +1 -1
- package/dist/cjs/data-structures/queue/queue.js.map +1 -1
- package/dist/mjs/data-structures/binary-tree/binary-tree.d.ts +9 -6
- package/dist/mjs/data-structures/binary-tree/binary-tree.js +28 -10
- package/dist/mjs/data-structures/binary-tree/bst.d.ts +1 -1
- package/dist/mjs/data-structures/binary-tree/bst.js +2 -2
- package/dist/mjs/data-structures/binary-tree/rb-tree.d.ts +20 -4
- package/dist/mjs/data-structures/binary-tree/rb-tree.js +110 -45
- package/dist/mjs/data-structures/binary-tree/tree-multiset.js +2 -2
- package/dist/umd/data-structure-typed.min.js +1 -1
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +9 -9
- package/src/data-structures/binary-tree/avl-tree.ts +3 -2
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +1 -1
- package/src/data-structures/binary-tree/binary-tree.ts +73 -25
- package/src/data-structures/binary-tree/bst.ts +7 -4
- package/src/data-structures/binary-tree/rb-tree.ts +121 -68
- package/src/data-structures/binary-tree/tree-multiset.ts +4 -3
- package/src/data-structures/graph/abstract-graph.ts +11 -12
- package/src/data-structures/graph/directed-graph.ts +7 -6
- package/src/data-structures/graph/undirected-graph.ts +7 -6
- package/src/data-structures/hash/hash-map.ts +1 -1
- package/src/data-structures/hash/tree-map.ts +1 -2
- package/src/data-structures/hash/tree-set.ts +1 -2
- package/src/data-structures/heap/heap.ts +2 -2
- package/src/data-structures/heap/max-heap.ts +1 -1
- package/src/data-structures/heap/min-heap.ts +1 -1
- package/src/data-structures/linked-list/doubly-linked-list.ts +1 -1
- package/src/data-structures/linked-list/singly-linked-list.ts +1 -1
- package/src/data-structures/matrix/matrix.ts +1 -1
- package/src/data-structures/matrix/vector2d.ts +1 -2
- package/src/data-structures/priority-queue/max-priority-queue.ts +1 -1
- package/src/data-structures/priority-queue/min-priority-queue.ts +1 -1
- package/src/data-structures/priority-queue/priority-queue.ts +1 -1
- package/src/data-structures/queue/deque.ts +3 -4
- package/src/data-structures/queue/queue.ts +1 -1
- package/src/types/data-structures/matrix/navigator.ts +1 -1
- package/src/types/utils/utils.ts +1 -1
- package/src/types/utils/validate-type.ts +2 -2
- package/test/integration/avl-tree.test.ts +3 -3
- package/test/integration/bst.test.ts +7 -7
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +6 -6
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +11 -11
- package/test/unit/data-structures/binary-tree/bst.test.ts +22 -20
- package/test/unit/data-structures/binary-tree/overall.test.ts +2 -2
- package/test/unit/data-structures/binary-tree/rb-tree.test.ts +214 -21
- package/test/unit/data-structures/binary-tree/tree-multiset.test.ts +8 -8
- package/test/utils/big-o.js +10 -0
|
@@ -1,27 +1,41 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* data-structure-typed
|
|
3
|
+
*
|
|
4
|
+
* @author Tyler Zeng
|
|
5
|
+
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
6
|
+
* @license MIT License
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {RBTNColor} from '../../types';
|
|
2
10
|
|
|
3
11
|
export class RBTreeNode {
|
|
4
|
-
key: number
|
|
12
|
+
key: number;
|
|
5
13
|
parent: RBTreeNode;
|
|
6
14
|
left: RBTreeNode;
|
|
7
15
|
right: RBTreeNode;
|
|
8
16
|
color: number = RBTNColor.BLACK;
|
|
9
17
|
|
|
10
|
-
constructor() {
|
|
18
|
+
constructor(key: number, color: RBTNColor = RBTNColor.BLACK) {
|
|
19
|
+
this.key = key;
|
|
20
|
+
this.color = color;
|
|
11
21
|
this.parent = null as unknown as RBTreeNode;
|
|
12
22
|
this.left = null as unknown as RBTreeNode;
|
|
13
23
|
this.right = null as unknown as RBTreeNode;
|
|
14
24
|
}
|
|
15
25
|
}
|
|
16
26
|
|
|
27
|
+
export const NIL = new RBTreeNode(0);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 1. Each node is either red or black.
|
|
31
|
+
* 2. The root node is always black.
|
|
32
|
+
* 3. Leaf nodes are typically NIL nodes and are considered black.
|
|
33
|
+
* 4. Red nodes must have black children.
|
|
34
|
+
* 5. Black balance: Every path from any node to each of its leaf nodes contains the same number of black nodes.
|
|
35
|
+
*/
|
|
17
36
|
export class RedBlackTree {
|
|
18
|
-
|
|
19
37
|
constructor() {
|
|
20
|
-
this.
|
|
21
|
-
this.NIL.color = RBTNColor.BLACK;
|
|
22
|
-
this.NIL.left = null as unknown as RBTreeNode;
|
|
23
|
-
this.NIL.right = null as unknown as RBTreeNode;
|
|
24
|
-
this._root = this.NIL;
|
|
38
|
+
this._root = NIL;
|
|
25
39
|
}
|
|
26
40
|
|
|
27
41
|
protected _root: RBTreeNode;
|
|
@@ -30,12 +44,6 @@ export class RedBlackTree {
|
|
|
30
44
|
return this._root;
|
|
31
45
|
}
|
|
32
46
|
|
|
33
|
-
protected _NIL: RBTreeNode;
|
|
34
|
-
|
|
35
|
-
get NIL(): RBTreeNode {
|
|
36
|
-
return this._NIL;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
47
|
/**
|
|
40
48
|
* The `insert` function inserts a new node with a given key into a red-black tree and fixes any
|
|
41
49
|
* violations of the red-black tree properties.
|
|
@@ -44,18 +52,14 @@ export class RedBlackTree {
|
|
|
44
52
|
* @returns The function does not explicitly return anything.
|
|
45
53
|
*/
|
|
46
54
|
insert(key: number): void {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
node.
|
|
50
|
-
node.key = key;
|
|
51
|
-
node.left = this.NIL;
|
|
52
|
-
node.right = this.NIL;
|
|
53
|
-
node.color = RBTNColor.RED;
|
|
55
|
+
const node: RBTreeNode = new RBTreeNode(key, RBTNColor.RED);
|
|
56
|
+
node.left = NIL;
|
|
57
|
+
node.right = NIL;
|
|
54
58
|
|
|
55
59
|
let y: RBTreeNode = null as unknown as RBTreeNode;
|
|
56
60
|
let x: RBTreeNode = this.root;
|
|
57
61
|
|
|
58
|
-
while (x !==
|
|
62
|
+
while (x !== NIL) {
|
|
59
63
|
y = x;
|
|
60
64
|
if (node.key < x.key) {
|
|
61
65
|
x = x.left;
|
|
@@ -94,10 +98,9 @@ export class RedBlackTree {
|
|
|
94
98
|
*/
|
|
95
99
|
delete(key: number): void {
|
|
96
100
|
const helper = (node: RBTreeNode): void => {
|
|
97
|
-
|
|
98
|
-
let z: RBTreeNode = this.NIL;
|
|
101
|
+
let z: RBTreeNode = NIL;
|
|
99
102
|
let x: RBTreeNode, y: RBTreeNode;
|
|
100
|
-
while (node !==
|
|
103
|
+
while (node !== NIL) {
|
|
101
104
|
if (node.key === key) {
|
|
102
105
|
z = node;
|
|
103
106
|
}
|
|
@@ -109,17 +112,16 @@ export class RedBlackTree {
|
|
|
109
112
|
}
|
|
110
113
|
}
|
|
111
114
|
|
|
112
|
-
if (z ===
|
|
113
|
-
console.log("Couldn't find key in the tree");
|
|
115
|
+
if (z === NIL) {
|
|
114
116
|
return;
|
|
115
117
|
}
|
|
116
118
|
|
|
117
119
|
y = z;
|
|
118
120
|
let yOriginalColor: number = y.color;
|
|
119
|
-
if (z.left ===
|
|
121
|
+
if (z.left === NIL) {
|
|
120
122
|
x = z.right;
|
|
121
123
|
this._rbTransplant(z, z.right);
|
|
122
|
-
} else if (z.right ===
|
|
124
|
+
} else if (z.right === NIL) {
|
|
123
125
|
x = z.left;
|
|
124
126
|
this._rbTransplant(z, z.left);
|
|
125
127
|
} else {
|
|
@@ -139,13 +141,17 @@ export class RedBlackTree {
|
|
|
139
141
|
y.left.parent = y;
|
|
140
142
|
y.color = z.color;
|
|
141
143
|
}
|
|
142
|
-
if (yOriginalColor ===
|
|
144
|
+
if (yOriginalColor === RBTNColor.BLACK) {
|
|
143
145
|
this._fixDelete(x);
|
|
144
146
|
}
|
|
145
|
-
}
|
|
147
|
+
};
|
|
146
148
|
helper(this.root);
|
|
147
149
|
}
|
|
148
150
|
|
|
151
|
+
isRealNode(node: RBTreeNode | null | undefined): node is RBTreeNode {
|
|
152
|
+
return node !== NIL && node !== null;
|
|
153
|
+
}
|
|
154
|
+
|
|
149
155
|
/**
|
|
150
156
|
* The function `getNode` is a recursive depth-first search algorithm that searches for a node with a
|
|
151
157
|
* given key in a red-black tree.
|
|
@@ -158,40 +164,40 @@ export class RedBlackTree {
|
|
|
158
164
|
*/
|
|
159
165
|
getNode(key: number, beginRoot = this.root): RBTreeNode {
|
|
160
166
|
const dfs = (node: RBTreeNode): RBTreeNode => {
|
|
161
|
-
if (
|
|
162
|
-
|
|
163
|
-
|
|
167
|
+
if (this.isRealNode(node)) {
|
|
168
|
+
if (key === node.key) {
|
|
169
|
+
return node;
|
|
170
|
+
}
|
|
164
171
|
|
|
165
|
-
|
|
166
|
-
return dfs(node.
|
|
172
|
+
if (key < node.key) return dfs(node.left);
|
|
173
|
+
return dfs(node.right);
|
|
174
|
+
} else {
|
|
175
|
+
return null as unknown as RBTreeNode;
|
|
167
176
|
}
|
|
168
|
-
|
|
169
|
-
}
|
|
177
|
+
};
|
|
170
178
|
return dfs(beginRoot);
|
|
171
179
|
}
|
|
172
180
|
|
|
173
|
-
|
|
174
181
|
/**
|
|
175
182
|
* The function returns the leftmost node in a red-black tree.
|
|
176
183
|
* @param {RBTreeNode} node - The parameter "node" is of type RBTreeNode, which represents a node in
|
|
177
184
|
* a Red-Black Tree.
|
|
178
185
|
* @returns The leftmost node in the given RBTreeNode.
|
|
179
186
|
*/
|
|
180
|
-
getLeftMost(node: RBTreeNode): RBTreeNode {
|
|
181
|
-
while (node.left !== null && node.left !==
|
|
187
|
+
getLeftMost(node: RBTreeNode = this.root): RBTreeNode {
|
|
188
|
+
while (node.left !== null && node.left !== NIL) {
|
|
182
189
|
node = node.left;
|
|
183
190
|
}
|
|
184
191
|
return node;
|
|
185
192
|
}
|
|
186
193
|
|
|
187
|
-
|
|
188
194
|
/**
|
|
189
195
|
* The function returns the rightmost node in a red-black tree.
|
|
190
196
|
* @param {RBTreeNode} node - The parameter "node" is of type RBTreeNode.
|
|
191
197
|
* @returns the rightmost node in a red-black tree.
|
|
192
198
|
*/
|
|
193
199
|
getRightMost(node: RBTreeNode): RBTreeNode {
|
|
194
|
-
while (node.right !== null && node.right !==
|
|
200
|
+
while (node.right !== null && node.right !== NIL) {
|
|
195
201
|
node = node.right;
|
|
196
202
|
}
|
|
197
203
|
return node;
|
|
@@ -203,13 +209,12 @@ export class RedBlackTree {
|
|
|
203
209
|
* @returns the successor of the given RBTreeNode.
|
|
204
210
|
*/
|
|
205
211
|
getSuccessor(x: RBTreeNode): RBTreeNode {
|
|
206
|
-
|
|
207
|
-
if (x.right !== this.NIL) {
|
|
212
|
+
if (x.right !== NIL) {
|
|
208
213
|
return this.getLeftMost(x.right);
|
|
209
214
|
}
|
|
210
215
|
|
|
211
216
|
let y: RBTreeNode = x.parent;
|
|
212
|
-
while (y !==
|
|
217
|
+
while (y !== NIL && y !== null && x === y.right) {
|
|
213
218
|
x = y;
|
|
214
219
|
y = y.parent;
|
|
215
220
|
}
|
|
@@ -223,13 +228,12 @@ export class RedBlackTree {
|
|
|
223
228
|
* @returns the predecessor of the given RBTreeNode 'x'.
|
|
224
229
|
*/
|
|
225
230
|
getPredecessor(x: RBTreeNode): RBTreeNode {
|
|
226
|
-
|
|
227
|
-
if (x.left !== this.NIL) {
|
|
231
|
+
if (x.left !== NIL) {
|
|
228
232
|
return this.getRightMost(x.left);
|
|
229
233
|
}
|
|
230
234
|
|
|
231
235
|
let y: RBTreeNode = x.parent;
|
|
232
|
-
while (y !==
|
|
236
|
+
while (y !== NIL && x === y.left) {
|
|
233
237
|
x = y;
|
|
234
238
|
y = y.parent;
|
|
235
239
|
}
|
|
@@ -237,6 +241,65 @@ export class RedBlackTree {
|
|
|
237
241
|
return y;
|
|
238
242
|
}
|
|
239
243
|
|
|
244
|
+
print(beginRoot: RBTreeNode = this.root) {
|
|
245
|
+
const display = (root: RBTreeNode | null): void => {
|
|
246
|
+
const [lines, , ,] = _displayAux(root);
|
|
247
|
+
for (const line of lines) {
|
|
248
|
+
console.log(line);
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const _displayAux = (node: RBTreeNode | null): [string[], number, number, number] => {
|
|
253
|
+
if (node === null) {
|
|
254
|
+
return [[], 0, 0, 0];
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (node.right === null && node.left === null) {
|
|
258
|
+
const line = `${node.key}`;
|
|
259
|
+
const width = line.length;
|
|
260
|
+
const height = 1;
|
|
261
|
+
const middle = Math.floor(width / 2);
|
|
262
|
+
return [[line], width, height, middle];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (node.right === null) {
|
|
266
|
+
const [lines, n, p, x] = _displayAux(node.left);
|
|
267
|
+
const s = `${node.key}`;
|
|
268
|
+
const u = s.length;
|
|
269
|
+
const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s;
|
|
270
|
+
const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u);
|
|
271
|
+
const shifted_lines = lines.map(line => line + ' '.repeat(u));
|
|
272
|
+
return [[first_line, second_line, ...shifted_lines], n + u, p + 2, n + Math.floor(u / 2)];
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (node.left === null) {
|
|
276
|
+
const [lines, n, p, u] = _displayAux(node.right);
|
|
277
|
+
const s = `${node.key}`;
|
|
278
|
+
const x = s.length;
|
|
279
|
+
const first_line = s + '_'.repeat(x) + ' '.repeat(n - x);
|
|
280
|
+
const second_line = ' '.repeat(u + x) + '\\' + ' '.repeat(n - x - 1);
|
|
281
|
+
const shifted_lines = lines.map(line => ' '.repeat(u) + line);
|
|
282
|
+
return [[first_line, second_line, ...shifted_lines], n + x, p + 2, Math.floor(u / 2)];
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const [left, n, p, x] = _displayAux(node.left);
|
|
286
|
+
const [right, m, q, y] = _displayAux(node.right);
|
|
287
|
+
const s = `${node.key}`;
|
|
288
|
+
const u = s.length;
|
|
289
|
+
const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s + '_'.repeat(y) + ' '.repeat(m - y);
|
|
290
|
+
const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u + y) + '\\' + ' '.repeat(m - y - 1);
|
|
291
|
+
if (p < q) {
|
|
292
|
+
left.push(...new Array(q - p).fill(' '.repeat(n)));
|
|
293
|
+
} else if (q < p) {
|
|
294
|
+
right.push(...new Array(p - q).fill(' '.repeat(m)));
|
|
295
|
+
}
|
|
296
|
+
const zipped_lines = left.map((a, i) => a + ' '.repeat(u) + right[i]);
|
|
297
|
+
return [[first_line, second_line, ...zipped_lines], n + m + u, Math.max(p, q) + 2, n + Math.floor(u / 2)];
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
display(beginRoot);
|
|
301
|
+
}
|
|
302
|
+
|
|
240
303
|
/**
|
|
241
304
|
* The function performs a left rotation on a red-black tree node.
|
|
242
305
|
* @param {RBTreeNode} x - The parameter `x` is a RBTreeNode object.
|
|
@@ -244,7 +307,7 @@ export class RedBlackTree {
|
|
|
244
307
|
protected _leftRotate(x: RBTreeNode): void {
|
|
245
308
|
const y: RBTreeNode = x.right;
|
|
246
309
|
x.right = y.left;
|
|
247
|
-
if (y.left !==
|
|
310
|
+
if (y.left !== NIL) {
|
|
248
311
|
y.left.parent = x;
|
|
249
312
|
}
|
|
250
313
|
y.parent = x.parent;
|
|
@@ -267,7 +330,7 @@ export class RedBlackTree {
|
|
|
267
330
|
protected _rightRotate(x: RBTreeNode): void {
|
|
268
331
|
const y: RBTreeNode = x.left;
|
|
269
332
|
x.left = y.right;
|
|
270
|
-
if (y.right !==
|
|
333
|
+
if (y.right !== NIL) {
|
|
271
334
|
y.right.parent = x;
|
|
272
335
|
}
|
|
273
336
|
y.parent = x.parent;
|
|
@@ -289,24 +352,21 @@ export class RedBlackTree {
|
|
|
289
352
|
*/
|
|
290
353
|
protected _fixDelete(x: RBTreeNode): void {
|
|
291
354
|
let s: RBTreeNode;
|
|
292
|
-
while (x !== this.root && x.color ===
|
|
355
|
+
while (x !== this.root && x.color === RBTNColor.BLACK) {
|
|
293
356
|
if (x === x.parent.left) {
|
|
294
357
|
s = x.parent.right;
|
|
295
358
|
if (s.color === 1) {
|
|
296
|
-
|
|
297
359
|
s.color = RBTNColor.BLACK;
|
|
298
360
|
x.parent.color = RBTNColor.RED;
|
|
299
361
|
this._leftRotate(x.parent);
|
|
300
362
|
s = x.parent.right;
|
|
301
363
|
}
|
|
302
364
|
|
|
303
|
-
if (s.left.color ===
|
|
304
|
-
|
|
365
|
+
if (s.left !== null && s.left.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {
|
|
305
366
|
s.color = RBTNColor.RED;
|
|
306
367
|
x = x.parent;
|
|
307
368
|
} else {
|
|
308
|
-
if (s.right.color ===
|
|
309
|
-
|
|
369
|
+
if (s.right.color === RBTNColor.BLACK) {
|
|
310
370
|
s.left.color = RBTNColor.BLACK;
|
|
311
371
|
s.color = RBTNColor.RED;
|
|
312
372
|
this._rightRotate(s);
|
|
@@ -322,20 +382,17 @@ export class RedBlackTree {
|
|
|
322
382
|
} else {
|
|
323
383
|
s = x.parent.left;
|
|
324
384
|
if (s.color === 1) {
|
|
325
|
-
|
|
326
385
|
s.color = RBTNColor.BLACK;
|
|
327
386
|
x.parent.color = RBTNColor.RED;
|
|
328
387
|
this._rightRotate(x.parent);
|
|
329
388
|
s = x.parent.left;
|
|
330
389
|
}
|
|
331
390
|
|
|
332
|
-
if (s.right.color ===
|
|
333
|
-
|
|
391
|
+
if (s.right.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {
|
|
334
392
|
s.color = RBTNColor.RED;
|
|
335
393
|
x = x.parent;
|
|
336
394
|
} else {
|
|
337
|
-
if (s.left.color ===
|
|
338
|
-
|
|
395
|
+
if (s.left.color === RBTNColor.BLACK) {
|
|
339
396
|
s.right.color = RBTNColor.BLACK;
|
|
340
397
|
s.color = RBTNColor.RED;
|
|
341
398
|
this._leftRotate(s);
|
|
@@ -380,14 +437,12 @@ export class RedBlackTree {
|
|
|
380
437
|
if (k.parent === k.parent.parent.right) {
|
|
381
438
|
u = k.parent.parent.left;
|
|
382
439
|
if (u.color === 1) {
|
|
383
|
-
|
|
384
440
|
u.color = RBTNColor.BLACK;
|
|
385
441
|
k.parent.color = RBTNColor.BLACK;
|
|
386
442
|
k.parent.parent.color = RBTNColor.RED;
|
|
387
443
|
k = k.parent.parent;
|
|
388
444
|
} else {
|
|
389
445
|
if (k === k.parent.left) {
|
|
390
|
-
|
|
391
446
|
k = k.parent;
|
|
392
447
|
this._rightRotate(k);
|
|
393
448
|
}
|
|
@@ -400,14 +455,12 @@ export class RedBlackTree {
|
|
|
400
455
|
u = k.parent.parent.right;
|
|
401
456
|
|
|
402
457
|
if (u.color === 1) {
|
|
403
|
-
|
|
404
458
|
u.color = RBTNColor.BLACK;
|
|
405
459
|
k.parent.color = RBTNColor.BLACK;
|
|
406
460
|
k.parent.parent.color = RBTNColor.RED;
|
|
407
461
|
k = k.parent.parent;
|
|
408
462
|
} else {
|
|
409
463
|
if (k === k.parent.right) {
|
|
410
|
-
|
|
411
464
|
k = k.parent;
|
|
412
465
|
this._leftRotate(k);
|
|
413
466
|
}
|
|
@@ -423,4 +476,4 @@ export class RedBlackTree {
|
|
|
423
476
|
}
|
|
424
477
|
this.root.color = RBTNColor.BLACK;
|
|
425
478
|
}
|
|
426
|
-
}
|
|
479
|
+
}
|
|
@@ -37,7 +37,8 @@ export class TreeMultisetNode<
|
|
|
37
37
|
*/
|
|
38
38
|
export class TreeMultiset<V = any, N extends TreeMultisetNode<V, N> = TreeMultisetNode<V, TreeMultisetNodeNested<V>>>
|
|
39
39
|
extends AVLTree<V, N>
|
|
40
|
-
implements IBinaryTree<V, N>
|
|
40
|
+
implements IBinaryTree<V, N>
|
|
41
|
+
{
|
|
41
42
|
/**
|
|
42
43
|
* The constructor function for a TreeMultiset class in TypeScript, which extends another class and sets an option to
|
|
43
44
|
* merge duplicated values.
|
|
@@ -169,7 +170,7 @@ export class TreeMultiset<V = any, N extends TreeMultisetNode<V, N> = TreeMultis
|
|
|
169
170
|
} else if (parent.right === undefined) {
|
|
170
171
|
parent.right = newNode;
|
|
171
172
|
if (newNode !== null) {
|
|
172
|
-
this._size =
|
|
173
|
+
this._size = this.size + 1;
|
|
173
174
|
this._setCount(this.count + newNode.count);
|
|
174
175
|
}
|
|
175
176
|
return parent.right;
|
|
@@ -282,7 +283,7 @@ export class TreeMultiset<V = any, N extends TreeMultisetNode<V, N> = TreeMultis
|
|
|
282
283
|
const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];
|
|
283
284
|
if (!this.root) return bstDeletedResult;
|
|
284
285
|
|
|
285
|
-
const curr: N | null = this.
|
|
286
|
+
const curr: N | null = this.getNode(identifier, callback);
|
|
286
287
|
if (!curr) return bstDeletedResult;
|
|
287
288
|
|
|
288
289
|
const parent: N | null = curr?.parent ? curr.parent : null;
|
|
@@ -26,7 +26,6 @@ export abstract class AbstractVertex<V = any> {
|
|
|
26
26
|
this.key = key;
|
|
27
27
|
this.value = value;
|
|
28
28
|
}
|
|
29
|
-
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
export abstract class AbstractEdge<E = any> {
|
|
@@ -65,7 +64,8 @@ export abstract class AbstractGraph<
|
|
|
65
64
|
E = any,
|
|
66
65
|
VO extends AbstractVertex<V> = AbstractVertex<V>,
|
|
67
66
|
EO extends AbstractEdge<E> = AbstractEdge<E>
|
|
68
|
-
> implements IGraph<V, E, VO, EO>
|
|
67
|
+
> implements IGraph<V, E, VO, EO>
|
|
68
|
+
{
|
|
69
69
|
protected _vertices: Map<VertexKey, VO> = new Map<VertexKey, VO>();
|
|
70
70
|
|
|
71
71
|
get vertices(): Map<VertexKey, VO> {
|
|
@@ -513,14 +513,14 @@ export abstract class AbstractGraph<
|
|
|
513
513
|
}
|
|
514
514
|
|
|
515
515
|
getMinDist &&
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
516
|
+
distMap.forEach((d, v) => {
|
|
517
|
+
if (v !== srcVertex) {
|
|
518
|
+
if (d < minDist) {
|
|
519
|
+
minDist = d;
|
|
520
|
+
if (genPaths) minDest = v;
|
|
521
|
+
}
|
|
521
522
|
}
|
|
522
|
-
}
|
|
523
|
-
});
|
|
523
|
+
});
|
|
524
524
|
|
|
525
525
|
genPaths && getPaths(minDest);
|
|
526
526
|
|
|
@@ -582,7 +582,7 @@ export abstract class AbstractGraph<
|
|
|
582
582
|
if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Infinity);
|
|
583
583
|
}
|
|
584
584
|
|
|
585
|
-
const heap = new PriorityQueue<{
|
|
585
|
+
const heap = new PriorityQueue<{key: number; value: VO}>({comparator: (a, b) => a.key - b.key});
|
|
586
586
|
heap.add({key: 0, value: srcVertex});
|
|
587
587
|
|
|
588
588
|
distMap.set(srcVertex, 0);
|
|
@@ -811,7 +811,7 @@ export abstract class AbstractGraph<
|
|
|
811
811
|
* `predecessor` property is a 2D array of vertices (or `null`) representing the predecessor vertices in the shortest
|
|
812
812
|
* path between vertices in the
|
|
813
813
|
*/
|
|
814
|
-
floyd(): {
|
|
814
|
+
floyd(): {costs: number[][]; predecessor: (VO | null)[][]} {
|
|
815
815
|
const idAndVertices = [...this._vertices];
|
|
816
816
|
const n = idAndVertices.length;
|
|
817
817
|
|
|
@@ -996,5 +996,4 @@ export abstract class AbstractGraph<
|
|
|
996
996
|
protected _getVertexKey(vertexOrKey: VO | VertexKey): VertexKey {
|
|
997
997
|
return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey;
|
|
998
998
|
}
|
|
999
|
-
|
|
1000
999
|
}
|
|
@@ -46,13 +46,14 @@ export class DirectedEdge<E = any> extends AbstractEdge<E> {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
export class DirectedGraph<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
>
|
|
49
|
+
V = any,
|
|
50
|
+
E = any,
|
|
51
|
+
VO extends DirectedVertex<V> = DirectedVertex<V>,
|
|
52
|
+
EO extends DirectedEdge<E> = DirectedEdge<E>
|
|
53
|
+
>
|
|
54
54
|
extends AbstractGraph<V, E, VO, EO>
|
|
55
|
-
implements IGraph<V, E, VO, EO>
|
|
55
|
+
implements IGraph<V, E, VO, EO>
|
|
56
|
+
{
|
|
56
57
|
/**
|
|
57
58
|
* The constructor function initializes an instance of a class.
|
|
58
59
|
*/
|
|
@@ -43,13 +43,14 @@ export class UndirectedEdge<E = number> extends AbstractEdge<E> {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
export class UndirectedGraph<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
>
|
|
46
|
+
V = any,
|
|
47
|
+
E = any,
|
|
48
|
+
VO extends UndirectedVertex<V> = UndirectedVertex<V>,
|
|
49
|
+
EO extends UndirectedEdge<E> = UndirectedEdge<E>
|
|
50
|
+
>
|
|
51
51
|
extends AbstractGraph<V, E, VO, EO>
|
|
52
|
-
implements IGraph<V, E, VO, EO>
|
|
52
|
+
implements IGraph<V, E, VO, EO>
|
|
53
|
+
{
|
|
53
54
|
/**
|
|
54
55
|
* The constructor initializes a new Map object to store edges.
|
|
55
56
|
*/
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export class TreeMap {
|
|
2
|
-
}
|
|
1
|
+
export class TreeMap {}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export class TreeSet {
|
|
2
|
-
}
|
|
1
|
+
export class TreeSet {}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import type {Comparator, DFSOrderPattern} from '../../types';
|
|
9
9
|
|
|
10
10
|
export class Heap<E = any> {
|
|
11
|
-
constructor(options: {
|
|
11
|
+
constructor(options: {comparator: Comparator<E>; nodes?: E[]}) {
|
|
12
12
|
this._comparator = options.comparator;
|
|
13
13
|
if (options.nodes && options.nodes.length > 0) {
|
|
14
14
|
this._nodes = options.nodes;
|
|
@@ -48,7 +48,7 @@ export class Heap<E = any> {
|
|
|
48
48
|
* @returns A new Heap instance.
|
|
49
49
|
* @param options
|
|
50
50
|
*/
|
|
51
|
-
static heapify<E>(options: {
|
|
51
|
+
static heapify<E>(options: {nodes: E[]; comparator: Comparator<E>}): Heap<E> {
|
|
52
52
|
return new Heap<E>(options);
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -11,7 +11,7 @@ import type {Comparator} from '../../types';
|
|
|
11
11
|
|
|
12
12
|
export class MaxHeap<E = any> extends Heap<E> {
|
|
13
13
|
constructor(
|
|
14
|
-
options: {
|
|
14
|
+
options: {comparator: Comparator<E>; nodes?: E[]} = {
|
|
15
15
|
comparator: (a: E, b: E) => {
|
|
16
16
|
if (!(typeof a === 'number' && typeof b === 'number')) {
|
|
17
17
|
throw new Error('The a, b params of compare function must be number');
|
|
@@ -11,7 +11,7 @@ import type {Comparator} from '../../types';
|
|
|
11
11
|
|
|
12
12
|
export class MinHeap<E = any> extends Heap<E> {
|
|
13
13
|
constructor(
|
|
14
|
-
options: {
|
|
14
|
+
options: {comparator: Comparator<E>; nodes?: E[]} = {
|
|
15
15
|
comparator: (a: E, b: E) => {
|
|
16
16
|
if (!(typeof a === 'number' && typeof b === 'number')) {
|
|
17
17
|
throw new Error('The a, b params of compare function must be number');
|
|
@@ -594,7 +594,7 @@ export class DoublyLinkedList<E = any> {
|
|
|
594
594
|
/**
|
|
595
595
|
* The function returns an iterator that iterates over the values of a linked list.
|
|
596
596
|
*/
|
|
597
|
-
*
|
|
597
|
+
*[Symbol.iterator]() {
|
|
598
598
|
let current = this.head;
|
|
599
599
|
|
|
600
600
|
while (current) {
|
|
@@ -565,7 +565,7 @@ export class SinglyLinkedList<E = any> {
|
|
|
565
565
|
/**
|
|
566
566
|
* The function returns an iterator that iterates over the values of a linked list.
|
|
567
567
|
*/
|
|
568
|
-
*
|
|
568
|
+
*[Symbol.iterator]() {
|
|
569
569
|
let current = this.head;
|
|
570
570
|
|
|
571
571
|
while (current) {
|
|
@@ -14,7 +14,7 @@ export class MatrixNTI2D<V = any> {
|
|
|
14
14
|
* given initial value or 0 if not provided.
|
|
15
15
|
* @param options - An object containing the following properties:
|
|
16
16
|
*/
|
|
17
|
-
constructor(options: {
|
|
17
|
+
constructor(options: {row: number; col: number; initialVal?: V}) {
|
|
18
18
|
const {row, col, initialVal} = options;
|
|
19
19
|
this._matrix = new Array(row).fill(undefined).map(() => new Array(col).fill(initialVal || 0));
|
|
20
20
|
}
|
|
@@ -10,7 +10,7 @@ import type {Comparator} from '../../types';
|
|
|
10
10
|
|
|
11
11
|
export class MaxPriorityQueue<E = any> extends PriorityQueue<E> {
|
|
12
12
|
constructor(
|
|
13
|
-
options: {
|
|
13
|
+
options: {comparator: Comparator<E>; nodes?: E[]} = {
|
|
14
14
|
comparator: (a: E, b: E) => {
|
|
15
15
|
if (!(typeof a === 'number' && typeof b === 'number')) {
|
|
16
16
|
throw new Error('The a, b params of compare function must be number');
|
|
@@ -10,7 +10,7 @@ import type {Comparator} from '../../types';
|
|
|
10
10
|
|
|
11
11
|
export class MinPriorityQueue<E = any> extends PriorityQueue<E> {
|
|
12
12
|
constructor(
|
|
13
|
-
options: {
|
|
13
|
+
options: {comparator: Comparator<E>; nodes?: E[]} = {
|
|
14
14
|
comparator: (a: E, b: E) => {
|
|
15
15
|
if (!(typeof a === 'number' && typeof b === 'number')) {
|
|
16
16
|
throw new Error('The a, b params of compare function must be number');
|
|
@@ -10,7 +10,7 @@ import {Heap} from '../heap';
|
|
|
10
10
|
import {Comparator} from '../../types';
|
|
11
11
|
|
|
12
12
|
export class PriorityQueue<E = any> extends Heap<E> {
|
|
13
|
-
constructor(options: {
|
|
13
|
+
constructor(options: {comparator: Comparator<E>; nodes?: E[]}) {
|
|
14
14
|
super(options);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -9,8 +9,7 @@ import {DoublyLinkedList} from '../linked-list';
|
|
|
9
9
|
|
|
10
10
|
// O(n) time complexity of obtaining the value
|
|
11
11
|
// O(1) time complexity of adding at the beginning and the end
|
|
12
|
-
export class Deque<E = any> extends DoublyLinkedList<E> {
|
|
13
|
-
}
|
|
12
|
+
export class Deque<E = any> extends DoublyLinkedList<E> {}
|
|
14
13
|
|
|
15
14
|
// O(1) time complexity of obtaining the value
|
|
16
15
|
// O(n) time complexity of adding at the beginning and the end
|
|
@@ -20,9 +19,9 @@ export class ObjectDeque<E = number> {
|
|
|
20
19
|
if (capacity !== undefined) this._capacity = capacity;
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
protected _nodes: {
|
|
22
|
+
protected _nodes: {[key: number]: E} = {};
|
|
24
23
|
|
|
25
|
-
get nodes(): {
|
|
24
|
+
get nodes(): {[p: number]: E} {
|
|
26
25
|
return this._nodes;
|
|
27
26
|
}
|
|
28
27
|
|