public override bool Remove(TKey key) { if (!Splay(key)) { return(false); } // Root is now the node to be removed Debug.Assert(Root != null); BinaryNode <TKey, TValue> leftTree = Root.LeftChild; // 1. If the root's left subtree is empty, the root will start with the right subtree if (leftTree == null) { BinaryNode <TKey, TValue> oldRoot = Root; Root = oldRoot.RightChild; if (Root != null) { Root.Parent = null; } oldRoot.Dispose(); Count--; return(true); } // 2. Find the right-most node in the root's left subtree -- it will become the new root BinaryNode <TKey, TValue> rightMost = null; _traversalActions.SetActions(inAction: n => { rightMost = n; return(false); // Terminate the DFS when we find the first node }); leftTree.SiftRight(_traversalActions); Debug.Assert(rightMost != null); // Count > 0: there should be at least the root // 3. Splay the right-most node // Remove the parent of root's left child to not splay up to root leftTree.Parent = null; rightMost.Splay(out Root, out LastSplayDepth); // 4. Right-most is now root of the left tree (and has no right subtree); merge it with Root leftTree = rightMost; Debug.Assert(leftTree.RightChild == null); // Splay on the right-most node should make it have no right (larger) children leftTree.RightChild = Root.RightChild; if (leftTree.RightChild != null) { leftTree.RightChild.Parent = leftTree; } Root.Clear(); Root = leftTree; Count--; return(true); }
public override void Clear() { if (Count == 0) { return; } _traversalActions.SetActions(postAction: n => { n.Dispose(); return(true); }); // Start Dispose from the last node (postAction) _consolidateRoots.Sift(_traversalActions); foreach (var root in GetRoots()) { root.Sift(_traversalActions); } _roots.Clear(); _minNode = null; _consolidateRoots = null; Count = 0; }
public override string ToString() { StringBuilder prefix = new StringBuilder(); StringBuilder sb = new StringBuilder(); NodeTraversalActions <TKey, TValue, BinaryNode <TKey, TValue>, NodeTraversalAction> .NodeTraversalAction preAction = node => { Debug.Assert(node == this || node.Parent != null); // Compute new prefix for the right child prefix.Append(node.Parent != null && node.IsLeftChild() ? ExtendPrefix : EmptyPrefix); return(true); }; NodeTraversalActions <TKey, TValue, BinaryNode <TKey, TValue>, NodeTraversalAction> .NodeTraversalAction inAction = node => { // Get the old prefix (revert the preAction) prefix.Length -= ExtendPrefix.Length; bool isLeftChild = node.Parent == null || node.IsLeftChild(); // Output a new line sb.Append(prefix); if (node.Parent == null) { sb.Append(RootFork); } else { sb.Append(isLeftChild ? LeftFork : RightFork); } sb.AppendLine(node.Key.ToString()); // Compute new prefix for the left child prefix.Append(isLeftChild ? EmptyPrefix : ExtendPrefix); return(true); }; NodeTraversalActions <TKey, TValue, BinaryNode <TKey, TValue>, NodeTraversalAction> .NodeTraversalAction postAction = node => { // Get the old prefix (revert the inAction) prefix.Length -= ExtendPrefix.Length; return(true); }; var nodeActions = new NodeTraversalActions <TKey, TValue, BinaryNode <TKey, TValue>, NodeTraversalAction>(); // We do not need to pass the owner's comparer -- Sift does not use it (only Find does) nodeActions.SetActions(preAction, inAction, postAction); SiftRight(nodeActions); return(sb.ToString()); }
public string ToString(NodeTraversalActions <TKey, TValue, DisseminateNode <TKey, TValue>, NodeTraversalAction> traversalActions) { var sb = new StringBuilder(); var indent = new StringBuilder(); const string ind = " "; traversalActions.SetActions(preAction: node => { indent.Append(ind); sb.Append(indent); sb.AppendLine(node.ToString()); return(true); }, postAction: node => { indent.Length -= ind.Length; return(true); }); Sift(traversalActions); return(sb.ToString()); }