DijkstraMethod.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. // Статический класс для алгоритма Дейкстры
  5. static public class DijkstraMethod
  6. {
  7. // Метод для решения
  8. static public Dictionary<Vertex, int> ApplyMethod(Graph graph, int startingVertexNumber)
  9. {
  10. // Находим изначальную вершину (откуда считаем расстояния)
  11. Vertex sourceVertex = graph.GetVertexByNumber(startingVertexNumber);
  12. if (sourceVertex == null)
  13. {
  14. return new Dictionary<Vertex, int>();
  15. }
  16. // Инициализируем словарь, в котором для каждой вершины будем хранить минимальные расстояния
  17. // Ключ - вершина (Vertex), значение - расстояние до этой вершины (от изначальной вершины)
  18. Dictionary<Vertex, int> distances = new Dictionary<Vertex, int>(); //ключ-значение
  19. // Для каждой вершины ставим расстояние на максимальное значение (бесконечность*)
  20. for (int i = 0; i < graph.Vertices.Count; i++)
  21. {
  22. distances.Add(graph.Vertices[i], int.MaxValue);
  23. }
  24. // Для исходной вершины ставим расстояние на 0
  25. distances[sourceVertex] = 0;
  26. // Список вершин, которые НАДО посетить
  27. List<(Vertex, int)> verticesToVisit = new List<(Vertex, int)>(); // List из Tuple(вершина, расстояние)
  28. // Кладем в список первую вершину - исходную вершину, расстояние = 0
  29. verticesToVisit.Add((sourceVertex, 0));
  30. // Основной цикл выполняется, пока список вершин для посещения не станет пустым
  31. while (verticesToVisit.Count != 0)
  32. {
  33. // Принимаем самую первую вершину в списке как вершину с минимальным расстоянием
  34. Vertex currentVertex = verticesToVisit[0].Item1;
  35. int currentVertexDistance = verticesToVisit[0].Item2;
  36. // Ищем вершину с минимальным расстоянием в списке verticesToVisit
  37. for (int i = 0; i < verticesToVisit.Count; i++)
  38. {
  39. if (verticesToVisit[i].Item2 < currentVertexDistance)
  40. {
  41. currentVertex = verticesToVisit[i].Item1;
  42. currentVertexDistance = verticesToVisit[i].Item2;
  43. }
  44. }
  45. // Найденную вершину удаляем из списка
  46. verticesToVisit.Remove((currentVertex, currentVertexDistance));
  47. // Если эта вершина уже была посещена, то пропускаем
  48. if (currentVertex.WasVisited)
  49. {
  50. continue;
  51. }
  52. // Отметить текущую вершину как посещенную
  53. currentVertex.Visit();
  54. // Исследуем все вершины, которые соединены с нашей текущей вершиной
  55. for (int i = 0; i < currentVertex.Edges.Count; i++)
  56. {
  57. // Целевая вершина текущего ребра (стороны)
  58. Vertex targetVertex = currentVertex.Edges[i].To; // edge.To -> куда ведет ребро
  59. // Если вершина уже была посещена, то пропускаем ее
  60. if (targetVertex.WasVisited)
  61. {
  62. continue;
  63. }
  64. // Высчитываем новое расстояние
  65. int distance = distances[currentVertex] + currentVertex.Edges[i].Distance;
  66. // Если новое расстояние меньше имеющегося, обновляем значение
  67. if (distance < distances[targetVertex])
  68. {
  69. // Обновляем расстояние
  70. distances[targetVertex] = distance;
  71. // Закидываем вершину в список с новым расстоянием
  72. verticesToVisit.Add((targetVertex, distance));
  73. }
  74. }
  75. }
  76. return distances;
  77. }
  78. static public void PrintSolution(Graph graph, int startingVertexNumber, Dictionary<Vertex, int> distances)
  79. {
  80. if (distances.Count != graph.Vertices.Count)
  81. {
  82. Console.WriteLine("Решение не было найдено.");
  83. Console.ReadKey();
  84. return;
  85. }
  86. Console.WriteLine($"\nИсходная вершина: {startingVertexNumber}");
  87. //Console.WriteLine($"Минимальные расстояния: {sourceId}");
  88. foreach (Vertex vertex in graph.Vertices)
  89. {
  90. if (distances[vertex] != int.MaxValue)
  91. {
  92. Console.WriteLine($"- из вершины {startingVertexNumber} в вершину {vertex.Number} минимальное расстояние равно {distances[vertex]}");
  93. }
  94. else
  95. {
  96. Console.WriteLine($"- из вершины {startingVertexNumber} в вершину {vertex.Number} нет пути, так как граф не является связным.");
  97. }
  98. }
  99. Console.ReadKey();
  100. }
  101. }