private void AssertEdges(IMinimalSpanTreeSearch algorithm, IGraphDefinition graph, params int[] edgeIds) { var edges = algorithm.GetMST(graph).ToList(); Assert.AreEqual(edgeIds.Length, edges.Count); foreach (var edgeId in edgeIds) { Assert.IsTrue(edges.Any(x => x.Id == edgeId), $"Edge: {edgeId} not found in : {string.Join(",", edges.Select(x => x.Id))}"); } }
/// <inheritdoc/> public IEnumerable <Edge> GetMST(IGraphDefinition graphDefinition) { if (graphDefinition == null) { throw new ArgumentNullException(nameof(graphDefinition)); } var allVertexes = graphDefinition.Vertices.ToList(); if (allVertexes.Count <= 1) { throw new ArgumentException("Minimal vertexes count is 2", nameof(graphDefinition)); } var firstVertex = allVertexes[0]; var notDistributedVertexes = new List <VertextExt>(); for (var i = 1; i < allVertexes.Count; ++i) { var edges = graphDefinition.GetEdges(firstVertex, allVertexes[i]).ToList(); notDistributedVertexes.Add(new VertextExt { Vertex = allVertexes[i], Winner = edges.Any() ? edges.OrderBy(x => x.Weight).Min() : null }); } var heap = new VertextHeap(notDistributedVertexes); while (!heap.IsEmpty) { var heapElement = heap.Extract(); var closestVertex = heapElement.Value; if (closestVertex.Winner == null) { throw new InvalidOperationException("Graph is not connected"); } for (var i = 0; i < heap.Count; ++i) { var vertex = heap.Heap[i].Value.Vertex; if (graphDefinition.EdgeExists(closestVertex.Vertex, vertex)) { var closestEdge = graphDefinition.GetEdges(closestVertex.Vertex, vertex).OrderBy(x => x.Weight).First(); if (heap.Heap[i].Value.Winner == null || heap.Heap[i].Key > closestEdge.Weight) { heap.EditElementKey(vertex, closestEdge); } } } yield return(closestVertex.Winner); } }
/// <inheritdoc/> public IEnumerable <Edge> GetMST(IGraphDefinition graphDefinition) { var edges = graphDefinition.Edges.ToArray(); var vertexes = graphDefinition.Vertices.Select(x => new VertexUnionFindItem { Id = x.Id, Vertex = x }).ToList(); var vertexesDict = vertexes.ToDictionary(x => x.Id, x => x); _sortAlgorithm.Sort(edges); var unionFind = new UnionFind <int>(vertexes); foreach (var edge in edges) { var(from, to) = graphDefinition.GetVertexPair(edge); var firstParent = unionFind.Find(vertexesDict[from.Id]); var secondParent = unionFind.Find(vertexesDict[to.Id]); if (firstParent != secondParent) { unionFind.Union(vertexesDict[from.Id], vertexesDict[to.Id]); yield return(edge); } } }