using RichCreator.Utility.Structs; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace RichCreator.Utility.PathFinding { public class Dijkstra { private List nodes; private List edges; public Dijkstra() { nodes = new List(); edges = new List(); } public Dijkstra(List> edges) { nodes = new List(); this.edges = new List(); InitEdge(edges); } public void InitEdge(List> edges) { this.edges = ConvertToEdge(edges); InitNodes(); } public List Find(ZTPoint start, ZTPoint end) { var startNode = GetNodeByName(start); var endNode = GetNodeByName(end); if (startNode == null || endNode == null) { return new List(); } var s = nodes.Where(x => x.Name == start).ToList(); var u = nodes.Where(x => x.Name != start).ToList(); s.ForEach(x => { x.Weight = 0; }); u.ForEach(x => { x.Weight = double.PositiveInfinity; }); while (u.Any()) { var node = s.Last(); //更新node到x的距离 u.ForEach(x => { var edge = GetEdgeByTwoNode(node, x); if (edge != null) { var weights = node.GetAllWeight() + edge.Weight; if (weights < x.Weight) { x.Weight = weights; x.Parent = node; } } }); //找出距离最小的 var minNode = u.OrderBy(x => x.Weight).FirstOrDefault(); s.Add(minNode); u.Remove(minNode); } var paths = new Stack(); while (endNode != null) { paths.Push(endNode.Name); endNode = endNode.Parent; } //如果路劲中包含起点 if (paths.ToList().Contains(start)) { return paths.ToList(); } else { return new List(); } } private Edge GetEdgeByTwoNode(Node start, Node end) { var edge = edges.FirstOrDefault(x => x.Start == start.Name && x.End == end.Name); if (edge == null) { edge = edges.FirstOrDefault(x => x.Start == end.Name && x.End == start.Name); } return edge; } /// /// 将权值转换成边 /// /// private List ConvertToEdge(List> weights) { var edges = new List(); weights.ForEach(weight => { edges.Add(new Edge() { Start = weight.Item1, End = weight.Item2, Weight = weight.Item3 }); }); return edges; } /// /// 根据名字获取节点 /// /// /// private Node GetNodeByName(ZTPoint nodeName) { return nodes.FirstOrDefault(x => x.Name == nodeName); } /// /// 初始化点 /// private void InitNodes() { edges.ForEach(edge => { if (nodes.All(x => x.Name != edge.Start)) { nodes.Add(new Node() { Name = edge.Start }); } if (nodes.All(x => x.Name != edge.End)) { nodes.Add(new Node() { Name = edge.End }); } }); } } }