Пример #1
0
        private TreeEvalItem <TTreeNode> GetNextRBFSCousin(TTreeNode curr, TreeNodePath path, int targetDepth)
        {
            // If we've gotten into an error state, or if we're attempting to go past root
            if (curr == null || curr == m_traversalParameters.Root)
            {
                return(null);
            }

            // Iterate over all siblings and build a stack of siblings for us to evaluate (popping will give us sibling closest to curr, instead of parent's index[0])
            var parent = m_traversalParameters.GetParentMethod(curr);

            if (parent == null)
            {
                return(null);
            }

            var siblingStack = new Stack <IndexTrackedNode>();
            int siblingIndex = 0;

            foreach (var sibling in m_traversalParameters.GetChildrenMethod(parent))
            {
                if (sibling == curr)
                {
                    break;
                }

                siblingStack.Push(new IndexTrackedNode(siblingIndex++, sibling));
            }

            // Evaluate from closest to curr back to index zero, and call GetlastLeafAtDepth, if we find a cousin at the target depth
            //  then that is the next BFS item to search
            while (siblingStack.Count > 0)
            {
                var next = siblingStack.Pop();
                TreeEvalItem <TTreeNode> cousinLeaf = this.GetLastLeafAtDepth(next.Node, path.CopyAndSwapEndForSibling(next.Index), targetDepth);
                if (cousinLeaf != null)
                {
                    return(cousinLeaf);
                }
            }

            // If no cousin is found, than recurse upwards, this will be evaluting parent as curr
            return(this.GetNextRBFSCousin(parent, path.CopyAndRemoveEnd(), targetDepth));
        }
Пример #2
0
        private TreeEvalItem <TTreeNode> GetLastLeafAtDepth(TTreeNode node, TreeNodePath path, int targetDepth)
        {
            if (path.Count == targetDepth)
            {
                return(new TreeEvalItem <TTreeNode>(node, path));
            }

            List <TTreeNode> children = m_traversalParameters.GetChildrenMethod(node).ToList();

            for (int childIndex = children.Count - 1; childIndex >= 0; --childIndex)
            {
                var result = GetLastLeafAtDepth(children[childIndex], path.CopyAndAddToPath(childIndex), targetDepth);
                if (result != null)
                {
                    return(result);
                }
            }

            return(null);
        }
Пример #3
0
        /// <summary>
        /// Specialty constructor for creating iter from a root node
        /// </summary>
        /// <param name="start">The root node</param>
        /// <param name="traversalParameters">The parameters to the tree traversal</param>
        /// <param name="getChildrenMethodOverride">An override to the default GetChildren method</param>
        /// <param name="getParentMethodOverride">An override to the default GetParent method</param>
        internal TreeIter(TTreeNode start, TreeTraversalParameters <TTreeNode> traversalParameters)
        {
            this.TraversalParameters = traversalParameters;

            // We want our paths to be root-centric so if start is not root (and there is a root listed)
            //  then we need to give ourselves a starter path from root
            TreeNodePath pathFromRoot = null;

            if (traversalParameters.Root != null && start != traversalParameters.Root)
            {
                var       treePath = new Stack <int>();
                TTreeNode target   = start;
                while (target != null && target != traversalParameters.Root)
                {
                    var parent = this.TraversalParameters.GetParentMethod(target);
                    if (parent == null)
                    {
                        break;
                    }

                    // To path in this way, we must gurantee that the children we get are indexable
                    //  thus this will throw if they are not of IList
                    var children = this.TraversalParameters.GetChildrenMethod.Invoke(parent);
                    if (children is IList listChild)
                    {
                        treePath.Push(listChild.IndexOf(target));
                    }
                    else
                    {
                        treePath.Push(children.Count(_ => _ != target));
                    }

                    target = parent;
                }

                pathFromRoot = new TreeNodePath(treePath);
            }
            this.State = new TreeIterState <TTreeNode>(start, traversalParameters, pathFromRoot);
            this.State.ProcessNextEvaluations();
        }
Пример #4
0
        private void ProcessNextEvaluationsForParentTraversal()
        {
            TTreeNode parent = this.Target != null?m_traversalParameters.GetParentMethod(this.Target) : null;

            if (parent == null)
            {
                return;
            }

            if (!this.IsUniqueInIteration(parent))
            {
                return;
            }

            TreeNodePath newPath = this.TargetPath.CopyAndRemoveEnd();

            m_nextEvalSet.Add(new TreeEvalItem <TTreeNode>(parent, newPath));
            if (m_traversalParameters.TrackReentrancy)
            {
                m_reentrancyTracking.Add(parent);
            }
            return;
        }
Пример #5
0
        public static int CompareTreeNodePaths(TreeNodePath left, TreeNodePath right, eTraversalFlowDirection flowDirection = eTraversalFlowDirection.ThroughChildren, eTraversalStrategy traversalStrategy = eTraversalStrategy.Default)
        {
            switch (flowDirection)
            {
            case eTraversalFlowDirection.ThroughParents:
                return(CompareTreeNodePaths_ThroughParents(left, right));

            case eTraversalFlowDirection.ThroughChildren:
                if (traversalStrategy == eTraversalStrategy.BreadthFirst)
                {
                    return(CompareTreeNodePaths_BreadthFirst(left, right));
                }
                return(CompareTreeNodePaths_DepthFirst(left, right));

            case eTraversalFlowDirection.ReversedThroughChildren:
                if (traversalStrategy == eTraversalStrategy.BreadthFirst)
                {
                    return(CompareTreeNodePaths_ReverseBreadthFirst(left, right));
                }
                return(CompareTreeNodePaths_ReverseDepthFirst(left, right));
            }

            throw new InvalidOperationException("Traversal flow and/or strategy was invalid, flowDirection was casted to something invalid");
        }
Пример #6
0
        private TreeEvalItem <TTreeNode> ProcessNextEvaluationsForRBFS(TTreeNode target, TreeNodePath path, int targetDepth)
        {
            if (target == null)
            {
                return(null);
            }

            var parent = m_traversalParameters.GetParentMethod(target);

            if (parent == null)
            {
                return(null);
            }


            TTreeNode nextClosestSibling      = null;
            int       nextClosestSiblingIndex = -1;
            int       childIndex = 0;

            foreach (var sibling in m_traversalParameters.GetChildrenMethod(parent))
            {
                if (sibling == target)
                {
                    break;
                }

                nextClosestSiblingIndex = childIndex++;
                nextClosestSibling      = sibling;
            }

            // No siblings, recurse to the parent/grandparent
            if (nextClosestSibling == null)
            {
                TreeEvalItem <TTreeNode> cousin = this.GetNextRBFSCousin(parent, path.CopyAndRemoveEnd(), targetDepth);
                if (cousin != null)
                {
                    return(cousin);
                }

                // Looks like end of this depth... time to go forward and back to the end
                return(this.GetLastLeafAtDepth(m_traversalParameters.Root, new TreeNodePath(), this.CurrentDepthFromOrigin - 1));
            }


            // There were some siblings, see if we can find our next target
            return(new TreeEvalItem <TTreeNode>(nextClosestSibling, path.CopyAndSwapEndForSibling(nextClosestSiblingIndex)));
        }
Пример #7
0
        private TreeEvalItem <TTreeNode> GetLastLeaf(TTreeNode node, int currentDepth, TreeNodePath path)
        {
            IList <TTreeNode> children = m_traversalParameters.GetChildrenMethod(node).ToList();

            if (children.Count == 0)
            {
                return(new TreeEvalItem <TTreeNode>(node, path));
            }

            int lastIndex = children.Count - 1;

            path.AddToPath(lastIndex);
            return(GetLastLeaf(children[lastIndex], currentDepth + 1, path));
        }
Пример #8
0
        internal TreeIterState(TTreeNode node, TreeTraversalParameters <TTreeNode> traversalParameters, TreeNodePath nodePath = null)
        {
            m_traversalParameters = traversalParameters;

            this.Target = node;
            this.CurrentNumberOfEvaluations = 0;

            if (nodePath != null)
            {
                this.TargetPath = nodePath;
            }
            else
            {
                this.TargetPath = new TreeNodePath();
            }
        }
Пример #9
0
 public TreeEvalItem(TTreeNode node, TreeNodePath path)
 {
     this.Node     = node;
     this.NodePath = path;
 }
Пример #10
0
        internal static TreeIter <TTreeNode> CreateIteratorAtNodePath(TTreeNode root, TreeNodePath nodePath, TreeTraversalParameters <TTreeNode> traversalParameters, GetTreeNodeChildren <TTreeNode> getChildrenMethodOverride = null, GetTreeNodeParent <TTreeNode> getParentMethodOverride = null)
        {
            // If the node path is empty, then we're creating one from the root
            if (nodePath.Count == 0)
            {
                return(new TreeIter <TTreeNode>(root, traversalParameters));
            }

            if (traversalParameters.FlowDirection == eTraversalFlowDirection.ThroughParents)
            {
                // Why is this not supported
                Debug.Fail("Node pathing through parents is not supported");
            }
            else if (traversalParameters.FlowDirection == eTraversalFlowDirection.ThroughChildren)
            {
                // Otherwise we are creating an iterator for the node's parent, but with the next evaluations stocked starting at the final nodepath piece,
                //  then we can just increment by one. This enables us to use the siblings to the indicated start node.
                TTreeNode parentNode = TreeTraversal <TTreeNode> .ParentNodeFromPath(root, nodePath);

                if (parentNode == null)
                {
                    return(End);
                }

                var justBeforeIter = new TreeIter <TTreeNode>(parentNode, nodePath, traversalParameters, getChildrenMethodOverride, getParentMethodOverride);
                return(++justBeforeIter);
            }
            else if (traversalParameters.FlowDirection == eTraversalFlowDirection.ReversedThroughChildren)
            {
                Debug.Fail("Node pathing through parents is not supported");
            }

            return(End);
        }
Пример #11
0
 private static int CompareTreeNodePaths_ReverseBreadthFirst(TreeNodePath left, TreeNodePath right)
 {
     throw new NotImplementedException("Reverse methods not implemented yet");
 }
Пример #12
0
 private static int CompareTreeNodePaths_ThroughParents(TreeNodePath left, TreeNodePath right)
 {
     throw new NotSupportedException("I'm just not sure about parent traversal right now...");
 }
Пример #13
0
 public TTreeNode NodeAt(TreeNodePath nodePath)
 {
     return(TreeTraversal <TTreeNode> .NodeAt(this.Root, nodePath, this.GetChildrenOverride, this.GetParentOverride));
 }
Пример #14
0
 public TreeIter <TTreeNode> IteratorAt(TreeNodePath nodePath, Predicate <TTreeNode> predicate = null, eTraversalFlowDirection flowDirection = TreeTraversal <TTreeNode> .DefaultTraversalFlowDirection, eTraversalStrategy strategy = TreeTraversal <TTreeNode> .DefaultTraversalStrategy, bool includeRoot = true, LevelRestriction depthLimits = null)
 {
     return(TreeTraversal <TTreeNode> .IteratorAt(this.Root, nodePath, predicate, flowDirection, strategy, includeRoot, depthLimits, this.GetChildrenOverride, this.GetParentOverride));
 }
Пример #15
0
 internal TreeNodePath(TreeNodePath other) : this(new List <int>(other.m_actualIndexList))
 {
 }