Skip to content

Commit d27eb94

Browse files
✨ feat: Do not mangle references in RedBlackTree#delete succ branch.
1 parent c3da5be commit d27eb94

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

src/deletion/replace_node.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Node from '../types/Node.js';
1010
const replace_node = (A, B) => {
1111
assert(A instanceof Node);
1212
assert(B instanceof Node);
13-
// We never apply delete_one_child or delete_no_child on the root
13+
// We never apply replace_node on the root
1414
assert(A.parent !== null);
1515

1616
if (A === A.parent.left) A.parent.left = B;

src/types/RedBlackTree.js

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import delete_no_child from '../deletion/delete_no_child.js';
1010
import search from '../search/search.js';
1111
import inordertraversal from '../traversal/inordertraversal.js';
1212
import rangetraversal from '../traversal/rangetraversal.js';
13+
import replace_node from '../deletion/replace_node.js';
1314

1415
/**
1516
* A RedBlackTree with key-only nodes.
@@ -110,13 +111,35 @@ export default class RedBlackTree {
110111
delete_one_child(pred);
111112
}
112113
} else if (node.right !== null) {
113-
// Replace node's key with successor's key
114-
// NOTE: Since there is no left child, then there can only be one
115-
// right child by the red-black tree invariant.
114+
/**
115+
* Swap node with its successor.
116+
*
117+
* NOTE: Since pred is a leaf, there can only by one node in the
118+
* right subtree, succ, which is necessarily red, hence
119+
* node is black.
120+
*
121+
* The configuration:
122+
*
123+
* (A) (B) (C)
124+
*
125+
* p p p
126+
* | | |
127+
* node (BLACK) succ (BLACK) succ (BLACK)
128+
* / \ / \ / \
129+
* - succ (RED) -> - node (RED) -> - -
130+
* / \ / \
131+
* - - - -
132+
*
133+
* NOTE: We take a shortcut and go directly from (A) to (C)
134+
*/
116135
const succ = node.right;
117-
node.key = succ.key;
118-
// Delete successor node
119-
delete_no_child(succ);
136+
assert(succ._color === RED);
137+
succ._color = BLACK;
138+
if (node === this.root) {
139+
this.root = succ;
140+
} else {
141+
replace_node(node, succ);
142+
}
120143
} else if (node === this.root) {
121144
assert(node._color === BLACK);
122145
this.root = null;

0 commit comments

Comments
 (0)