예제 #1
0
파일: Graph.cs 프로젝트: bfdes/Collections
        /// <summary>
        /// Produces a minimum spanning tree of the given graph using Prim's algorithm in O(E*ln E) time.
        /// Raises <exception cref="System.InvalidOperationException"> if the graph is not connected.
        /// </summary>
        /// <returns>Graph representation of the MST</returns>
        public static Graph <V> Prim <V>(Graph <V> graph)
        {
            if (graph == null)
            {
                throw new ArgumentNullException();
            }

            if (!graph.IsConnected())
            {
                throw new InvalidOperationException();
            }

            // Lazy variant of Prim's algorithm:
            // Grow a tree by adding the smallest edge pointing out of it
            var tree     = new Graph <V>();
            var queue    = new BinaryHeap <Edge <V> >();
            var vertices = new HashSet <V>();  // vertices in the tree

            // Adds edges of v pointing out of the tree to the PQ
            void Visit(V v)
            {
                vertices.Add(v);
                foreach (var e in graph.Edges(v))
                {
                    if (!vertices.Contains(e.to))
                    {
                        queue.Push(e);  // If e.to is already in the tree then e (or rather its complement) is in the queue
                    }
                }
            }

            if (!graph.IsEmpty())
            {
                Visit(graph.Vertices().First());
            }

            while (!queue.IsEmpty())
            {
                var e = queue.Pop();
                if (vertices.Contains(e.to))
                {
                    continue;  // Otherwise we will form a cycle
                }
                tree.Add(e);
                Visit(e.to);
            }
            return(tree);
        }
예제 #2
0
파일: Graph.cs 프로젝트: bfdes/Collections
        /// <summary>
        /// Produces a minimum spanning tree of the given graph using Kruskal's algorithm in O(E*ln V) time.
        /// Raises <exception cref="System.InvalidOperationException"> if the graph is not connected.
        /// </summary>
        /// <returns>Graph representation of the MST</returns>
        public static Graph <V> Kruskal <V>(Graph <V> graph)
        {
            if (graph == null)
            {
                throw new ArgumentNullException();
            }

            if (!graph.IsConnected())
            {
                throw new InvalidOperationException();  // We would need to produce a minimum spanning forest instead
            }
            // Kruskal's algorithm is a special case of the greedy MST algorithm:
            // - Maintain a forest of trees (initially individual vertices of the graph)
            // - Repreatedly add edges in descending order of weight to combine forests into a tree
            //   (Exclude edges that connect vertices that are already part of the same tree.)

            var tree  = new Graph <V>();
            var n     = 0; // no. of vertices in the MST
            var queue = new BinaryHeap <Edge <V> >();

            foreach (var e in graph.Edges())
            {
                queue.Push(e);
            }

            var vertices = graph.Vertices();
            var N        = vertices.Count(); // no. of vertices in the original graph
            var uf       = new QuickUnion <V>(vertices.ToArray());

            // The MST of a connected graph must contain exactly N-1 edges
            while (n < N - 1)
            {
                var e = queue.Pop();
                if (!uf.Connected(e.from, e.to))
                {
                    uf.Union(e.from, e.to);
                    tree.Add(e);
                    n++;
                }
            }
            return(tree);
        }