|
@@ -0,0 +1,144 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Linq;
|
|
|
+using System.Text;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+namespace Djikstra
|
|
|
+{
|
|
|
+ class Path
|
|
|
+ {
|
|
|
+ public string Name;
|
|
|
+ public int Cost;
|
|
|
+ public bool Visited;
|
|
|
+
|
|
|
+ public Path(string name, int cost, bool visited)
|
|
|
+ {
|
|
|
+ Name = name;
|
|
|
+ Cost = cost;
|
|
|
+ Visited = visited;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ class MemoTable
|
|
|
+ {
|
|
|
+ private List<Path> Table;
|
|
|
+ public Path S;
|
|
|
+
|
|
|
+ public MemoTable(string[] vertices)
|
|
|
+ {
|
|
|
+ S = new Path("S", 0, false);
|
|
|
+ Table = new List<Path>() {S};
|
|
|
+
|
|
|
+ foreach (var vertex in vertices)
|
|
|
+ {
|
|
|
+ Table.Add(new Path(vertex, int.MaxValue, false));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<Path> GetCandidateVertices()
|
|
|
+ {
|
|
|
+ return Table.Where(x => !x.Visited).ToList();
|
|
|
+ }
|
|
|
+
|
|
|
+ public Path NextVertex()
|
|
|
+ {
|
|
|
+ List<Path> candidates = GetCandidateVertices();
|
|
|
+
|
|
|
+ if (candidates.Any())
|
|
|
+ {
|
|
|
+ return candidates.OrderBy(x => x.Cost).First();
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Path GetEntry(string vertex) => Table.First(x => x.Name == vertex);
|
|
|
+
|
|
|
+ private void SetCurrentCost(string vertex, int cost)
|
|
|
+ {
|
|
|
+ GetEntry(vertex).Cost = cost;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void SetAsVisited(string vertex)
|
|
|
+ {
|
|
|
+ GetEntry(vertex).Visited = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int GetCost(string vertex)
|
|
|
+ {
|
|
|
+ return GetEntry(vertex).Cost;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Evaluate(List<GraphItem> graph, Path vertex)
|
|
|
+ {
|
|
|
+ GraphItem[] edges = graph.Where(x => x.From == vertex.Name).ToArray();
|
|
|
+ foreach (var edge in edges)
|
|
|
+ {
|
|
|
+ int currentVertexCost = GetCost(edge.From);
|
|
|
+ int toVertexCost = GetCost(edge.To);
|
|
|
+ int tentativeCost = currentVertexCost == int.MaxValue ? int.MaxValue : currentVertexCost + edge.Cost;
|
|
|
+ if (tentativeCost < toVertexCost)
|
|
|
+ SetCurrentCost(edge.To, tentativeCost);
|
|
|
+ }
|
|
|
+ SetAsVisited(vertex.Name);
|
|
|
+
|
|
|
+ Path next = NextVertex();
|
|
|
+ if (next != null)
|
|
|
+ Evaluate(graph, next);
|
|
|
+ }
|
|
|
+
|
|
|
+ public override string ToString()
|
|
|
+ {
|
|
|
+ StringBuilder buffer = new StringBuilder();
|
|
|
+ foreach (var element in Table)
|
|
|
+ {
|
|
|
+ buffer.AppendLine($"name: {element.Name}, cost: {element.Cost}, visited: {element.Visited}");
|
|
|
+ }
|
|
|
+ return buffer.ToString();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ class GraphItem
|
|
|
+ {
|
|
|
+ public string From;
|
|
|
+ public string To;
|
|
|
+ public int Cost;
|
|
|
+
|
|
|
+ public GraphItem(string from, string to, int cost)
|
|
|
+ {
|
|
|
+ From = from;
|
|
|
+ To = to;
|
|
|
+ Cost = cost;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ class Program
|
|
|
+ {
|
|
|
+ static string[] vertices = { "A", "B", "C", "D", "E" };
|
|
|
+
|
|
|
+ static List<GraphItem> graph = new List<GraphItem>()
|
|
|
+ {
|
|
|
+ new GraphItem("S", "A", 4),
|
|
|
+ new GraphItem("S", "E", 2),
|
|
|
+ new GraphItem("A", "D", 3),
|
|
|
+ new GraphItem("A", "C", 6),
|
|
|
+ new GraphItem("A", "B", 5),
|
|
|
+ new GraphItem("B", "A", 3),
|
|
|
+ new GraphItem("C", "B", 1),
|
|
|
+ new GraphItem("D", "C", 3),
|
|
|
+ new GraphItem("D", "A", 1),
|
|
|
+ new GraphItem("E", "D", 1)
|
|
|
+ };
|
|
|
+
|
|
|
+ static void Main()
|
|
|
+ {
|
|
|
+ MemoTable memo = new MemoTable(vertices);
|
|
|
+
|
|
|
+ memo.Evaluate(graph, memo.S);
|
|
|
+
|
|
|
+ Console.WriteLine(memo.ToString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|