Skip to content

Commit 02dd8ca

Browse files
make-github-pseudonymous-againAurélien Ooms
authored andcommitted
🚴 perf(delete_one_child): Hoist red input case.
This avoids creating a mocked leaf in that case.
1 parent 80cfb27 commit 02dd8ca

File tree

3 files changed

+44
-34
lines changed

3 files changed

+44
-34
lines changed

src/deletion/delete_mocked_leaf.js

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/deletion/delete_one_child.js

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Leaf from '../types/Leaf.js';
77
import replace_node from './replace_node.js';
88
import delete_case2 from './delete_case2.js';
99

10-
import delete_mocked_leaf from './delete_mocked_leaf.js';
10+
import prune_subtree from './prune_subtree.js';
1111

1212
/**
1313
* Delete a node <code>n</code> that has at most a single non-leaf child.
@@ -29,32 +29,41 @@ const delete_one_child = (n) => {
2929
// properties
3030
assert(n.right === null);
3131

32+
if (n._color === RED) {
33+
// If n is red then its child can only be black. Replacing n with its
34+
// child suffices.
35+
const child = n.left;
36+
if (child === null) {
37+
prune_subtree(n);
38+
} else {
39+
assert(child._color === BLACK);
40+
replace_node(n, child);
41+
}
42+
43+
return;
44+
}
45+
46+
assert(n._color === BLACK);
47+
3248
// Mock leaf if there is no left child
3349
const child = n.left === null ? new Leaf(null) : n.left;
3450

35-
// TODO skip creating mocked leaf if n._color === RED
36-
3751
// Replace n with its left child
3852
replace_node(n, child);
3953

4054
// If n is black, deleting it reduces the black-height of every path going
4155
// through it by 1.
42-
if (n._color === BLACK) {
43-
// We can easily fix this when its left child is an
44-
// internal red node: change the color of the left child to black and
45-
// replace n with it.
46-
if (child._color === RED) child._color = BLACK;
47-
// Otherwise, there are more things to fix.
48-
else {
49-
delete_case2(child);
50-
}
51-
} else {
52-
// If n is red then its child can only be black. Replacing n with its
53-
// child suffices. This is a NO-OP.
54-
assert(child._color === BLACK);
56+
// We can easily fix this when its left child is an
57+
// internal red node: change the color of the left child to black and
58+
// replace n with it.
59+
if (child._color === RED) child._color = BLACK;
60+
// Otherwise, there are more things to fix.
61+
else {
62+
delete_case2(child);
5563
}
5664

57-
if (child instanceof Leaf) delete_mocked_leaf(child);
65+
// Delete mocked leaf
66+
if (child instanceof Leaf) prune_subtree(child);
5867
};
5968

6069
export default delete_one_child;

src/deletion/prune_subtree.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import assert from 'assert';
2+
import Node from '../types/Node.js';
3+
import Leaf from '../types/Leaf.js';
4+
5+
/**
6+
* Prune subtree rooted at input node.
7+
*
8+
* @param {Node|Leaf} root - The leaf to delete.
9+
*/
10+
const prune_subtree = (root) => {
11+
assert(root instanceof Node || root instanceof Leaf);
12+
assert(root.parent !== null);
13+
14+
if (root === root.parent.left) root.parent.left = null;
15+
else root.parent.right = null;
16+
};
17+
18+
export default prune_subtree;

0 commit comments

Comments
 (0)