149 lines
4.5 KiB
C#
149 lines
4.5 KiB
C#
|
using FLCompanionByDvurechensky.Data;
|
|||
|
using System.Collections.Generic;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// TODO: работает не корректно
|
|||
|
/// Алгоритм Дейкстры
|
|||
|
/// </summary>
|
|||
|
public class Dijkstra
|
|||
|
{
|
|||
|
Graph graph;
|
|||
|
|
|||
|
List<GraphVertexInfo> infos;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Конструктор
|
|||
|
/// </summary>
|
|||
|
/// <param name="graph">Граф</param>
|
|||
|
public Dijkstra(Graph graph)
|
|||
|
{
|
|||
|
this.graph = graph;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Инициализация информации
|
|||
|
/// </summary>
|
|||
|
void InitInfo()
|
|||
|
{
|
|||
|
infos = new List<GraphVertexInfo>();
|
|||
|
foreach (var v in graph.Vertices)
|
|||
|
{
|
|||
|
infos.Add(new GraphVertexInfo(v));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Получение информации о вершине графа
|
|||
|
/// </summary>
|
|||
|
/// <param name="v">Вершина</param>
|
|||
|
/// <returns>Информация о вершине</returns>
|
|||
|
GraphVertexInfo GetVertexInfo(GraphVertex v)
|
|||
|
{
|
|||
|
if (v == null) return null;
|
|||
|
|
|||
|
foreach (var i in infos)
|
|||
|
{
|
|||
|
if (i.Vertex.Name.Contains(v.Name))
|
|||
|
{
|
|||
|
return i;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Поиск непосещенной вершины с минимальным значением суммы
|
|||
|
/// </summary>
|
|||
|
/// <returns>Информация о вершине</returns>
|
|||
|
public GraphVertexInfo FindUnvisitedVertexWithMinSum()
|
|||
|
{
|
|||
|
var minValue = int.MaxValue;
|
|||
|
GraphVertexInfo minVertexInfo = null;
|
|||
|
foreach (var i in infos)
|
|||
|
{
|
|||
|
if (i.IsUnvisited && i.EdgesWeightSum < minValue)
|
|||
|
{
|
|||
|
minVertexInfo = i;
|
|||
|
minValue = i.EdgesWeightSum;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return minVertexInfo;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Поиск кратчайшего пути по названиям вершин
|
|||
|
/// </summary>
|
|||
|
/// <param name="startName">Название стартовой вершины</param>
|
|||
|
/// <param name="finishName">Название финишной вершины</param>
|
|||
|
/// <returns>Кратчайший путь</returns>
|
|||
|
public string FindShortestPath(string startName, string finishName)
|
|||
|
{
|
|||
|
return FindShortestPath(graph.FindVertex(startName), graph.FindVertex(finishName));
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Поиск кратчайшего пути по вершинам
|
|||
|
/// </summary>
|
|||
|
/// <param name="startVertex">Стартовая вершина</param>
|
|||
|
/// <param name="finishVertex">Финишная вершина</param>
|
|||
|
/// <returns>Кратчайший путь</returns>
|
|||
|
public string FindShortestPath(GraphVertex startVertex, GraphVertex finishVertex)
|
|||
|
{
|
|||
|
InitInfo();
|
|||
|
var first = GetVertexInfo(startVertex);
|
|||
|
first.EdgesWeightSum = 0;
|
|||
|
while (true)
|
|||
|
{
|
|||
|
var current = FindUnvisitedVertexWithMinSum();
|
|||
|
if (current == null)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
SetSumToNextVertex(current);
|
|||
|
}
|
|||
|
|
|||
|
return GetPath(startVertex, finishVertex);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Вычисление суммы весов ребер для следующей вершины
|
|||
|
/// </summary>
|
|||
|
/// <param name="info">Информация о текущей вершине</param>
|
|||
|
void SetSumToNextVertex(GraphVertexInfo info)
|
|||
|
{
|
|||
|
info.IsUnvisited = false;
|
|||
|
foreach (var e in info.Vertex.Edges)
|
|||
|
{
|
|||
|
var nextInfo = GetVertexInfo(e.ConnectedVertex);
|
|||
|
var sum = info.EdgesWeightSum + e.EdgeWeight;
|
|||
|
if (sum < nextInfo.EdgesWeightSum)
|
|||
|
{
|
|||
|
nextInfo.EdgesWeightSum = sum;
|
|||
|
nextInfo.PreviousVertex = info.Vertex;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Формирование пути
|
|||
|
/// </summary>
|
|||
|
/// <param name="startVertex">Начальная вершина</param>
|
|||
|
/// <param name="endVertex">Конечная вершина</param>
|
|||
|
/// <returns>Путь</returns>
|
|||
|
string GetPath(GraphVertex startVertex, GraphVertex endVertex)
|
|||
|
{
|
|||
|
var path = endVertex.ToString();
|
|||
|
while (startVertex != endVertex)
|
|||
|
{
|
|||
|
if(endVertex == null) return path;
|
|||
|
endVertex = GetVertexInfo(endVertex).PreviousVertex;
|
|||
|
if(endVertex != null)
|
|||
|
path = endVertex.ToString() + " = " + path;
|
|||
|
}
|
|||
|
|
|||
|
return path;
|
|||
|
}
|
|||
|
}
|