@@ -10,6 +10,7 @@ import delete_no_child from '../deletion/delete_no_child.js';
1010import search from '../search/search.js' ;
1111import inordertraversal from '../traversal/inordertraversal.js' ;
1212import 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