/// <summary> /// If the type parameter is <see cref="NoFlip"/>, nodes are iterated from the smallest /// to the largest key (left to right); if the parameter is <see cref="DoFlip"/>, /// nodes are iterated from the largest to the smallest key (right to left). /// </summary> internal bool SiftRecursive <T>(NodeTraversalActions <TKey, TValue, BinaryNode <TKey, TValue>, NodeTraversalAction> nodeActions) where T : FlipBase <T> { if (!nodeActions.InvokePreAction(this)) { return(false); } if (GetLeftChild <T>() != null && !GetLeftChild <T>().SiftRecursive <T>(nodeActions)) { return(false); } if (!nodeActions.InvokeInAction(this)) { return(false); } if (GetRightChild <T>() != null && !GetRightChild <T>().SiftRecursive <T>(nodeActions)) { return(false); } if (!nodeActions.InvokePostAction(this)) { return(false); } return(true); }
private bool HandleSift <T>( Stack <NodeTraversalToken <BinaryNode <TKey, TValue>, NodeTraversalAction> > stack, NodeTraversalActions <TKey, TValue, BinaryNode <TKey, TValue>, NodeTraversalAction> nodeActions) where T : FlipBase <T> { // First and only visit to this node if (!nodeActions.InvokePreAction(this)) { return(false); } // Push actions in reverse order var right = GetRightChild <T>(); var left = GetLeftChild <T>(); if (right != null) { if (nodeActions.HasPostAction) { stack.Push(GetNodeTraversalToken(this, NodeTraversalAction.PostAction)); } stack.Push(GetNodeTraversalToken(right, NodeTraversalAction.Sift)); } else if (left != null && nodeActions.HasPostAction) { // We need to store the action (it has to be executed after sifting through Left) stack.Push(GetNodeTraversalToken(this, NodeTraversalAction.PostAction)); } if (left != null) { if (nodeActions.HasInAction) { stack.Push(GetNodeTraversalToken(this, NodeTraversalAction.InAction)); } stack.Push(GetNodeTraversalToken(left, NodeTraversalAction.Sift)); } else { // Handle missing children -- we can only invoke actions right away if children are null from left to right if (!nodeActions.InvokeInAction(this)) { return(false); } if (right == null) { if (!nodeActions.InvokePostAction(this)) { return(false); } } } return(true); }
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()); }
/// <summary> /// If the type parameter is <see cref="NoFlip"/>, nodes are iterated from the smallest /// to the largest key (left to right); if the parameter is <see cref="DoFlip"/>, /// nodes are iterated from the largest to the smallest key (right to left). /// </summary> private bool Sift <T>(NodeTraversalActions <TKey, TValue, BinaryNode <TKey, TValue>, NodeTraversalAction> nodeActions) where T : FlipBase <T> { // We have to use an iterative way because the default stack size of .net apps is 1MB // and it's impractical to change it..... var stack = nodeActions.TraversalStack; Debug.Assert(stack.Count == 0); stack.Push(GetNodeTraversalToken(this, NodeTraversalAction.Sift)); try { while (stack.Count > 0) { var token = stack.Pop(); switch (token.Action) { case NodeTraversalAction.Sift: if (!token.Node.HandleSift <T>(stack, nodeActions)) { return(false); } break; case NodeTraversalAction.InAction: if (!nodeActions.InvokeInAction(token.Node)) { return(false); } break; case NodeTraversalAction.PostAction: if (!nodeActions.InvokePostAction(token.Node)) { return(false); } break; default: throw new ArgumentOutOfRangeException(); } } } finally { stack.Clear(); } return(true); }
/// <summary> /// Traverses the binary search tree looking for the searchKey. /// If no exact match is found in the tree, returns null. /// </summary> /// <returns>The first node that matches the <see cref="searchKey"/> or null if the key /// is not present in the tree.</returns> public BinaryNode <TKey, TValue> Find(TKey searchKey, NodeTraversalActions <TKey, TValue, BinaryNode <TKey, TValue>, NodeTraversalAction> nodeActions) { // We have to use an iterative way because the default stack size of .net apps is 1MB // and it's impractical to change it..... var stack = nodeActions.TraversalStack; Debug.Assert(stack.Count == 0); stack.Push(GetNodeTraversalToken(this, NodeTraversalAction.Sift)); try { while (stack.Count > 0) { var token = stack.Pop(); if (!nodeActions.InvokeKeyPreAction(token.Node, searchKey)) { return(null); } int comp = nodeActions.KeyComparer.Compare(searchKey, token.Node.Key); if (comp == 0) { return(token.Node); } var nextNode = comp < 0 ? token.Node.LeftChild : token.Node.RightChild; if (nextNode == null) { return(null); } stack.Push(GetNodeTraversalToken(nextNode, NodeTraversalAction.Sift)); } } finally { stack.Clear(); } Debug.Fail("Wth?"); return(null); }
private bool HandleSift( Stack <NodeTraversalToken <DisseminateNode <TKey, TValue>, NodeTraversalAction> > stack, NodeTraversalActions <TKey, TValue, DisseminateNode <TKey, TValue>, NodeTraversalAction> nodeActions, bool addSiblings) { // First and only visit to this node if (!nodeActions.InvokePreAction(this)) { return(false); } // Push actions in reverse order // Push all siblings if (addSiblings && RightSibling != this) { foreach (var siblingNode in GetSiblingsReverse().Where(s => s != this)) { // Notify that when being sifted, don't try to add all siblings again stack.Push(GetNodeTraversalToken((DisseminateNode <TKey, TValue>)siblingNode, NodeTraversalAction.SiftOnlySiblings)); } } // Push the child if (FirstChild != null) { if (nodeActions.HasPostAction) { stack.Push(GetNodeTraversalToken(this, NodeTraversalAction.PostAction)); } stack.Push(GetNodeTraversalToken(FirstChild, NodeTraversalAction.Sift)); } else if (!nodeActions.InvokePostAction(this)) // Handle missing children -- we can invoke actions right away { return(false); } return(true); }
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()); }
/// <summary> /// Traverses the binary search tree looking for the searchKey. /// If no exact match is found in the tree, returns null. /// </summary> /// <returns>The first node that matches the <see cref="searchKey"/> or null if the key /// is not present in the tree.</returns> internal BinaryNode <TKey, TValue> FindRecursive(TKey searchKey, NodeTraversalActions <TKey, TValue, BinaryNode <TKey, TValue>, NodeTraversalAction> nodeActions) { if (!nodeActions.InvokeKeyPreAction(this, searchKey)) { return(null); } int comp = nodeActions.KeyComparer.Compare(searchKey, Key); if (comp == 0) { return(this); } try { if (comp < 0) { if (LeftChild == null) { return(null); } return(LeftChild.FindRecursive(searchKey, nodeActions)); } if (RightChild == null) { return(null); } return(RightChild.FindRecursive(searchKey, nodeActions)); } finally { nodeActions.InvokeKeyPostAction(this, searchKey); } }
/// <summary> /// Right DFS traversal of the binary search tree. Nodes are traversed from the largest to the smallest key. /// The False return value of the action functions will result in early termination of the traversal. /// </summary> /// <returns>False if an early termination of the recursion is requested.</returns> public bool SiftRight(NodeTraversalActions <TKey, TValue, BinaryNode <TKey, TValue>, NodeTraversalAction> nodeActions) { return(Sift <DoFlip>(nodeActions)); }
public SplayTree(IComparer <TKey> keyComparer = null) { _traversalActions = new NodeTraversalActions <TKey, TValue, BinaryNode <TKey, TValue>, NodeTraversalAction>(keyComparer); }
public FibonacciHeap(IComparer <TKey> keyComparer = null) : base(keyComparer) { _traversalActions = new NodeTraversalActions <TKey, TValue, DisseminateNode <TKey, TValue>, NodeTraversalAction>(); }