123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- // Статический класс для алгоритма Дейкстры
- static public class DijkstraMethod
- {
- // Метод для решения
- static public Dictionary<Vertex, int> ApplyMethod(Graph graph, int startingVertexNumber)
- {
- // Находим изначальную вершину (откуда считаем расстояния)
- Vertex sourceVertex = graph.GetVertexByNumber(startingVertexNumber);
- if (sourceVertex == null)
- {
- return new Dictionary<Vertex, int>();
- }
- // Инициализируем словарь, в котором для каждой вершины будем хранить минимальные расстояния
- // Ключ - вершина (Vertex), значение - расстояние до этой вершины (от изначальной вершины)
- Dictionary<Vertex, int> distances = new Dictionary<Vertex, int>(); //ключ-значение
- // Для каждой вершины ставим расстояние на максимальное значение (бесконечность*)
- for (int i = 0; i < graph.Vertices.Count; i++)
- {
- distances.Add(graph.Vertices[i], int.MaxValue);
- }
- // Для исходной вершины ставим расстояние на 0
- distances[sourceVertex] = 0;
- // Список вершин, которые НАДО посетить
- List<(Vertex, int)> verticesToVisit = new List<(Vertex, int)>(); // List из Tuple(вершина, расстояние)
- // Кладем в список первую вершину - исходную вершину, расстояние = 0
- verticesToVisit.Add((sourceVertex, 0));
- // Основной цикл выполняется, пока список вершин для посещения не станет пустым
- while (verticesToVisit.Count != 0)
- {
- // Принимаем самую первую вершину в списке как вершину с минимальным расстоянием
- Vertex currentVertex = verticesToVisit[0].Item1;
- int currentVertexDistance = verticesToVisit[0].Item2;
- // Ищем вершину с минимальным расстоянием в списке verticesToVisit
- for (int i = 0; i < verticesToVisit.Count; i++)
- {
- if (verticesToVisit[i].Item2 < currentVertexDistance)
- {
- currentVertex = verticesToVisit[i].Item1;
- currentVertexDistance = verticesToVisit[i].Item2;
- }
- }
- // Найденную вершину удаляем из списка
- verticesToVisit.Remove((currentVertex, currentVertexDistance));
- // Если эта вершина уже была посещена, то пропускаем
- if (currentVertex.WasVisited)
- {
- continue;
- }
- // Отметить текущую вершину как посещенную
- currentVertex.Visit();
- // Исследуем все вершины, которые соединены с нашей текущей вершиной
- for (int i = 0; i < currentVertex.Edges.Count; i++)
- {
- // Целевая вершина текущего ребра (стороны)
- Vertex targetVertex = currentVertex.Edges[i].To; // edge.To -> куда ведет ребро
- // Если вершина уже была посещена, то пропускаем ее
- if (targetVertex.WasVisited)
- {
- continue;
- }
- // Высчитываем новое расстояние
- int distance = distances[currentVertex] + currentVertex.Edges[i].Distance;
- // Если новое расстояние меньше имеющегося, обновляем значение
- if (distance < distances[targetVertex])
- {
- // Обновляем расстояние
- distances[targetVertex] = distance;
- // Закидываем вершину в список с новым расстоянием
- verticesToVisit.Add((targetVertex, distance));
- }
- }
- }
- return distances;
- }
- static public void PrintSolution(Graph graph, int startingVertexNumber, Dictionary<Vertex, int> distances)
- {
- if (distances.Count != graph.Vertices.Count)
- {
- Console.WriteLine("Решение не было найдено.");
- Console.ReadKey();
- return;
- }
- Console.WriteLine($"\nИсходная вершина: {startingVertexNumber}");
- //Console.WriteLine($"Минимальные расстояния: {sourceId}");
- foreach (Vertex vertex in graph.Vertices)
- {
- if (distances[vertex] != int.MaxValue)
- {
- Console.WriteLine($"- из вершины {startingVertexNumber} в вершину {vertex.Number} минимальное расстояние равно {distances[vertex]}");
- }
- else
- {
- Console.WriteLine($"- из вершины {startingVertexNumber} в вершину {vertex.Number} нет пути, так как граф не является связным.");
- }
- }
- Console.ReadKey();
- }
- }
|