最短路徑之Dijkstra演算法

何畢之發表於2018-06-11
using System;

namespace Dijkstra演算法
{
    class Program
    {

        public static readonly int M = -1;//表示不可到達距離

        static int[,] map = new int[,] {
                { 0, 6, 3, M,M,M },
                { 6, 0, 2, 5,M,M },
                { 3, 2, 0, 3, 4, M },
                { M, 5, 3, 0, 2, 3 },
                { M,M, 4, 2, 0, 5 },
                { M,M,M, 3, 5, 0 }
            };//路徑圖

        static int places = (int)Math.Sqrt(map.Length);//獲取地點數;
        static int[] shortest = new int[places];  //存放從start到其他節點的最短路徑  
        static Boolean[] visited = new Boolean[places]; //標記當前該頂點的最短路徑是否已經求出,true表示已經求出 
        static string[] path = new string[places];//記錄路徑
        static int[] map2 = new int[places];//記錄A的連線情況


        static void Main(string[] args)
        {
            DisplayMap();
            Console.WriteLine();
            Console.WriteLine();

            int start = 0; //起始點  

            for (int i = 0; i < places; i++)
                map2[i] = map[0, i];
            dijkstra_alg(start);

            if (shortest == null)
            {
                return;
            }

            for (int i = 0; i < places; i++)
            {
                string res = displayResult(i);
                res=res.Replace("--","-");
                if (res[res.Length - 1] == '-')
                    res = res.Remove(res.Length - 1);
                Console.WriteLine(res + " ; 最短距離為:" + shortest[i]);
            }

            Console.ReadKey();
        }
        /// <summary>
        /// 輸出路徑
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public static string displayResult(int index)
        {
            string str = path[index];
            int num = (int)Enum.Parse(typeof(Place), (str.Replace("-", "")[0]).ToString());
            if (map2[index] != M)
                return path[num] + str.Remove(0, 1);
            else
                return displayResult(num) + str.Remove(0, 1);
        }

        /// <summary>
        /// 表示A-E六個地點
        /// </summary>
        public enum Place
        {
            A = 0,
            B = 1,
            C = 2,
            D = 3,
            E = 4,
            F = 5
        }

        /// <summary>
        /// 將原矩陣顯示
        /// </summary>
        public static void DisplayMap()
        {
            Console.Write("    ");
            for (int i = 0; i < places; i++)
            {
                Console.Write((Place)i + "   ");
            }
            Console.Write("\r\n");
            for (int i = 0; i < places; i++)
            {
                Console.Write((Place)i + "   ");
                for (int j = 0; j < places; j++)
                {
                    if (map[i, j] < 0)
                        Console.Write(map[i, j] + "  ");
                    else
                        Console.Write(map[i, j] + "   ");
                }
                Console.Write("\r\n");
            }
        }

        private static void dijkstra_alg(int start)
        {
            //初始化源點到其他各個地點的最短路徑長度
            for (int i = 0; i < places; i++)
            {
                shortest[i] = map[start, i];
                visited[i] = false;
                //如果和起點相鄰則新增路徑
                if (map[start, i] != M)
                    path[i] = "A" + '-';
            }
            // TODO Auto-generated method stub  
            // 初始化,第一個頂點求出  
            shortest[start] = 0;
            visited[start] = true;
            for (int count = 0; count != places - 1; count++)
            {
                //選出一個距離初始頂點最近的為標記頂點  
                int k = start;
                int min = M;
                for (int i = 0; i < places; i++)//遍歷每一個頂點  
                {
                    if (!visited[i] && map[start, i] != M) //如果該頂點未被遍歷過且與start相連  
                    {
                        if (min == M || min > map[start, i]) //找到與start最近的點  
                        {
                            min = map[start, i];
                            k = i;
                            //新增路徑
                            if (path[i] != null)
                                if (path[i].IndexOf(((Place)i).ToString()) < 0)
                                    path[i] += (Place)i + "-";
                                else { }
                            else
                                path[i] = (Place)i + "-";
                        }
                    }
                }
                //正確的圖生成的矩陣不可能出現K== M的情況  
                if (k == M)
                {
                    Console.WriteLine("the input map matrix is wrong!");
                    return;
                }
                shortest[k] = min;
                visited[k] = true;
                //以k為中心點,更新start到未訪問點的距離  
                for (int i = 0; i < places; i++)
                {
                    if (!visited[i] && map[k, i] != M)
                    {
                        int callen = min + map[k, i];
                        if (map[start, i] == M || map[start, i] > callen)
                        {
                            //新增或者更新路徑
                            if (path[i] != null)
                                if (path[i].IndexOf(((Place)i).ToString()) > 0)
                                    path[i] = path[i].Remove(path[i].Length - 3, 2);
                            path[i] += (Place)k + "-" + (Place)i + "-";
                            //更新最短距離
                            map[start, i] = callen;
                        }
                    }
                }
            }

        }

    }
}



相關文章