Esempio n. 1
0
        /// <summary>
        /// See https://www.youtube.com/watch?v=sD1IoalFomA
        /// The graph has to be rooted. Since the algorithm is intended to work for trees I made an adjustment
        /// such that I process branching nodes only once.
        /// Otherwise we would process the same sub graphs again and again.
        /// </summary>
        public GraphNode FindCommonAncestor(GraphNode node1, GraphNode node2)
        {
            if (_preprocessData is null)
            {
                _preprocessData = PreprocessLeastCommonAncestor();
            }

            var index1 = _preprocessData.GraphNodeToIndex[node1];
            var index2 = _preprocessData.GraphNodeToIndex[node2];

            var from = Math.Min(index1, index2);
            var to   = Math.Max(index1, index2);

            var lcaIndex = -1;

            var minDepth = int.MaxValue;

            for (var i = from; i <= to; i++)
            {
                if (_preprocessData.Depth[i] < minDepth)
                {
                    minDepth = _preprocessData.Depth[i];
                    lcaIndex = i;
                }
            }

            return(_preprocessData.EulerPath[lcaIndex]);
        }
Esempio n. 2
0
        public void UpdateGraph(string hash, IEnumerable <string> allParents)
        {
            lock (_lockObj)
            {
                _preprocessData = null;

                // GraphNode for the given hash.
                var node = GetOrAddNode(hash);

                // Update parents and child relationships
                foreach (var parentHash in allParents)
                {
                    node.Parents.Add(GetOrAddNode(parentHash));

                    var parent = GetOrAddNode(parentHash);
                    parent.Children.Add(GetOrAddNode(hash));
                }
            }
        }
Esempio n. 3
0
        private LeaseCommonAncestorPreprocessData PreprocessLeastCommonAncestor()
        {
            void TraverseDepthFirst(LeaseCommonAncestorPreprocessData preprocessData, GraphNode node, int currentDepth = 0)
            {
                if (preprocessData.AlreadyProcessed.Add(node) is false)
                {
                    return;
                }

                preprocessData.Record(node, currentDepth);
                foreach (var child in node.Children)
                {
                    TraverseDepthFirst(preprocessData, child, currentDepth + 1);
                    preprocessData.Record(node, currentDepth);
                }
            }

            var data = new LeaseCommonAncestorPreprocessData();
            var root = AllNodes.Single(node => !node.Parents.Any());

            TraverseDepthFirst(data, root);

            return(data);
        }