min-heap-typed 1.42.3 → 1.42.5

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 (34) hide show
  1. package/.prettierignore +1 -1
  2. package/README.md +1 -1
  3. package/dist/data-structures/binary-tree/avl-tree.d.ts +2 -2
  4. package/dist/data-structures/binary-tree/avl-tree.js +5 -3
  5. package/dist/data-structures/binary-tree/binary-tree.d.ts +56 -52
  6. package/dist/data-structures/binary-tree/binary-tree.js +115 -53
  7. package/dist/data-structures/binary-tree/bst.d.ts +42 -15
  8. package/dist/data-structures/binary-tree/bst.js +77 -21
  9. package/dist/data-structures/binary-tree/index.d.ts +1 -1
  10. package/dist/data-structures/binary-tree/index.js +1 -1
  11. package/dist/data-structures/binary-tree/rb-tree.d.ts +28 -51
  12. package/dist/data-structures/binary-tree/rb-tree.js +148 -180
  13. package/dist/data-structures/binary-tree/{tree-multiset.d.ts → tree-multimap.d.ts} +20 -20
  14. package/dist/data-structures/binary-tree/{tree-multiset.js → tree-multimap.js} +34 -31
  15. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +1 -1
  16. package/dist/types/data-structures/binary-tree/index.d.ts +1 -1
  17. package/dist/types/data-structures/binary-tree/index.js +1 -1
  18. package/dist/types/data-structures/binary-tree/rb-tree.d.ts +4 -0
  19. package/dist/types/data-structures/binary-tree/rb-tree.js +0 -5
  20. package/dist/types/data-structures/binary-tree/tree-multimap.d.ts +4 -0
  21. package/package.json +2 -2
  22. package/src/data-structures/binary-tree/avl-tree.ts +5 -4
  23. package/src/data-structures/binary-tree/binary-tree.ts +201 -131
  24. package/src/data-structures/binary-tree/bst.ts +100 -34
  25. package/src/data-structures/binary-tree/index.ts +1 -1
  26. package/src/data-structures/binary-tree/rb-tree.ts +227 -236
  27. package/src/data-structures/binary-tree/{tree-multiset.ts → tree-multimap.ts} +38 -37
  28. package/src/types/data-structures/binary-tree/binary-tree.ts +1 -1
  29. package/src/types/data-structures/binary-tree/index.ts +1 -1
  30. package/src/types/data-structures/binary-tree/rb-tree.ts +5 -5
  31. package/src/types/data-structures/binary-tree/tree-multimap.ts +6 -0
  32. package/dist/types/data-structures/binary-tree/tree-multiset.d.ts +0 -4
  33. package/src/types/data-structures/binary-tree/tree-multiset.ts +0 -6
  34. /package/dist/types/data-structures/binary-tree/{tree-multiset.js → tree-multimap.js} +0 -0
@@ -6,26 +6,27 @@
6
6
  * @license MIT License
7
7
  */
8
8
 
9
- import {RBTNColor} from '../../types';
10
-
11
- export class RBTreeNode {
12
- key: number;
13
- parent: RBTreeNode;
14
- left: RBTreeNode;
15
- right: RBTreeNode;
16
- color: number = RBTNColor.BLACK;
17
-
18
- constructor(key: number, color: RBTNColor = RBTNColor.BLACK) {
19
- this.key = key;
9
+ import {
10
+ BinaryTreeDeletedResult,
11
+ BTNCallback,
12
+ BTNKey,
13
+ IterationType,
14
+ RBTNColor,
15
+ RBTreeNodeNested,
16
+ RBTreeOptions
17
+ } from '../../types';
18
+ import {BST, BSTNode} from "./bst";
19
+ import {IBinaryTree} from "../../interfaces";
20
+ import {BinaryTreeNode} from "./binary-tree";
21
+
22
+ export class RBTreeNode<V = any, N extends RBTreeNode<V, N> = RBTreeNodeNested<V>> extends BSTNode<V, N> {
23
+ color: RBTNColor;
24
+ constructor(key: BTNKey, value?: V, color: RBTNColor = RBTNColor.BLACK) {
25
+ super(key, value);
20
26
  this.color = color;
21
- this.parent = null as unknown as RBTreeNode;
22
- this.left = null as unknown as RBTreeNode;
23
- this.right = null as unknown as RBTreeNode;
24
27
  }
25
28
  }
26
29
 
27
- export const NIL = new RBTreeNode(0);
28
-
29
30
  /**
30
31
  * 1. Each node is either red or black.
31
32
  * 2. The root node is always black.
@@ -33,14 +34,19 @@ export const NIL = new RBTreeNode(0);
33
34
  * 4. Red nodes must have black children.
34
35
  * 5. Black balance: Every path from any node to each of its leaf nodes contains the same number of black nodes.
35
36
  */
36
- export class RedBlackTree {
37
- constructor() {
38
- this._root = NIL;
37
+ export class RedBlackTree<V = any, N extends RBTreeNode<V, N> = RBTreeNode<V, RBTreeNodeNested<V>>>
38
+ extends BST<V, N>
39
+ implements IBinaryTree<V, N>
40
+ {
41
+
42
+ constructor(options?: RBTreeOptions) {
43
+ super(options);
44
+ this._root = this.NIL;
39
45
  }
40
46
 
41
- protected _root: RBTreeNode;
47
+ protected _root: N;
42
48
 
43
- get root(): RBTreeNode {
49
+ get root(): N {
44
50
  return this._root;
45
51
  }
46
52
 
@@ -50,46 +56,53 @@ export class RedBlackTree {
50
56
  return this._size;
51
57
  }
52
58
 
53
- /**
54
- * The `insert` function inserts a new node with a given key into a red-black tree and fixes any
55
- * violations of the red-black tree properties.
56
- * @param {number} key - The key parameter is a number that represents the value to be inserted into
57
- * the RBTree.
58
- * @returns The function does not explicitly return anything.
59
- */
60
- add(key: number): void {
61
- const node: RBTreeNode = new RBTreeNode(key, RBTNColor.RED);
62
- node.left = NIL;
63
- node.right = NIL;
59
+ NIL: N = new RBTreeNode<V>(NaN) as unknown as N;
64
60
 
65
- let y: RBTreeNode = null as unknown as RBTreeNode;
66
- let x: RBTreeNode = this.root;
61
+ override add(keyOrNode: BTNKey | N | null | undefined, value?: V): N | undefined {
62
+ let node: N;
63
+ if (typeof keyOrNode === 'number') {
64
+ node = this.createNode(keyOrNode, value, RBTNColor.RED);
65
+ } else if(keyOrNode instanceof RBTreeNode) {
66
+ node = keyOrNode;
67
+ } else if (keyOrNode === null) {
68
+ return;
69
+ } else if (keyOrNode === undefined) {
70
+ return;
71
+ } else {
72
+ return;
73
+ }
74
+
75
+ node.left = this.NIL;
76
+ node.right = this.NIL;
77
+
78
+ let y: N | undefined = undefined;
79
+ let x: N | undefined = this.root;
67
80
 
68
- while (x !== NIL) {
81
+ while (x !== this.NIL) {
69
82
  y = x;
70
- if (node.key < x.key) {
83
+ if (x && node.key < x.key) {
71
84
  x = x.left;
72
85
  } else {
73
- x = x.right;
86
+ x = x?.right;
74
87
  }
75
88
  }
76
89
 
77
90
  node.parent = y;
78
- if (y === null) {
79
- this._root = node;
91
+ if (y === undefined) {
92
+ this._setRoot(node);
80
93
  } else if (node.key < y.key) {
81
94
  y.left = node;
82
95
  } else {
83
96
  y.right = node;
84
97
  }
85
98
 
86
- if (node.parent === null) {
99
+ if (node.parent === undefined) {
87
100
  node.color = RBTNColor.BLACK;
88
101
  this._size++;
89
102
  return;
90
103
  }
91
104
 
92
- if (node.parent.parent === null) {
105
+ if (node.parent.parent === undefined) {
93
106
  this._size++;
94
107
  return;
95
108
  }
@@ -98,95 +111,121 @@ export class RedBlackTree {
98
111
  this._size++;
99
112
  }
100
113
 
101
- /**
102
- * The `delete` function in TypeScript is used to remove a node with a specific key from a red-black
103
- * tree.
104
- * @param {number} key - The `node` parameter is of type `RBTreeNode` and represents the current
105
- * node being processed in the delete operation.
106
- * @returns The `delete` function does not return anything. It has a return type of `void`.
107
- */
108
- delete(key: number): void {
109
- const helper = (node: RBTreeNode): void => {
110
- let z: RBTreeNode = NIL;
111
- let x: RBTreeNode, y: RBTreeNode;
112
- while (node !== NIL) {
113
- if (node.key === key) {
114
+ override createNode(key: BTNKey, value?: V, color: RBTNColor = RBTNColor.BLACK): N {
115
+ return new RBTreeNode<V, N>(key, value, color) as N;
116
+ }
117
+
118
+
119
+ delete<C extends BTNCallback<N>>(
120
+ identifier: ReturnType<C> | null | undefined,
121
+ callback: C = this.defaultOneParamCallback as C
122
+ ): BinaryTreeDeletedResult<N>[] {
123
+ const ans: BinaryTreeDeletedResult<N>[] = [];
124
+ if (identifier === null) return ans;
125
+ const helper = (node: N | undefined): void => {
126
+ let z: N = this.NIL;
127
+ let x: N | undefined, y: N;
128
+ while (node !== this.NIL) {
129
+ if (node && callback(node) === identifier) {
114
130
  z = node;
115
131
  }
116
132
 
117
- if (node.key <= key) {
133
+ if (node && identifier && callback(node) <= identifier) {
118
134
  node = node.right;
119
135
  } else {
120
- node = node.left;
136
+ node = node?.left;
121
137
  }
122
138
  }
123
139
 
124
- if (z === NIL) {
140
+ if (z === this.NIL) {
125
141
  this._size--;
126
142
  return;
127
143
  }
128
144
 
129
145
  y = z;
130
146
  let yOriginalColor: number = y.color;
131
- if (z.left === NIL) {
147
+ if (z.left === this.NIL) {
132
148
  x = z.right;
133
- this._rbTransplant(z, z.right);
134
- } else if (z.right === NIL) {
149
+ this._rbTransplant(z, z.right!);
150
+ } else if (z.right === this.NIL) {
135
151
  x = z.left;
136
- this._rbTransplant(z, z.left);
152
+ this._rbTransplant(z, z.left!);
137
153
  } else {
138
154
  y = this.getLeftMost(z.right);
139
155
  yOriginalColor = y.color;
140
156
  x = y.right;
141
157
  if (y.parent === z) {
142
- x.parent = y;
158
+ x!.parent = y;
143
159
  } else {
144
- this._rbTransplant(y, y.right);
160
+ this._rbTransplant(y, y.right!);
145
161
  y.right = z.right;
146
- y.right.parent = y;
162
+ y.right!.parent = y;
147
163
  }
148
164
 
149
165
  this._rbTransplant(z, y);
150
166
  y.left = z.left;
151
- y.left.parent = y;
167
+ y.left!.parent = y;
152
168
  y.color = z.color;
153
169
  }
154
170
  if (yOriginalColor === RBTNColor.BLACK) {
155
- this._fixDelete(x);
171
+ this._fixDelete(x!);
156
172
  }
157
173
  this._size--;
158
174
  };
159
175
  helper(this.root);
176
+ // TODO
177
+ return ans;
160
178
  }
161
179
 
162
- isRealNode(node: RBTreeNode | null | undefined): node is RBTreeNode {
163
- return node !== NIL && node !== null;
180
+ isNode(node: N | undefined): node is N {
181
+ return node !== this.NIL && node !== undefined;
164
182
  }
165
183
 
184
+ getNode<C extends BTNCallback<N, BTNKey>>(
185
+ identifier: BTNKey,
186
+ callback?: C,
187
+ beginRoot?: N | undefined,
188
+ iterationType?: IterationType
189
+ ): N | undefined;
190
+
191
+ getNode<C extends BTNCallback<N, N>>(
192
+ identifier: N | undefined,
193
+ callback?: C,
194
+ beginRoot?: N | undefined,
195
+ iterationType?: IterationType
196
+ ): N | undefined;
197
+
198
+ getNode<C extends BTNCallback<N>>(
199
+ identifier: ReturnType<C>,
200
+ callback: C,
201
+ beginRoot?: N | undefined,
202
+ iterationType?: IterationType
203
+ ): N | undefined;
204
+
166
205
  /**
167
- * The function `getNode` is a recursive depth-first search algorithm that searches for a node with a
168
- * given key in a red-black tree.
169
- * @param {number} key - The key parameter is a number that represents the value we are searching for
170
- * in the RBTree.
171
- * @param beginRoot - The `beginRoot` parameter is an optional parameter that represents the starting
172
- * point for the search in the binary search tree. If no value is provided for `beginRoot`, it
173
- * defaults to the root of the binary search tree (`this.root`).
174
- * @returns a RBTreeNode.
206
+ * The function `get` returns the first node in a binary tree that matches the given property or key.
207
+ * @param {BTNKey | N} identifier - The `identifier` parameter is the key or value of
208
+ * the node that you want to find in the binary tree. It can be either a `BTNKey` or `N`
209
+ * type.
210
+ * @param callback - The `callback` parameter is a function that is used to determine whether a node
211
+ * matches the desired criteria. It takes a node as input and returns a boolean value indicating
212
+ * whether the node matches the criteria or not. The default callback function
213
+ * (`this.defaultOneParamCallback`) is used if no callback function is
214
+ * @param beginRoot - The `beginRoot` parameter is the starting point for the search. It specifies
215
+ * the root node from which the search should begin.
216
+ * @param iterationType - The `iterationType` parameter specifies the type of iteration to be
217
+ * performed when searching for a node in the binary tree. It can have one of the following values:
218
+ * @returns either the found node (of type N) or null if no node is found.
175
219
  */
176
- getNode(key: number, beginRoot = this.root): RBTreeNode {
177
- const dfs = (node: RBTreeNode): RBTreeNode => {
178
- if (this.isRealNode(node)) {
179
- if (key === node.key) {
180
- return node;
181
- }
182
-
183
- if (key < node.key) return dfs(node.left);
184
- return dfs(node.right);
185
- } else {
186
- return null as unknown as RBTreeNode;
187
- }
188
- };
189
- return dfs(beginRoot);
220
+ getNode<C extends BTNCallback<N>>(
221
+ identifier: ReturnType<C> | undefined,
222
+ callback: C = this.defaultOneParamCallback as C,
223
+ beginRoot = this.root,
224
+ iterationType = this.iterationType
225
+ ): N | null | undefined {
226
+ if ((identifier as any) instanceof BinaryTreeNode) callback = (node => node) as C;
227
+
228
+ return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? undefined;
190
229
  }
191
230
 
192
231
  /**
@@ -195,8 +234,8 @@ export class RedBlackTree {
195
234
  * a Red-Black Tree.
196
235
  * @returns The leftmost node in the given RBTreeNode.
197
236
  */
198
- getLeftMost(node: RBTreeNode = this.root): RBTreeNode {
199
- while (node.left !== null && node.left !== NIL) {
237
+ getLeftMost(node: N = this.root): N {
238
+ while (node.left !== undefined && node.left !== this.NIL) {
200
239
  node = node.left;
201
240
  }
202
241
  return node;
@@ -207,8 +246,8 @@ export class RedBlackTree {
207
246
  * @param {RBTreeNode} node - The parameter "node" is of type RBTreeNode.
208
247
  * @returns the rightmost node in a red-black tree.
209
248
  */
210
- getRightMost(node: RBTreeNode): RBTreeNode {
211
- while (node.right !== null && node.right !== NIL) {
249
+ getRightMost(node: N): N {
250
+ while (node.right !== undefined && node.right !== this.NIL) {
212
251
  node = node.right;
213
252
  }
214
253
  return node;
@@ -219,13 +258,13 @@ export class RedBlackTree {
219
258
  * @param {RBTreeNode} x - RBTreeNode - The node for which we want to find the successor.
220
259
  * @returns the successor of the given RBTreeNode.
221
260
  */
222
- getSuccessor(x: RBTreeNode): RBTreeNode {
223
- if (x.right !== NIL) {
261
+ getSuccessor(x: N): N | undefined {
262
+ if (x.right !== this.NIL) {
224
263
  return this.getLeftMost(x.right);
225
264
  }
226
265
 
227
- let y: RBTreeNode = x.parent;
228
- while (y !== NIL && y !== null && x === y.right) {
266
+ let y: N | undefined = x.parent;
267
+ while (y !== this.NIL && y !== undefined && x === y.right) {
229
268
  x = y;
230
269
  y = y.parent;
231
270
  }
@@ -238,104 +277,54 @@ export class RedBlackTree {
238
277
  * Red-Black Tree.
239
278
  * @returns the predecessor of the given RBTreeNode 'x'.
240
279
  */
241
- getPredecessor(x: RBTreeNode): RBTreeNode {
242
- if (x.left !== NIL) {
243
- return this.getRightMost(x.left);
280
+ getPredecessor(x: N): N {
281
+ if (x.left !== this.NIL) {
282
+ return this.getRightMost(x.left!);
244
283
  }
245
284
 
246
- let y: RBTreeNode = x.parent;
247
- while (y !== NIL && x === y.left) {
248
- x = y;
249
- y = y.parent;
285
+ let y: N | undefined = x.parent;
286
+ while (y !== this.NIL && x === y!.left) {
287
+ x = y!;
288
+ y = y!.parent;
250
289
  }
251
290
 
252
- return y;
291
+ return y!;
253
292
  }
254
293
 
255
- clear() {
256
- this._root = NIL;
294
+ override clear() {
295
+ this._root = this.NIL;
257
296
  this._size = 0;
258
297
  }
259
298
 
260
- print(beginRoot: RBTreeNode = this.root) {
261
- const display = (root: RBTreeNode | null): void => {
262
- const [lines, , ,] = _displayAux(root);
263
- for (const line of lines) {
264
- console.log(line);
265
- }
266
- };
267
-
268
- const _displayAux = (node: RBTreeNode | null): [string[], number, number, number] => {
269
- if (node === null) {
270
- return [[], 0, 0, 0];
271
- }
272
-
273
- if (node.right === null && node.left === null) {
274
- const line = `${node.key}`;
275
- const width = line.length;
276
- const height = 1;
277
- const middle = Math.floor(width / 2);
278
- return [[line], width, height, middle];
279
- }
280
-
281
- if (node.right === null) {
282
- const [lines, n, p, x] = _displayAux(node.left);
283
- const s = `${node.key}`;
284
- const u = s.length;
285
- const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s;
286
- const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u);
287
- const shifted_lines = lines.map(line => line + ' '.repeat(u));
288
- return [[first_line, second_line, ...shifted_lines], n + u, p + 2, n + Math.floor(u / 2)];
289
- }
290
-
291
- if (node.left === null) {
292
- const [lines, n, p, u] = _displayAux(node.right);
293
- const s = `${node.key}`;
294
- const x = s.length;
295
- const first_line = s + '_'.repeat(x) + ' '.repeat(n - x);
296
- const second_line = ' '.repeat(u + x) + '\\' + ' '.repeat(n - x - 1);
297
- const shifted_lines = lines.map(line => ' '.repeat(u) + line);
298
- return [[first_line, second_line, ...shifted_lines], n + x, p + 2, Math.floor(u / 2)];
299
- }
300
-
301
- const [left, n, p, x] = _displayAux(node.left);
302
- const [right, m, q, y] = _displayAux(node.right);
303
- const s = `${node.key}`;
304
- const u = s.length;
305
- const first_line = ' '.repeat(x + 1) + '_'.repeat(n - x - 1) + s + '_'.repeat(y) + ' '.repeat(m - y);
306
- const second_line = ' '.repeat(x) + '/' + ' '.repeat(n - x - 1 + u + y) + '\\' + ' '.repeat(m - y - 1);
307
- if (p < q) {
308
- left.push(...new Array(q - p).fill(' '.repeat(n)));
309
- } else if (q < p) {
310
- right.push(...new Array(p - q).fill(' '.repeat(m)));
311
- }
312
- const zipped_lines = left.map((a, i) => a + ' '.repeat(u) + right[i]);
313
- return [[first_line, second_line, ...zipped_lines], n + m + u, Math.max(p, q) + 2, n + Math.floor(u / 2)];
314
- };
315
-
316
- display(beginRoot);
299
+ protected override _setRoot(v: N) {
300
+ if (v) {
301
+ v.parent = undefined;
302
+ }
303
+ this._root = v;
317
304
  }
318
305
 
319
306
  /**
320
307
  * The function performs a left rotation on a red-black tree node.
321
308
  * @param {RBTreeNode} x - The parameter `x` is a RBTreeNode object.
322
309
  */
323
- protected _leftRotate(x: RBTreeNode): void {
324
- const y: RBTreeNode = x.right;
325
- x.right = y.left;
326
- if (y.left !== NIL) {
327
- y.left.parent = x;
328
- }
329
- y.parent = x.parent;
330
- if (x.parent === null) {
331
- this._root = y;
332
- } else if (x === x.parent.left) {
333
- x.parent.left = y;
334
- } else {
335
- x.parent.right = y;
310
+ protected _leftRotate(x: N): void {
311
+ if (x.right) {
312
+ const y: N = x.right;
313
+ x.right = y.left;
314
+ if (y.left !== this.NIL) {
315
+ if (y.left) y.left.parent = x;
316
+ }
317
+ y.parent = x.parent;
318
+ if (x.parent === undefined) {
319
+ this._setRoot(y);
320
+ } else if (x === x.parent.left) {
321
+ x.parent.left = y;
322
+ } else {
323
+ x.parent.right = y;
324
+ }
325
+ y.left = x;
326
+ x.parent = y;
336
327
  }
337
- y.left = x;
338
- x.parent = y;
339
328
  }
340
329
 
341
330
  /**
@@ -343,22 +332,24 @@ export class RedBlackTree {
343
332
  * @param {RBTreeNode} x - x is a RBTreeNode, which represents the node that needs to be right
344
333
  * rotated.
345
334
  */
346
- protected _rightRotate(x: RBTreeNode): void {
347
- const y: RBTreeNode = x.left;
348
- x.left = y.right;
349
- if (y.right !== NIL) {
350
- y.right.parent = x;
351
- }
352
- y.parent = x.parent;
353
- if (x.parent === null) {
354
- this._root = y;
355
- } else if (x === x.parent.right) {
356
- x.parent.right = y;
357
- } else {
358
- x.parent.left = y;
335
+ protected _rightRotate(x: N): void {
336
+ if (x.left) {
337
+ const y: N = x.left;
338
+ x.left = y.right;
339
+ if (y.right !== this.NIL) {
340
+ if (y.right) y.right.parent = x;
341
+ }
342
+ y.parent = x.parent;
343
+ if (x.parent === undefined) {
344
+ this._setRoot(y);
345
+ } else if (x === x.parent.right) {
346
+ x.parent.right = y;
347
+ } else {
348
+ x.parent.left = y;
349
+ }
350
+ y.right = x;
351
+ x.parent = y;
359
352
  }
360
- y.right = x;
361
- x.parent = y;
362
353
  }
363
354
 
364
355
  /**
@@ -366,59 +357,59 @@ export class RedBlackTree {
366
357
  * @param {RBTreeNode} x - The parameter `x` is of type `RBTreeNode`, which represents a node in a
367
358
  * red-black tree.
368
359
  */
369
- protected _fixDelete(x: RBTreeNode): void {
370
- let s: RBTreeNode;
360
+ protected _fixDelete(x: N): void {
361
+ let s: N | undefined;
371
362
  while (x !== this.root && x.color === RBTNColor.BLACK) {
372
- if (x === x.parent.left) {
373
- s = x.parent.right;
363
+ if (x.parent && x === x.parent.left) {
364
+ s = x.parent.right!;
374
365
  if (s.color === 1) {
375
366
  s.color = RBTNColor.BLACK;
376
367
  x.parent.color = RBTNColor.RED;
377
368
  this._leftRotate(x.parent);
378
- s = x.parent.right;
369
+ s = x.parent.right!;
379
370
  }
380
371
 
381
- if (s.left !== null && s.left.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {
372
+ if (s.left !== undefined && s.left.color === RBTNColor.BLACK && s.right && s.right.color === RBTNColor.BLACK) {
382
373
  s.color = RBTNColor.RED;
383
374
  x = x.parent;
384
375
  } else {
385
- if (s.right.color === RBTNColor.BLACK) {
386
- s.left.color = RBTNColor.BLACK;
376
+ if (s.right && s.right.color === RBTNColor.BLACK) {
377
+ if (s.left) s.left.color = RBTNColor.BLACK;
387
378
  s.color = RBTNColor.RED;
388
379
  this._rightRotate(s);
389
380
  s = x.parent.right;
390
381
  }
391
382
 
392
- s.color = x.parent.color;
383
+ if (s) s.color = x.parent.color;
393
384
  x.parent.color = RBTNColor.BLACK;
394
- s.right.color = RBTNColor.BLACK;
385
+ if (s && s.right) s.right.color = RBTNColor.BLACK;
395
386
  this._leftRotate(x.parent);
396
387
  x = this.root;
397
388
  }
398
389
  } else {
399
- s = x.parent.left;
390
+ s = x.parent!.left!;
400
391
  if (s.color === 1) {
401
392
  s.color = RBTNColor.BLACK;
402
- x.parent.color = RBTNColor.RED;
403
- this._rightRotate(x.parent);
404
- s = x.parent.left;
393
+ x.parent!.color = RBTNColor.RED;
394
+ this._rightRotate(x.parent!);
395
+ s = x.parent!.left;
405
396
  }
406
397
 
407
- if (s.right.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {
398
+ if (s && s.right && s.right.color === RBTNColor.BLACK && s.right.color === RBTNColor.BLACK) {
408
399
  s.color = RBTNColor.RED;
409
- x = x.parent;
400
+ x = x.parent!;
410
401
  } else {
411
- if (s.left.color === RBTNColor.BLACK) {
412
- s.right.color = RBTNColor.BLACK;
402
+ if (s && s.left && s.left.color === RBTNColor.BLACK) {
403
+ if (s.right) s.right.color = RBTNColor.BLACK;
413
404
  s.color = RBTNColor.RED;
414
405
  this._leftRotate(s);
415
- s = x.parent.left;
406
+ s = x.parent!.left;
416
407
  }
417
408
 
418
- s.color = x.parent.color;
419
- x.parent.color = RBTNColor.BLACK;
420
- s.left.color = RBTNColor.BLACK;
421
- this._rightRotate(x.parent);
409
+ if (s) s.color = x.parent!.color;
410
+ x.parent!.color = RBTNColor.BLACK;
411
+ if (s && s.left) s.left.color = RBTNColor.BLACK;
412
+ this._rightRotate(x.parent!);
422
413
  x = this.root;
423
414
  }
424
415
  }
@@ -431,9 +422,9 @@ export class RedBlackTree {
431
422
  * @param {RBTreeNode} u - The parameter "u" represents a RBTreeNode object.
432
423
  * @param {RBTreeNode} v - The parameter "v" is a RBTreeNode object.
433
424
  */
434
- protected _rbTransplant(u: RBTreeNode, v: RBTreeNode): void {
435
- if (u.parent === null) {
436
- this._root = v;
425
+ protected _rbTransplant(u: N, v: N): void {
426
+ if (u.parent === undefined) {
427
+ this._setRoot(v);
437
428
  } else if (u === u.parent.left) {
438
429
  u.parent.left = v;
439
430
  } else {
@@ -447,12 +438,12 @@ export class RedBlackTree {
447
438
  * @param {RBTreeNode} k - The parameter `k` is a RBTreeNode object, which represents a node in a
448
439
  * red-black tree.
449
440
  */
450
- protected _fixInsert(k: RBTreeNode): void {
451
- let u: RBTreeNode;
452
- while (k.parent.color === 1) {
453
- if (k.parent === k.parent.parent.right) {
441
+ protected _fixInsert(k: N): void {
442
+ let u: N | undefined;
443
+ while (k.parent && k.parent.color === 1) {
444
+ if (k.parent.parent && k.parent === k.parent.parent.right) {
454
445
  u = k.parent.parent.left;
455
- if (u.color === 1) {
446
+ if (u && u.color === 1) {
456
447
  u.color = RBTNColor.BLACK;
457
448
  k.parent.color = RBTNColor.BLACK;
458
449
  k.parent.parent.color = RBTNColor.RED;
@@ -463,27 +454,27 @@ export class RedBlackTree {
463
454
  this._rightRotate(k);
464
455
  }
465
456
 
466
- k.parent.color = RBTNColor.BLACK;
467
- k.parent.parent.color = RBTNColor.RED;
468
- this._leftRotate(k.parent.parent);
457
+ k.parent!.color = RBTNColor.BLACK;
458
+ k.parent!.parent!.color = RBTNColor.RED;
459
+ this._leftRotate(k.parent!.parent!);
469
460
  }
470
461
  } else {
471
- u = k.parent.parent.right;
462
+ u = k.parent.parent!.right;
472
463
 
473
- if (u.color === 1) {
464
+ if (u && u.color === 1) {
474
465
  u.color = RBTNColor.BLACK;
475
466
  k.parent.color = RBTNColor.BLACK;
476
- k.parent.parent.color = RBTNColor.RED;
477
- k = k.parent.parent;
467
+ k.parent.parent!.color = RBTNColor.RED;
468
+ k = k.parent.parent!;
478
469
  } else {
479
470
  if (k === k.parent.right) {
480
471
  k = k.parent;
481
472
  this._leftRotate(k);
482
473
  }
483
474
 
484
- k.parent.color = RBTNColor.BLACK;
485
- k.parent.parent.color = RBTNColor.RED;
486
- this._rightRotate(k.parent.parent);
475
+ k.parent!.color = RBTNColor.BLACK;
476
+ k.parent!.parent!.color = RBTNColor.RED;
477
+ this._rightRotate(k.parent!.parent!);
487
478
  }
488
479
  }
489
480
  if (k === this.root) {