/// <summary> /// Thanks to Morton Mertner for a fix here /// </summary> /// <param name="g"></param> /// <param name="s"></param> /// <returns></returns> public static IDigraph DijkstrasAlgorithm(IDigraph g, int s) { int n = g.NumberOfVertices; Entry[] table = new Entry[n]; for (int v = 0; v < n; ++v) { table[v] = new Entry(false, int.MaxValue, int.MaxValue); } table[s].distance = 0; IPriorityQueue queue = new BinaryHeap(g.NumberOfEdges); queue.Enqueue(new Association(0, g.GetVertex(s))); int vertexCount = 0; // MM fix while (!queue.IsEmpty) { Association assoc = (Association)queue.DequeueMin(); IVertex v0 = (IVertex)assoc.Value; if (!table[v0.Number].known) { table[v0.Number].known = true; vertexCount++; // MM fix foreach (IEdge e in v0.EmanatingEdges) { IVertex v1 = e.MateOf(v0); int d = table[v0.Number].distance + (e.Weight != null ? (int)e.Weight : 0); if (table[v1.Number].distance > d) { table[v1.Number].distance = d; table[v1.Number].predecessor = v0.Number; queue.Enqueue(new Association(d, v1)); } } } } // MM fixed loop to filter out unused edges and vertices IDigraph result = new DigraphAsLists(vertexCount); int cv = 0; int[] v2cv = new int[n]; for (int v = 0; v < n; ++v) { if (table[v].known) { result.AddVertex(cv, table[v].distance); v2cv[v] = cv++; } } for (int v = 0; v < n; ++v) { if (v != s && table[v].known && table[v].distance < int.MaxValue) { result.AddConnection(v2cv[v], v2cv[table[v].predecessor]); } } return(result); }
/// <summary> /// Kruskal's algorithm is an algorithm that finds a minimum spanning tree for a connected weighted graph. /// This means it finds a subset of the edges that forms a tree that includes every vertex, /// where the total weight of all the edges in the tree is minimized. /// If the graph is not connected, then it finds a minimum spanning forest (a minimum spanning tree for each connected component). /// </summary> /// <param name="g"></param> /// <returns></returns> public static IGraph KruskalsAlgorithm(IGraph g) { Console.WriteLine("Starting..."); int i1 = g.NumberOfVertices; IGraph graph1 = new GraphAsLists(i1); for (int j1 = 0; j1 < i1; j1++) { graph1.AddVertex(j1); } IPriorityQueue priorityQueue = new BinaryHeap(g.NumberOfEdges); IEnumerator iEnumerator = g.Edges.GetEnumerator(); Console.WriteLine("got the edge enumerator..."); try { while (iEnumerator.MoveNext()) { IEdge edge1 = (IEdge)iEnumerator.Current; int k; //the casting depends on the datatype of the weight, here you are on your own //we'll assume that an int will do as an example if (edge1.Weight == null) { k = 0; } else { try { k = (int)edge1.Weight; } catch { k = 0; } } priorityQueue.Enqueue(new Association(k, edge1)); } } finally { IDisposable iDisposable = iEnumerator as IDisposable; if (iDisposable != null) { iDisposable.Dispose(); } } Console.WriteLine("after the edge enumerator..."); Console.WriteLine(priorityQueue.ToString()); IPartition partition = new PartitionAsForest(i1); Console.WriteLine("The partition: " + partition.Count); while (!priorityQueue.IsEmpty && (partition.Count > 1)) { IEdge edge2 = (IEdge)((Association)priorityQueue.DequeueMin()).Value; Console.WriteLine(edge2.ToString()); int i2 = edge2.V0.Number; int j2 = edge2.V1.Number; Console.WriteLine("got vertices (" + i2 + "," + j2 + ")"); ISet set1 = partition.Find(i2); ISet set2 = partition.Find(j2); if (set1 != set2) { partition.Join(set1, set2); graph1.AddConnection(i2, j2); } } return(graph1); }
/// <summary> /// Computes a spanning tree /// </summary> /// <param name="g"></param> /// <param name="s"></param> /// <returns></returns> public static IGraph PrimsAlgorithm(IGraph g, int s) { int i1 = g.NumberOfVertices; Entry[] entrys = new Entry[i1]; for (int j1 = 0; j1 < i1; j1++) { entrys[j1] = new Entry(false, int.MaxValue, int.MaxValue); } entrys[s].distance = 0; IPriorityQueue priorityQueue = new BinaryHeap(g.NumberOfEdges); priorityQueue.Enqueue(new Association(0, g.GetVertex(s))); while (!priorityQueue.IsEmpty) { IVertex vertex1 = (IVertex)((Association)priorityQueue.DequeueMin()).Value; if (entrys[vertex1.Number].known) { continue; } entrys[vertex1.Number].known = true; IEnumerator iEnumerator = vertex1.EmanatingEdges.GetEnumerator(); try { while (iEnumerator.MoveNext()) { IEdge edge = (IEdge)iEnumerator.Current; IVertex vertex2 = edge.MateOf(vertex1); int k = (edge.Weight == null? 0 :(int)edge.Weight); if (!entrys[vertex2.Number].known && entrys[vertex2.Number].distance > k) { entrys[vertex2.Number].distance = k; entrys[vertex2.Number].predecessor = vertex1.Number; priorityQueue.Enqueue(new Association(k, vertex2)); } } } finally { IDisposable iDisposable = iEnumerator as IDisposable; if (iDisposable != null) { iDisposable.Dispose(); } } } IGraph graph1 = new GraphAsLists(i1); for (int i2 = 0; i2 < i1; i2++) { graph1.AddVertex(i2); } for (int j2 = 0; j2 < i1; j2++) { if (j2 != s) { graph1.AddConnection(j2, entrys[j2].predecessor); } } return(graph1); }