狄克斯特拉 Dijkstra 演算法 C#實現
阿新 • • 發佈:2018-12-17
今天在看《演算法圖解》,看了加權最小路徑演算法,決定用程式碼實現一下。
首先是畫有向圖,在網上找了一下,有不錯的開源軟體graphviz,該原始碼託管在GitLab上。該軟體是一個圖形視覺化軟體。 畫了一個有向圖如下:
畫圖用的程式碼:
digraph dijkstra{
start->A[label="6"]
start->B[label="2"]
A->end[label="1"]
B->A[label="3"]
B->end[label="5"]
}
我建了一個控制檯應用程式:
class Program { public static List<Node> NodeList { get; set; } public static Dictionary<string,int> CostDictionary { get; set; } public static Dictionary<string, string> ParentDictionary { get; set; } public static List<string> CheckedNodeName { get; set; } public Program() { NodeList= new List<Node> { new Node { NodeName = "start", RelatedNode = new Dictionary<string, int>() { {"A", 6}, {"B", 2} } }, new Node { NodeName = "A", RelatedNode = new Dictionary<string, int>() { {"end", 1} } }, new Node { NodeName = "B", RelatedNode = new Dictionary<string, int>() { {"A", 3}, {"end", 5} } }, new Node { NodeName = "end", RelatedNode = new Dictionary<string, int>() } }; CostDictionary = new Dictionary<string,int>() { {"A",6}, {"B",2}, {"end",int.MaxValue} }; ParentDictionary = new Dictionary<string, string>() { {"A","start"}, {"B","start"}, {"end",""} }; CheckedNodeName=new List<string>(); } static void Main(string[] args) { var progra=new Program(); Console.WriteLine($"{"parent",10}|{"node",10}|{"cost",10}"); foreach ( var item in NodeList.SelectMany(node=>node.RelatedNode,(node,relatenode)=>new {node.NodeName,relatenode})) { Console.WriteLine($"{item.NodeName,10}|{item.relatenode.Key,10}|{item.relatenode.Value,10}"); } while (CheckedNodeName.Count!=CostDictionary.Count) { //找到Cost最小的節點 var currentNode = FindMinCostNode(CostDictionary); //取出relatednode, if (currentNode != null) { //迴圈如果subNode的Cost小於CostDictionary的Cost foreach (var subNode in currentNode.RelatedNode) { if (subNode.Value < CostDictionary[subNode.Key]) { //替換 CostDictionary[subNode.Key] = subNode.Value+ CostDictionary[currentNode.NodeName]; ParentDictionary[subNode.Key] = currentNode.NodeName; } } CheckedNodeName.Add(currentNode.NodeName); } } Console.WriteLine("最短路徑:"+ GetTheMinCostPath()); Console.WriteLine("最短路徑開銷:"+CostDictionary["end"]); Console.ReadKey(); } public static string GetTheMinCostPath() { bool isStart=false; string startKey="end"; string path= "end=>"; while (!isStart) { path += ParentDictionary[startKey]+"=>"; startKey = ParentDictionary[startKey]; if (!ParentDictionary.ContainsKey(ParentDictionary[startKey])) { path += ParentDictionary[startKey]; isStart = true; } } return path; } public static Node FindMinCostNode(Dictionary<string,int> costDictionary) { var costItems= costDictionary.Where(c => !CheckedNodeName.Contains(c.Key)).ToList(); if (costItems.Any()) { var minCostItem = costItems.OrderBy(c => c.Value).First().Key; return NodeList.FirstOrDefault(n => n.NodeName == minCostItem); } return null; } } public class Node { public string NodeName { get; set; } public Dictionary<string, int> RelatedNode { get; set; } } public class CostItem { public string ParentName { get; set; } public string NodeName { get; set; } public int Cost { get; set; } }