public static Graph <VisVertex> GetMST_KrusculDSU(Graph <VisVertex> graph) { Edge <VisVertex>[] sortedEdges = GetSortedEdges(graph.EdgesClone); Graph <VisVertex> mst = new Graph <VisVertex>(graph.VerticesClone);//Создаем МОД DisjointSet dsu = new DisjointSet(graph.Order); foreach (Edge <VisVertex> edge in sortedEdges) { if (mst.EdgesCount == graph.Order - 1) { break; //Если МОД построен выходим из цикла } if (dsu.InTheSameSet(edge.V1Id, edge.V2Id)) { continue; } //Если вершины ребра в одной компоненте пропускаем ребро mst.AddEdge(edge); //Добавляем ребро мнимального веса в МОД dsu.UnionSets(edge.V1Id, edge.V2Id); //Объединяем связанные компоненты } if (mst.EdgesCount != graph.Order - 1) { throw new Exception("Ошибка МОД не найдено"); } return(mst); }
public AdjVertexSortedList Union(AdjVertexSortedList list2Union, DisjointSet dsu) { var unionList = new AdjVertexSortedList(); while (!this.IsEmpty && !list2Union.IsEmpty) { if (dsu.InTheSameSet(this.MaxWeightEdge.V1Id, this.MaxWeightEdge.V2Id)) { this.ExtractMaxWeightEdge(); } //Удаляем из текущего списка ребра, //у которых обе вершины входят в одну компоненту связности else if (dsu.InTheSameSet( list2Union.MaxWeightEdge.V1Id, list2Union.MaxWeightEdge.V2Id)) { list2Union.ExtractMaxWeightEdge(); //Удаляем из списка для объединения ребра, //у которых обе вершины входят в одну компоненту связности } else if (this.MaxWeightNode > list2Union.MaxWeightNode) { unionList.Add(this.ExtractMaxWeightEdge()); } else { unionList.Add(list2Union.ExtractMaxWeightEdge()); } } while (!this.IsEmpty) { if (dsu.InTheSameSet(this.MaxWeightEdge.V1Id, this.MaxWeightEdge.V2Id)) { this.ExtractMaxWeightEdge(); } else { unionList.Add(this.ExtractMaxWeightEdge()); } } while (!list2Union.IsEmpty) { if (dsu.InTheSameSet(list2Union.MaxWeightEdge.V1Id, list2Union.MaxWeightEdge.V2Id)) { list2Union.ExtractMaxWeightEdge(); } else { unionList.Add(list2Union.ExtractMaxWeightEdge()); } } return(unionList); }
public async void KrusculAlgorithmVisAsync() { if (!graph.IsConnected) { visualisator.Print("Остовное дерево не может быть построено. Граф не связен!"); visualisator.ApEndLog("Остовное дерево не может быть построено. Граф не связен!"); return; } form.BlockTabControl(); int order = graph.Order; Edge <VisVertex>[] sortedEdges = GetSortedEdges(graph.EdgesClone); Graph <VisVertex> mst = new Graph <VisVertex>(graph.VerticesClone);//Создаем МОД DisjointSet dsu = new DisjointSet(order); SetVerticesDifferentColors(); visualisator.Print("Маркировка вершин"); visualisator.ApEndLog("МОД сотоит из отдельных вершин - компонент связности, " + "маркированных различными цветами" + "\nПоследовательно простомтрим ребра, отсортированные по неубыванию веса."); visualisator.PrintDataStructuresKruskal(sortedEdges, sortedEdges[0], dsu, colors); await Task.Delay(SleepInterval); foreach (Edge <VisVertex> edge in sortedEdges) { if (mst.EdgesCount == order - 1) { break; //Если МОД построен выходим из цикла } if (dsu.InTheSameSet(edge.V1Id, edge.V2Id)) { visualisator.ApEndLog( $"Ребро {edge} соединяет вершины из одной компоненты - пропускаем."); visualisator.PrintDataStructuresKruskal(sortedEdges, edge, dsu, colors); await Task.Delay(SleepInterval); continue; //Если вершины ребра в одной компоненте пропускаем ребро } mst.AddEdge(edge); //Добавляем ребро мнимального веса в МОД dsu.UnionSets(edge.V1Id, edge.V2Id); //Объединяем связанные компоненты RefreshColors(dsu, mst); visualisator.Print($"Добавление ребра минимального веса. " + $"Всего ребер {mst.EdgesCount}. Общий вес {mst.TotalWeight}."); visualisator.ApEndLog( $"Ребро {edge} соединяет вершины из разных компонент - добавляем в МОД. " + $"Объединяем связанные ребром компоненты."); visualisator.PrintDataStructuresKruskal(sortedEdges, edge, dsu, colors); await Task.Delay(SleepInterval); } if (mst.EdgesCount != order - 1) { throw new Exception("Ошибка МОД не найдено"); } else { visualisator.Print( $"Минимальное остовное дерево построено. Общий вес {mst.TotalWeight}."); visualisator.ApEndLog( $"Минимальное остовное дерево построено. Общий вес {mst.TotalWeight}."); } form.UnBlockTabControl(); }