protected N DoDelete(AvlTreeTraversal <N, P> deletionPointLocator) { N currentNode = deletionPointLocator.CurrentNode; Descent direction = deletionPointLocator.Descend(); if (direction == Descent.NotFound) { return(null); } else if (direction == Descent.Found) { if (currentNode.Left.IsNil) { return(currentNode.Right); } else if (currentNode.Right.IsNil) { return(currentNode.Left); } else // has both children { (P payload, N residue) = DeleteMin(currentNode.Right); return(Rebalance(payload, currentNode.Left, residue)); } } else { N left; N right; if (direction == Descent.Left) { left = DoDelete(deletionPointLocator); if (left == null) { return(null); // propagate the 'deletion point not found' result up the stack } right = currentNode.Right; } else { right = DoDelete(deletionPointLocator); if (right == null) { return(null); } left = currentNode.Left; } return(Rebalance(currentNode.Payload, left, right)); } }
protected N DoInsertOrUpdate( P payloadToInsert, Func <P, P> payloadUpdate, AvlTreeTraversal <N, P> nodeLocator) { N currentNode = nodeLocator.CurrentNode; // memorize the current node before descending Descent direction = nodeLocator.Descend(); // descend: insertionLeafLocator.CurrentNode changes if (direction == Descent.NotFound) { return(null); } P value; N left; N right; if (direction == Descent.Found) { if (currentNode.IsNil) // insertion case { value = payloadToInsert; left = NilNode; right = NilNode; } else // payload replacement case { value = payloadUpdate(currentNode.Payload); left = currentNode.Left; right = currentNode.Right; } } else { value = currentNode.Payload; // preserve payload N rebuiltSubtree = DoInsertOrUpdate(payloadToInsert, payloadUpdate, nodeLocator); if (rebuiltSubtree == null) { return(null); // propagate the 'insertion/update point not found' result up the stack } if (direction == Descent.Left) { left = rebuiltSubtree; right = currentNode.Right; } else // direction == Descent.Right { left = currentNode.Left; right = rebuiltSubtree; } } return(Rebalance(value, left, right)); }