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,36 +1,45 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* data-structure-typed
|
|
4
|
+
*
|
|
5
|
+
* @author Tyler Zeng
|
|
6
|
+
* @copyright Copyright (c) 2022 Tyler Zeng <zrwusa@gmail.com>
|
|
7
|
+
* @license MIT License
|
|
8
|
+
*/
|
|
2
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RedBlackTree = exports.RBTreeNode = void 0;
|
|
10
|
+
exports.RedBlackTree = exports.NIL = exports.RBTreeNode = void 0;
|
|
4
11
|
const types_1 = require("../../types");
|
|
5
12
|
class RBTreeNode {
|
|
6
|
-
key
|
|
13
|
+
key;
|
|
7
14
|
parent;
|
|
8
15
|
left;
|
|
9
16
|
right;
|
|
10
17
|
color = types_1.RBTNColor.BLACK;
|
|
11
|
-
constructor() {
|
|
18
|
+
constructor(key, color = types_1.RBTNColor.BLACK) {
|
|
19
|
+
this.key = key;
|
|
20
|
+
this.color = color;
|
|
12
21
|
this.parent = null;
|
|
13
22
|
this.left = null;
|
|
14
23
|
this.right = null;
|
|
15
24
|
}
|
|
16
25
|
}
|
|
17
26
|
exports.RBTreeNode = RBTreeNode;
|
|
27
|
+
exports.NIL = new RBTreeNode(0);
|
|
28
|
+
/**
|
|
29
|
+
* 1. Each node is either red or black.
|
|
30
|
+
* 2. The root node is always black.
|
|
31
|
+
* 3. Leaf nodes are typically NIL nodes and are considered black.
|
|
32
|
+
* 4. Red nodes must have black children.
|
|
33
|
+
* 5. Black balance: Every path from any node to each of its leaf nodes contains the same number of black nodes.
|
|
34
|
+
*/
|
|
18
35
|
class RedBlackTree {
|
|
19
36
|
constructor() {
|
|
20
|
-
this.
|
|
21
|
-
this.NIL.color = types_1.RBTNColor.BLACK;
|
|
22
|
-
this.NIL.left = null;
|
|
23
|
-
this.NIL.right = null;
|
|
24
|
-
this._root = this.NIL;
|
|
37
|
+
this._root = exports.NIL;
|
|
25
38
|
}
|
|
26
39
|
_root;
|
|
27
40
|
get root() {
|
|
28
41
|
return this._root;
|
|
29
42
|
}
|
|
30
|
-
_NIL;
|
|
31
|
-
get NIL() {
|
|
32
|
-
return this._NIL;
|
|
33
|
-
}
|
|
34
43
|
/**
|
|
35
44
|
* The `insert` function inserts a new node with a given key into a red-black tree and fixes any
|
|
36
45
|
* violations of the red-black tree properties.
|
|
@@ -39,15 +48,12 @@ class RedBlackTree {
|
|
|
39
48
|
* @returns The function does not explicitly return anything.
|
|
40
49
|
*/
|
|
41
50
|
insert(key) {
|
|
42
|
-
const node = new RBTreeNode();
|
|
43
|
-
node.
|
|
44
|
-
node.
|
|
45
|
-
node.left = this.NIL;
|
|
46
|
-
node.right = this.NIL;
|
|
47
|
-
node.color = types_1.RBTNColor.RED;
|
|
51
|
+
const node = new RBTreeNode(key, types_1.RBTNColor.RED);
|
|
52
|
+
node.left = exports.NIL;
|
|
53
|
+
node.right = exports.NIL;
|
|
48
54
|
let y = null;
|
|
49
55
|
let x = this.root;
|
|
50
|
-
while (x !==
|
|
56
|
+
while (x !== exports.NIL) {
|
|
51
57
|
y = x;
|
|
52
58
|
if (node.key < x.key) {
|
|
53
59
|
x = x.left;
|
|
@@ -84,9 +90,9 @@ class RedBlackTree {
|
|
|
84
90
|
*/
|
|
85
91
|
delete(key) {
|
|
86
92
|
const helper = (node) => {
|
|
87
|
-
let z =
|
|
93
|
+
let z = exports.NIL;
|
|
88
94
|
let x, y;
|
|
89
|
-
while (node !==
|
|
95
|
+
while (node !== exports.NIL) {
|
|
90
96
|
if (node.key === key) {
|
|
91
97
|
z = node;
|
|
92
98
|
}
|
|
@@ -97,17 +103,16 @@ class RedBlackTree {
|
|
|
97
103
|
node = node.left;
|
|
98
104
|
}
|
|
99
105
|
}
|
|
100
|
-
if (z ===
|
|
101
|
-
console.log("Couldn't find key in the tree");
|
|
106
|
+
if (z === exports.NIL) {
|
|
102
107
|
return;
|
|
103
108
|
}
|
|
104
109
|
y = z;
|
|
105
110
|
let yOriginalColor = y.color;
|
|
106
|
-
if (z.left ===
|
|
111
|
+
if (z.left === exports.NIL) {
|
|
107
112
|
x = z.right;
|
|
108
113
|
this._rbTransplant(z, z.right);
|
|
109
114
|
}
|
|
110
|
-
else if (z.right ===
|
|
115
|
+
else if (z.right === exports.NIL) {
|
|
111
116
|
x = z.left;
|
|
112
117
|
this._rbTransplant(z, z.left);
|
|
113
118
|
}
|
|
@@ -128,12 +133,15 @@ class RedBlackTree {
|
|
|
128
133
|
y.left.parent = y;
|
|
129
134
|
y.color = z.color;
|
|
130
135
|
}
|
|
131
|
-
if (yOriginalColor ===
|
|
136
|
+
if (yOriginalColor === types_1.RBTNColor.BLACK) {
|
|
132
137
|
this._fixDelete(x);
|
|
133
138
|
}
|
|
134
139
|
};
|
|
135
140
|
helper(this.root);
|
|
136
141
|
}
|
|
142
|
+
isRealNode(node) {
|
|
143
|
+
return node !== exports.NIL && node !== null;
|
|
144
|
+
}
|
|
137
145
|
/**
|
|
138
146
|
* The function `getNode` is a recursive depth-first search algorithm that searches for a node with a
|
|
139
147
|
* given key in a red-black tree.
|
|
@@ -146,13 +154,17 @@ class RedBlackTree {
|
|
|
146
154
|
*/
|
|
147
155
|
getNode(key, beginRoot = this.root) {
|
|
148
156
|
const dfs = (node) => {
|
|
149
|
-
if (
|
|
150
|
-
|
|
157
|
+
if (this.isRealNode(node)) {
|
|
158
|
+
if (key === node.key) {
|
|
159
|
+
return node;
|
|
160
|
+
}
|
|
161
|
+
if (key < node.key)
|
|
162
|
+
return dfs(node.left);
|
|
163
|
+
return dfs(node.right);
|
|
151
164
|
}
|
|
152
|
-
|
|
153
|
-
return
|
|
165
|
+
else {
|
|
166
|
+
return null;
|
|
154
167
|
}
|
|
155
|
-
return dfs(node.right);
|
|
156
168
|
};
|
|
157
169
|
return dfs(beginRoot);
|
|
158
170
|
}
|
|
@@ -162,8 +174,8 @@ class RedBlackTree {
|
|
|
162
174
|
* a Red-Black Tree.
|
|
163
175
|
* @returns The leftmost node in the given RBTreeNode.
|
|
164
176
|
*/
|
|
165
|
-
getLeftMost(node) {
|
|
166
|
-
while (node.left !== null && node.left !==
|
|
177
|
+
getLeftMost(node = this.root) {
|
|
178
|
+
while (node.left !== null && node.left !== exports.NIL) {
|
|
167
179
|
node = node.left;
|
|
168
180
|
}
|
|
169
181
|
return node;
|
|
@@ -174,7 +186,7 @@ class RedBlackTree {
|
|
|
174
186
|
* @returns the rightmost node in a red-black tree.
|
|
175
187
|
*/
|
|
176
188
|
getRightMost(node) {
|
|
177
|
-
while (node.right !== null && node.right !==
|
|
189
|
+
while (node.right !== null && node.right !== exports.NIL) {
|
|
178
190
|
node = node.right;
|
|
179
191
|
}
|
|
180
192
|
return node;
|
|
@@ -185,11 +197,11 @@ class RedBlackTree {
|
|
|
185
197
|
* @returns the successor of the given RBTreeNode.
|
|
186
198
|
*/
|
|
187
199
|
getSuccessor(x) {
|
|
188
|
-
if (x.right !==
|
|
200
|
+
if (x.right !== exports.NIL) {
|
|
189
201
|
return this.getLeftMost(x.right);
|
|
190
202
|
}
|
|
191
203
|
let y = x.parent;
|
|
192
|
-
while (y !==
|
|
204
|
+
while (y !== exports.NIL && y !== null && x === y.right) {
|
|
193
205
|
x = y;
|
|
194
206
|
y = y.parent;
|
|
195
207
|
}
|
|
@@ -202,16 +214,69 @@ class RedBlackTree {
|
|
|
202
214
|
* @returns the predecessor of the given RBTreeNode 'x'.
|
|
203
215
|
*/
|
|
204
216
|
getPredecessor(x) {
|
|
205
|
-
if (x.left !==
|
|
217
|
+
if (x.left !== exports.NIL) {
|
|
206
218
|
return this.getRightMost(x.left);
|
|
207
219
|
}
|
|
208
220
|
let y = x.parent;
|
|
209
|
-
while (y !==
|
|
221
|
+
while (y !== exports.NIL && x === y.left) {
|
|
210
222
|
x = y;
|
|
211
223
|
y = y.parent;
|
|
212
224
|
}
|
|
213
225
|
return y;
|
|
214
226
|
}
|
|
227
|
+
print(beginRoot = this.root) {
|
|
228
|
+
const display = (root) => {
|
|
229
|
+
const [lines, , ,] = _displayAux(root);
|
|
230
|
+
for (const line of lines) {
|
|
231
|
+
console.log(line);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
const _displayAux = (node) => {
|
|
235
|
+
if (node === null) {
|
|
236
|
+
return [[], 0, 0, 0];
|
|
237
|
+
}
|
|
238
|
+
if (node.right === null && node.left === null) {
|
|
239
|
+
const line = `${node.key}`;
|
|
240
|
+
const width = line.length;
|
|
241
|
+
const height = 1;
|
|
242
|
+
const middle = Math.floor(width / 2);
|
|
243
|
+
return [[line], width, height, middle];
|
|
244
|
+
}
|
|
245
|
+
if (node.right === null) {
|
|
246
|
+
const [lines, n, p, x] = _displayAux(node.left);
|
|
247
|
+
const s = `${node.key}`;
|
|
248
|
+
const u = s.length;
|
|
249
|
+
const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s;
|
|
250
|
+
const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u);
|
|
251
|
+
const shifted_lines = lines.map(line => line + ' '.repeat(u));
|
|
252
|
+
return [[first_line, second_line, ...shifted_lines], n + u, p + 2, n + Math.floor(u / 2)];
|
|
253
|
+
}
|
|
254
|
+
if (node.left === null) {
|
|
255
|
+
const [lines, n, p, u] = _displayAux(node.right);
|
|
256
|
+
const s = `${node.key}`;
|
|
257
|
+
const x = s.length;
|
|
258
|
+
const first_line = s + '_'.repeat(x) + ' '.repeat(n - x);
|
|
259
|
+
const second_line = ' '.repeat(u + x) + '\\' + ' '.repeat(n - x - 1);
|
|
260
|
+
const shifted_lines = lines.map(line => ' '.repeat(u) + line);
|
|
261
|
+
return [[first_line, second_line, ...shifted_lines], n + x, p + 2, Math.floor(u / 2)];
|
|
262
|
+
}
|
|
263
|
+
const [left, n, p, x] = _displayAux(node.left);
|
|
264
|
+
const [right, m, q, y] = _displayAux(node.right);
|
|
265
|
+
const s = `${node.key}`;
|
|
266
|
+
const u = s.length;
|
|
267
|
+
const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s + '_'.repeat(y) + ' '.repeat(m - y);
|
|
268
|
+
const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u + y) + '\\' + ' '.repeat(m - y - 1);
|
|
269
|
+
if (p < q) {
|
|
270
|
+
left.push(...new Array(q - p).fill(' '.repeat(n)));
|
|
271
|
+
}
|
|
272
|
+
else if (q < p) {
|
|
273
|
+
right.push(...new Array(p - q).fill(' '.repeat(m)));
|
|
274
|
+
}
|
|
275
|
+
const zipped_lines = left.map((a, i) => a + ' '.repeat(u) + right[i]);
|
|
276
|
+
return [[first_line, second_line, ...zipped_lines], n + m + u, Math.max(p, q) + 2, n + Math.floor(u / 2)];
|
|
277
|
+
};
|
|
278
|
+
display(beginRoot);
|
|
279
|
+
}
|
|
215
280
|
/**
|
|
216
281
|
* The function performs a left rotation on a red-black tree node.
|
|
217
282
|
* @param {RBTreeNode} x - The parameter `x` is a RBTreeNode object.
|
|
@@ -219,7 +284,7 @@ class RedBlackTree {
|
|
|
219
284
|
_leftRotate(x) {
|
|
220
285
|
const y = x.right;
|
|
221
286
|
x.right = y.left;
|
|
222
|
-
if (y.left !==
|
|
287
|
+
if (y.left !== exports.NIL) {
|
|
223
288
|
y.left.parent = x;
|
|
224
289
|
}
|
|
225
290
|
y.parent = x.parent;
|
|
@@ -243,7 +308,7 @@ class RedBlackTree {
|
|
|
243
308
|
_rightRotate(x) {
|
|
244
309
|
const y = x.left;
|
|
245
310
|
x.left = y.right;
|
|
246
|
-
if (y.right !==
|
|
311
|
+
if (y.right !== exports.NIL) {
|
|
247
312
|
y.right.parent = x;
|
|
248
313
|
}
|
|
249
314
|
y.parent = x.parent;
|
|
@@ -266,7 +331,7 @@ class RedBlackTree {
|
|
|
266
331
|
*/
|
|
267
332
|
_fixDelete(x) {
|
|
268
333
|
let s;
|
|
269
|
-
while (x !== this.root && x.color ===
|
|
334
|
+
while (x !== this.root && x.color === types_1.RBTNColor.BLACK) {
|
|
270
335
|
if (x === x.parent.left) {
|
|
271
336
|
s = x.parent.right;
|
|
272
337
|
if (s.color === 1) {
|
|
@@ -275,12 +340,12 @@ class RedBlackTree {
|
|
|
275
340
|
this._leftRotate(x.parent);
|
|
276
341
|
s = x.parent.right;
|
|
277
342
|
}
|
|
278
|
-
if (s.left.color ===
|
|
343
|
+
if (s.left !== null && s.left.color === types_1.RBTNColor.BLACK && s.right.color === types_1.RBTNColor.BLACK) {
|
|
279
344
|
s.color = types_1.RBTNColor.RED;
|
|
280
345
|
x = x.parent;
|
|
281
346
|
}
|
|
282
347
|
else {
|
|
283
|
-
if (s.right.color ===
|
|
348
|
+
if (s.right.color === types_1.RBTNColor.BLACK) {
|
|
284
349
|
s.left.color = types_1.RBTNColor.BLACK;
|
|
285
350
|
s.color = types_1.RBTNColor.RED;
|
|
286
351
|
this._rightRotate(s);
|
|
@@ -301,12 +366,12 @@ class RedBlackTree {
|
|
|
301
366
|
this._rightRotate(x.parent);
|
|
302
367
|
s = x.parent.left;
|
|
303
368
|
}
|
|
304
|
-
if (s.right.color ===
|
|
369
|
+
if (s.right.color === types_1.RBTNColor.BLACK && s.right.color === types_1.RBTNColor.BLACK) {
|
|
305
370
|
s.color = types_1.RBTNColor.RED;
|
|
306
371
|
x = x.parent;
|
|
307
372
|
}
|
|
308
373
|
else {
|
|
309
|
-
if (s.left.color ===
|
|
374
|
+
if (s.left.color === types_1.RBTNColor.BLACK) {
|
|
310
375
|
s.right.color = types_1.RBTNColor.BLACK;
|
|
311
376
|
s.color = types_1.RBTNColor.RED;
|
|
312
377
|
this._leftRotate(s);
|
|
@@ -160,7 +160,7 @@ class TreeMultiset extends avl_tree_1.AVLTree {
|
|
|
160
160
|
else if (parent.right === undefined) {
|
|
161
161
|
parent.right = newNode;
|
|
162
162
|
if (newNode !== null) {
|
|
163
|
-
this._size =
|
|
163
|
+
this._size = this.size + 1;
|
|
164
164
|
this._setCount(this.count + newNode.count);
|
|
165
165
|
}
|
|
166
166
|
return parent.right;
|
|
@@ -263,7 +263,7 @@ class TreeMultiset extends avl_tree_1.AVLTree {
|
|
|
263
263
|
const bstDeletedResult = [];
|
|
264
264
|
if (!this.root)
|
|
265
265
|
return bstDeletedResult;
|
|
266
|
-
const curr = this.
|
|
266
|
+
const curr = this.getNode(identifier, callback);
|
|
267
267
|
if (!curr)
|
|
268
268
|
return bstDeletedResult;
|
|
269
269
|
const parent = curr?.parent ? curr.parent : null;
|