When a leaf underflows but a neighbor has a key to spare, the fix is to borrow one and slide the parent's separator to match. Today you redistribute a key from a sibling, pinning both the borrow-from-left and borrow-from-right cases.
Repair an underflowed leaf by borrowing a key from an adjacent sibling that has more than the minimum, updating the parent separator.
The cheaper of the two repairs is borrowing, also called redistribution. When a leaf underflows and an adjacent sibling has more than the minimum, one entry moves across the boundary to rebalance them, and - this is the part that is easy to miss - the parent separator has to move with it. The separator always names the first key of the right-hand leaf, so after keys shift, it must be reset to whatever now sits at the front of the right leaf.
Both directions follow the same principle but touch different ends. Borrowing from the right takes that sibling’s smallest key and appends it to the underflowed leaf; borrowing from the left takes that sibling’s largest key and prepends it. Either way the separator is refreshed to the right leaf’s new first key. Borrowing only works when a neighbor can actually spare a key; when both neighbors are at the minimum, there is nothing to lend, and the leaves have to merge instead - the next lesson.
// right sibling has a spare (> minKeys): move R.Keys[0]/Vals[0] to// the end of L, then set parent separator = R.Keys[0] (new first).// left sibling has a spare: move L's LAST entry to the front of R,// then set parent separator = the moved key (R's new first).const minKeys = maxKeys / 2 // = 1 for order 3