單源最短路徑演算法(Dijkstra演算法)

來源:互聯網
上載者:User
1、圖形相關類(前面有個,但這裡增加了一些屬性)
 /// <summary>    /// 圖類,由節點和邊構成.    /// </summary>    public class Graphic    {        /// <summary>        /// 用於圖形訪問臨時公開變數        /// </summary>        public int FinishOrder { get; set; }        /// <summary>        /// 用於圖形訪問臨時公開變數        /// </summary>        public int EnterOrder { get; set; }        public List<Node> Nodes { get; set; }        public List<Edge> Edges { get; set; }        public Graphic()        {            Nodes = new List<Node>();            Edges = new List<Edge>();        }        public void Add(Node Node)        {            if (this.Nodes.IndexOf(Node) < 0)            {                this.Nodes.Add(Node);            }        }        public void Add(Edge Edge)        {            if (this.Edges.IndexOf(Edge) < 0)            {                this.Edges.Add(Edge);            }        }        public void ResetTempAdjNodes()        {            foreach (var theNode in this.Nodes)            {                theNode.ResetTempAdjNodes();            }        }    }    /// <summary>    /// 樹類,包括節點和邊構成    /// </summary>    public class Tree    {        public List<Node> Nodes { get; set; }        public List<Edge> Edges { get; set; }        public Tree()        {            Nodes = new List<Node>();            Edges = new List<Edge>();        }        public void Add(Node Node)        {            if (this.Nodes.IndexOf(Node) < 0)            {                this.Nodes.Add(Node);            }        }        public void Add(Edge Edge)        {            if (this.Edges.IndexOf(Edge) < 0)            {                this.Edges.Add(Edge);            }        }    }    /// <summary>    /// 節點類    /// </summary>    public class Node    {        public string Symbol { get; set; }        public Node Parent { get; set; }        /// <summary>        /// 用於演算法臨時存放,一般為key值.        /// </summary>        public double TempVal { get; set; }        public int VisitedSign { get; set; }        /// <summary>        /// 用於演算法臨時存放        /// </summary>        public Edge TempEdge { get; set; }        /// <summary>        /// 鄰接節點        /// </summary>        public Dictionary<Node, Edge> AdjNodes;        /// <summary>        /// 臨時鄰接節點,用於計算中補破壞原圖結構.        /// </summary>        public Dictionary<Node, Edge> TempAdjNodes;        public Node(string Symbol)        {            this.Symbol = Symbol;            AdjNodes = new Dictionary<Node, Edge>();            TempAdjNodes = new Dictionary<Node, Edge>();        }        /// <summary>        /// 同步臨時鄰接節點集合值.        /// </summary>        public void ResetTempAdjNodes()        {            TempAdjNodes.Clear();            foreach (var theDictItem in AdjNodes)            {                TempAdjNodes.Add(theDictItem.Key, theDictItem.Value);                theDictItem.Value.ResetTempWeight();            }        }        /// <summary>        /// 用於深度搜尋標記        /// </summary>        public int EnterTime { get; set; }        /// <summary>        /// 用於深度搜尋標記        /// </summary>        public int FinishTime { get; set; }        public int FinishOrder { get; set; }        public int EnterOrder { get; set; }    }    /// <summary>    /// 邊類,包括兩個節點和權重.    /// </summary>    public class Edge    {        public Node Node1 { get; set; }        public Node Node2 { get; set; }        public double Weight { get; set; }        public double TempWeight { get; set; }        public int EdgeType { get; set; }        public Edge(Node N1, Node N2, double Weight)        {            this.Node1 = N1;            this.Node2 = N2;            this.Weight = Weight;        }        public void ResetTempWeight()        {            this.TempWeight = this.Weight;                    }    }

2、單源路徑基本操作

 public class SingleSourcePath    {        /// <summary>        /// 單源路徑中初始化圖的計算設定值        /// </summary>        /// <param name="g">要初始化的圖</param>        public void InitializeGraphic(Graphic g,Node s)        {            //Node節點的TempVal屬性存放最小路徑估計值,Parent屬性存放其父節點.            foreach (var theNode in g.Nodes)            {                theNode.TempVal = double.MaxValue;                theNode.Parent = null;            }            s.Parent = null;            s.TempVal = 0;        }        /// <summary>        /// 單源路徑中初始化圖的計算設定值(矩陣標記法)        /// </summary>        /// <param name="Parents"></param>        /// <param name="Distance"></param>        /// <param name="n"></param>        /// <param name="s"></param>        public void InitializeGraphic(int[] Parents, double[] Distance,int n,int s)        {            for (int i = 0; i < n; i++)            {                Parents[i] = -1;                Distance[i] = double.PositiveInfinity;            }            Distance[s] = 0;        }        /// <summary>        /// 鬆弛技術        /// </summary>        /// <param name="GraphicMatrix">圖鄰接矩陣</param>        /// <param name="Parents">頂點父節點</param>        /// <param name="Distance">源點到其它節點的距離</param>        /// <param name="u">頂點</param>        /// <param name="v">頂點</param>        public void Relax(double[,] GraphicMatrix,int[] Parents,double[] Distance,int u,int v)        {            if (double.IsPositiveInfinity(Distance[u])==true)            {                return;            }            if (Distance[v] > Distance[u] + GraphicMatrix[u,v])            {                Distance[v] = Distance[u] + GraphicMatrix[u, v];                Parents[v] = u;            }        }        /// <summary>        /// 鬆弛邊Edge的兩個節點node1,node2.        /// </summary>        /// <param name="node1"></param>        /// <param name="node2"></param>        /// <param name="weight"></param>        public void Relax(Edge edge)        {            if (edge.Node1.TempVal == double.MaxValue)            {                return;            }            if (edge.Node2.TempVal > edge.Node1.TempVal + edge.Weight)            {                edge.Node2.TempVal = edge.Node1.TempVal + edge.Weight;                edge.Node2.Parent = edge.Node1;            }        }    }

3、Dijkstra演算法

public class KruskalAlg    {        public  Tree MST_Kruskal(Graphic g)        {            //為每個頂點建立一顆樹,僅包含一個頂點,做初始化            List<Tree> theTrees = new List<Tree>();            foreach (var theNode in g.Nodes)            {                Tree theTree_Tmp = new Tree();                theTree_Tmp.Add(theNode);                theTrees.Add(theTree_Tmp);            }            //對邊進行排序            var theEdgesQuery = from e in g.Edges                               orderby e.Weight                               select e;            var theSortEdges = theEdgesQuery.ToArray();            //剛開始最小產生樹為空白.            Tree theMST = new Tree();            //沒有採用foreach,以保證訪問按排序進行.            for(int i=0;i<theSortEdges.Count();i++)             {                var theEdge = theSortEdges[i];                //找theEdge邊的兩個點各自所在的樹.                Tree theTree1 = FindTreeByNode(theEdge.Node1, theTrees);                Tree theTree2 = FindTreeByNode(theEdge.Node2, theTrees);                //如果theEdge邊的兩個點各自所在的樹不相同,則將該邊選入最小產生樹,                //同時需要將兩個樹進行合并。                if (theTree1 != theTree2)                {                    theMST.Edges.Add(theEdge);                    theMST.Nodes.Add(theEdge.Node1);                    theMST.Nodes.Add(theEdge.Node2);                    UnionTreeInForest(theTree1, theTree2, theEdge, theTrees);                }            }            return theMST;        }        /// <summary>        /// 在森林中尋找某個節點所在的樹        /// </summary>        /// <param name="Node">要找的節點</param>        /// <param name="Forest">森林</param>        /// <returns></returns>        private  Tree FindTreeByNode(Node Node, List<Tree> Forest)        {            foreach (var theTree in Forest)            {                foreach (var theNode in theTree.Nodes)                {                    if (theNode.Symbol == Node.Symbol)                    {                        return theTree;                    }                }            }            return null;        }        /// <summary>        /// 在這個演算法中,邊是可以不用合并進來的.        /// </summary>        /// <param name="Tree1"></param>        /// <param name="Tree2"></param>        /// <param name="Edge"></param>        /// <param name="Forest"></param>        private  void UnionTreeInForest(Tree Tree1, Tree Tree2, Edge Edge, List<Tree> Forest)        {            Tree1.Nodes.AddRange(Tree2.Nodes);            Tree1.Edges.AddRange(Tree2.Edges);            Tree1.Edges.Add(Edge);            Forest.Remove(Tree2);        }    }

Dijkstra演算法的思路其實很樸實,就是如果兩棵樹的一條割邊是所有串連這兩棵樹的割邊中最小的邊,那麼這條邊一定在這兩棵樹組成的圖形中跨樹最短路徑中。通過不斷的合并樹最終形成一棵完整的最短路徑樹。當然,合并的法則是按邊權從小到大進行。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.