/// <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); }
/// <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); }