Exemplo n.º 1
0
        /// <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)));
        }
Exemplo n.º 2
0
        /// <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);
        }
Exemplo n.º 3
0
        /// <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);
        }