/// <summary> /// Syncronize trees. /// </summary> /// <param name="userData">User data to pass from/to the algo.</param> /// <returns></returns> public static bool Sync <TreeT, NodeT>(TreeT uniTree, NodeT uniRoot, UFTree ufTree, SyncDelegate <TreeT, NodeT> sync, object userData) { Data <TreeT, NodeT> data = new Data <TreeT, NodeT> { Sync = sync, UniGetChild = TreeDefs <TreeT, NodeT, IteratorT> .FindTreeGetChildMethod(), UniTree = uniTree, UfTree = ufTree, UfNode = 0, UserData = userData }; return(SyncInternal(data, uniRoot, 0, default(IteratorT))); }
/// <summary> /// Walks the tree. /// </summary> public virtual void Walk(TreeT tree, NodeT root) { if (GetChild == null) { GetChild = TreeDefs <TreeT, NodeT, IteratorT> .FindTreeGetChildMethod(); } Terminate = false; OnTreeBegin(tree, root); // Algorithm: // 1. Put root to the stack. // 2. If stack is empty, exit; othewise take a node from the stack. // 3. If no pre-process have been done, do it: (PruneIf, OnBegin). If prune - remove from the stack, goto 2. // 4 Take child, put it on the stack, goto 2. In no more chilren, post-process the node, // remove node from the stack, goto 2. // // Context in the stack are reused (not removed from stack), only stack depth is changed and // reference to node is cleared. This speeds-up the algo by about factor 30. List <ContextT> stack = new List <ContextT>(100); stack.Add(new ContextT { Node = root }); int depth = 0; // The list of children is cleared every time the node is removed from the stack, // therefore it either new or cleared here. stack[0].CurrentChildInList = 0; if ((PruneIf == null || !PruneIf(root)) && OnNodeBegin(tree, root, stack, depth - 1)) { while (!Terminate) { ContextT parentContext = stack[depth]; ContextT childContext; if (parentContext.CurrentChildInList == 0) { // We have not processed the children yet. BeforeDirectChildren(tree, parentContext.Node, stack, depth); NodeT child; while (GetChild(tree, parentContext.Node, ref parentContext.ChildrenIt, out child)) { if ((PruneIf == null || !PruneIf(child)) && OnNodeBegin(tree, child, stack, depth)) { parentContext.Children.Add(child); } if (Terminate) { break; } } AfterDirectChildren(tree, parentContext.Node, stack, depth); } // Now put the children from the list on the stack one by one and process them recursively. if (parentContext.CurrentChildInList < parentContext.Children.Count) { depth++; if (stack.Count == depth) { stack.Add(new ContextT()); } childContext = stack[depth]; childContext.Node = parentContext.Children[parentContext.CurrentChildInList++]; // The list of children is cleared every time the node is removed from the stack, // therefore it either new or cleared here. childContext.CurrentChildInList = 0; childContext.ChildrenIt = default(IteratorT); } else { // No more children. OnNodeEnd(tree, parentContext.Node, stack, depth); // Release children. parentContext.Children.Clear(); parentContext.Node = default(NodeT); if (--depth < 0) { break; } } } } stack[0].Children.Clear(); OnTreeEnd(tree, root); }
/// <summary> /// Walks the tree. /// </summary> public virtual void Walk(TreeT tree, NodeT root) { if (GetChild == null) { GetChild = TreeDefs <TreeT, NodeT, IteratorT> .FindTreeGetChildMethod(); } Terminate = false; OnTreeBegin(tree, root); // Algorithm: // 1. Put root to the stack. // 2. If stack is empty, exit; othewise take a node from the stack. // 3. If no pre-process have been done, do it: (PruneIf, OnBegin). If prune - remove from the stack, goto 2. // 4 Take child, put it on the stack, goto 2. In no more chilren, post-process the node, // remove node from the stack, goto 2. // // Context in the stack are reused (not removed from stack), only stack depth is changed and // reference to node is cleared. This speeds-up the algo by about factor 30. List <ContextT> stack = new List <ContextT>(100); stack.Add(new ContextT { Node = root }); int depth = 0; ContextT context = stack[0]; while (!Terminate) { // Do preprocessing if ((PruneIf != null && PruneIf(context.Node)) || !OnNodeBegin(tree, context.Node, stack, depth)) { context.Node = default(NodeT); if (--depth < 0) { break; } context = stack[depth]; } skipPreprocessing: if (Terminate) { break; } NodeT child; if (GetChild(tree, context.Node, ref context.ChildrenIt, out child)) { // Child exists depth++; if (stack.Count == depth) { stack.Add(new ContextT()); } context = stack[depth]; context.Node = child; context.ChildrenIt = default(IteratorT); } else { // No more children. OnNodeEnd(tree, context.Node, stack, depth); context.Node = default(NodeT); if (--depth < 0) { break; } context = stack[depth]; goto skipPreprocessing; } } OnTreeEnd(tree, root); }