using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace RichCreator.Utility.PathFinding { public class Dijkstra where T : IEquatable { private Dictionary> edges = new Dictionary>(); /// /// 添加顶点 /// /// 顶点名称 /// 顶点所有的边 public void AddEdge(T vertice, Dictionary targetVertice) { foreach (var item in targetVertice) { AddEdge(vertice, item.Key, item.Value); } } /// /// 添加顶点 /// /// 顶点名称 /// 可连接顶点 /// 权重 public void AddEdge(T vertice, T targetVertice, Int32 weight) { if (!this.edges.ContainsKey(vertice)) { this.edges.Add(vertice, new Dictionary()); } if (!this.edges[vertice].ContainsKey(targetVertice)) { this.edges[vertice].Add(targetVertice, weight); } if (!this.edges.ContainsKey(targetVertice)) { this.edges.Add(targetVertice, new Dictionary()); } if (!this.edges[targetVertice].ContainsKey(vertice)) { this.edges[targetVertice].Add(vertice, weight); } } /// /// 移除顶点 /// /// public void RemoveEdge(T name) { if (this.edges.ContainsKey(name)) { return; } this.edges.Remove(name); foreach (var item in this.edges) { if (item.Value.ContainsKey(name)) { item.Value.Remove(name); } } } /// /// 查找最短路径 /// /// /// /// public List ShortestPath(T start, T finish) { var previous = new Dictionary(); var distances = new Dictionary(); var nodes = new List(); List path = new List(); foreach (var vertex in edges) { if (vertex.Key.Equals(start)) { distances[vertex.Key] = 0; } else { distances[vertex.Key] = Int32.MaxValue; } nodes.Add(vertex.Key); } while (nodes.Count != 0) { nodes.Sort((x, y) => distances[x] - distances[y]); var smallest = nodes[0]; nodes.Remove(smallest); if (smallest.Equals(finish)) { while (previous.ContainsKey(smallest)) { path.Add(smallest); smallest = previous[smallest]; } //倒译排列 path.Reverse(); break; } if (distances[smallest] == Int32.MaxValue) { break; } foreach (var neighbor in edges[smallest]) { var alt = distances[smallest] + neighbor.Value; if (alt < distances[neighbor.Key]) { distances[neighbor.Key] = alt; previous[neighbor.Key] = smallest; } } } return path; } } }