private void PrintASL(AdjVertexSortedList list, string name, Point point, int size) { float nameSize = graphics.MeasureString(name, smallFont).Width; graphics.DrawString(name, smallFont, textBrush, point); point = new Point(point.X + (int)nameSize + 1, point.Y); foreach (Edge <VisVertex> edge in list) { PrintEdgeRectangle(edge, point, size); point = new Point(point.X + size, point.Y); } }
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); }
private void ShowAdjLists() { string[][] lists = AdjVertexSortedList.GetStringAdjLists(graph); int maxLenght = GetMaxLenght(); dgvAdjMatrix.Columns.Clear(); dgvAdjMatrix.Rows.Clear(); dgvAdjMatrix.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; if (maxLenght == 0) { return; } for (int i = 0; i <= maxLenght; i++) { dgvAdjMatrix.Columns.Add(i.ToString(), ""); dgvAdjMatrix.Columns[i].Width = 60; } for (int i = 0; i < lists.Length; i++) { dgvAdjMatrix.Rows.Add(); dgvAdjMatrix.Rows[i].Height = 18; } for (int i = 0; i < lists.Length; i++) { for (int j = 0; j <= lists[i].Length; j++) { if (j == 0) { dgvAdjMatrix.Rows[i].Cells[j].Value = i.ToString(); dgvAdjMatrix.Rows[i].Cells[j].Style.BackColor = printer.VertexColor; } else { dgvAdjMatrix.Rows[i].Cells[j].Value = lists[i][j - 1]; } } } int GetMaxLenght() { int max = 0; foreach (var row in lists) { if (row.Length > max) { max = row.Length; } } return(max); } }
public AdjVertexSortedList Union(AdjVertexSortedList list2Union, bool[] isIncluded) { var unionList = new AdjVertexSortedList(); while (!this.IsEmpty && !list2Union.IsEmpty) { if (isIncluded[this.MaxWeightNode.AdjVertexID]) { this.ExtractMaxWeightEdge(); } //Удаляем из текущего списка ребра, //у которых обе вершины входят в текущую компоненту связности else if (isIncluded[list2Union.MaxWeightNode.AdjVertexID]) { list2Union.ExtractMaxWeightEdge(); } //Удаляем из списка для объединения ребра, //у которых обе вершины входят в текущую компоненту связности else if (this.MaxWeightNode > list2Union.MaxWeightNode) { unionList.Add(this.ExtractMaxWeightEdge()); } else { unionList.Add(list2Union.ExtractMaxWeightEdge()); } } while (!this.IsEmpty) { if (isIncluded[this.MaxWeightNode.AdjVertexID]) { this.ExtractMaxWeightEdge(); } else { unionList.Add(this.ExtractMaxWeightEdge()); } } while (!list2Union.IsEmpty) { if (isIncluded[list2Union.MaxWeightNode.AdjVertexID]) { list2Union.ExtractMaxWeightEdge(); } else { unionList.Add(list2Union.ExtractMaxWeightEdge()); } } return(unionList); }
public void PrintDataStructuresPrim(AdjVertexSortedList[] lists, AdjVertexSortedList mstList, int inMSTSize = 12, int aslSize = 20) { int width = Max(GetMaxLenght() * aslSize + 200, dataStructuresArea.Width); int height = Max(lists.Length * aslSize + 100, dataStructuresArea.Height); bitmap = new Bitmap(width, height); graphics = Graphics.FromImage(bitmap); graphics.Clear(areaBackColor); Point point = new Point(3, 3); PrintInMSTVertices(point, inMSTSize); point.Offset(0, inMSTSize + 3); PrintASL(mstList, "МОД", point, aslSize); point.Offset(0, aslSize + 3); for (int i = 0; i < lists.Length; i++) { if (lists[i].IsEmpty) { continue; } PrintASL(lists[i], i.ToString(), point, aslSize); point.Offset(0, aslSize + 3); } dataStructuresArea.Image = bitmap; int GetMaxLenght() { int max = 0; foreach (var row in lists) { if (row.Length > max) { max = row.Length; } } return(max); } int Max(int a, int b) { if (a > b) { return(a); } return(b); } }
public static Graph <VisVertex> GetMstPrim(Graph <VisVertex> graph) { if (!graph.IsConnected) { throw new Exception("Граф не связен"); } Random rnd = new Random(); bool[] inMST = new bool[graph.Order]; //Создаем логический массив для проверки вхождения вершин в МОД List <Vertex <VisVertex> > verticesMST = graph.VerticesClone; //Создаем список вершин МОД List <Edge <VisVertex> > edgesMST = new List <Edge <VisVertex> >(); //Создаем список ребер МОД var adjVertexSortLists = GetAdjLists(graph); //Создаем сортированные списки смежности для вершин графа var adjVertexSortListMST = new AdjVertexSortedList(); //Создаем пустой сортированный список смежности для всего МОД int firsrVertex = rnd.Next(0, graph.Order); //Выбираем случайную вершину для начала построения МОД inMST[firsrVertex] = true; //Отмечаем произвольную вершину, как включенную в МОД adjVertexSortListMST = adjVertexSortListMST.Union( adjVertexSortLists[firsrVertex], inMST); //Объединяем список смежности МОД и список смежности выбраной вершины //(при объединении сортировка поддерживается) for (int i = 0; i < graph.Order - 1; i++) //Цикл для построения МОД, шагов по количеству вершин - 1 { Edge <VisVertex> edge2Add = adjVertexSortListMST.ExtractMinWeightEdge(); //выбираем из списка смежности МОД ребро минимального веса AddEdge(edge2Add, verticesMST, edgesMST); //Добавляем ребро мнимального веса в МОД inMST[edge2Add.V2Id] = true; //Отмечаем присоединенную вершину, как включенную в МОД adjVertexSortListMST = adjVertexSortListMST.Union( adjVertexSortLists[edge2Add.V2Id], inMST); //Объединяем списки смежности МОД и последней добавленной вершины //(при этом ребра внутри МОД удаляются) } if (edgesMST.Count != graph.Order - 1) { throw new Exception("Ошибка МОД не найдено"); } return(new Graph <VisVertex>(verticesMST, edgesMST)); }
public static AdjVertexSortedList[] GetAdjLists(Graph <VisVertex> graph) { var lists = new AdjVertexSortedList[graph.Order]; //Создаем массив списков смежности for (int i = 0; i < graph.Order; i++) //Создаем сп.смеж-и для каждой вершины графа { lists[i] = new AdjVertexSortedList(); } foreach (Edge <VisVertex> edge in graph.Edges)//Распределяем ребра по спискам { if (edge.V1Id == edge.V2Id) { continue; //Пропускаем петли } lists[edge.V1Id].Add(edge); //Добавляем ребро в список первой вершины lists[edge.V2Id].Add(edge.Reverse()); //Добавляем ребро в список второй вершины //(переворачиваем ребро, т.к. для второй вешины смежняая будет первая) } return(lists); }
public async void PrimsAlgorithmVisAsync(Color mstColor, bool startFrom0) { if (!graph.IsConnected) { visualisator.Print("Остовное дерево не может быть построено. Граф не связен!"); visualisator.ApEndLog("Остовное дерево не может быть построено. Граф не связен!"); return; } form.BlockTabControl(); int mstWeight = 0; bool[] inMST = new bool[graph.Order]; //Создаем логический массив для проверки вхождения вершин в МОД List <Edge <VisVertex> > edgesMST = new List <Edge <VisVertex> >(); //Создаем список ребер МОД var adjVertexSortLists = GetAdjLists(graph); //Создаем сортированные списки смежности для вершин графа var adjVertexSortListMST = new AdjVertexSortedList(); //Создаем пустой сортированный список смежности для всего МОД int firsrVertex = startFrom0 ? 0 : rnd.Next(0, graph.Order); //Выбираем случайную вершину для начала построения МОД inMST[firsrVertex] = true; //Отмечаем произвольную вершину, как включенную в МОД visualisator.SetVertexColor(firsrVertex, mstColor); visualisator.Print(startFrom0 ? "Начиная с нулевой вершины" : "Начальная вершина выбрана произвольно"); visualisator.ApEndLog(startFrom0 ? "Начиная с нулевой вершины" : "Произвольный выбор начальной вершины МОД."); await Task.Delay(SleepInterval); adjVertexSortListMST = adjVertexSortListMST.Union( adjVertexSortLists[firsrVertex], inMST); //Объединяем список смежности МОД и список смежности выбраной вершины //(при объединении сортировка поддерживается) for (int i = 0; i < graph.Order - 1; i++) //Цикл для построения МОД, шагов по количеству вершин - 1 { Edge <VisVertex> edge2Add = adjVertexSortListMST.ExtractMinWeightEdge(); //выбираем из списка смежности МОД ребро минимального веса edgesMST.Add(edge2Add); //Добавляем ребро мнимального веса в МОД inMST[edge2Add.V2Id] = true; //Отмечаем присоединенную вершину, как включенную в МОД mstWeight += edge2Add.Weight; adjVertexSortListMST = adjVertexSortListMST.Union( adjVertexSortLists[edge2Add.V2Id], inMST); //Объединяем списки смежности МОД и последней добавленной вершины //(при этом ребра внутри МОД удаляются) visualisator.ApEndLog($"Шаг {i + 1}. Выбираем ребро минимального веса, " + $"соединяющее вершину внутри и вне МОД - {edge2Add}"); visualisator.SetEdgeColor(edge2Add, mstColor); visualisator.SetVertexColor(edge2Add.V2Id, mstColor); visualisator.Print($"Добавление к МОД смежного ребра минимального веса. " + $"Всего ребер {edgesMST.Count}. Общий вес {mstWeight}."); visualisator.PrintDataStructuresPrim(adjVertexSortLists, adjVertexSortListMST); await Task.Delay(SleepInterval); } if (edgesMST.Count != graph.Order - 1) { throw new Exception("Ошибка МОД не найдено"); } else { visualisator.Print( $"Минимальное остовное дерево построено. Общий вес {mstWeight}."); visualisator.ApEndLog( $"Минимальное остовное дерево построено. Общий вес {mstWeight}."); visualisator.PrintDataStructuresPrim(adjVertexSortLists, adjVertexSortListMST); } form.UnBlockTabControl(); }
public void Dispose() { list = null; currentNode = null; }
public AdjListEnumerator(AdjVertexSortedList list) { this.list = list; currentNode = list.Head; position = -1; }