C# 迪杰斯特拉算法 Dijkstra

什么也不想说,现在直接上封装的方法:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;

namespace 算法
{
    /// <summary>
    /// Dijkstra
    /// 迪杰斯特拉算法
    /// </summary>
    public class Dijkstra : ICloneable
    {

        /// <summary>节点集合</summary>
        public ConcurrentDictionary<String, Node> LN { get; set; }

        /// <summary>开始节点</summary>
        public Node StartNode { get; set; }

        /// <summary>结束节点</summary>
        public Node EndNode { get; set; }

        /// <summary>Dijkstra构造函数</summary>
        /// <param name="list">节点集合</param>
        /// <param name="start">开始节点</param>
        /// <param name="end">结束节点</param>
        public Dijkstra(ConcurrentDictionary<String, Node> list, String start, String end)
        {
            LN = list;
            Init(start, end);
        }

        /// <summary>Dijkstra构造函数</summary>
        /// <param name="list">节点集合</param>
        /// <param name="start">开始节点</param>
        /// <param name="end">结束节点</param>
        public Dijkstra(IEnumerable<Map> list, String start, String end)
        {
            LN = InitNode(list);
            Init(start, end);
        }

        /// <summary>查找最短路径</summary>
        public bool Find()
        {
            return FindMin(new List<Node> { StartNode }, EndNode);
        }

        /// <summary>初始化</summary>
        private void Init(String start, String end)
        {
            StartNode = LN[start];
            EndNode = LN[end];
            if (StartNode == null || EndNode == null)
            {
                throw new ArgumentNullException();//空异常
            }
            StartNode.SetRank(null);
            StartNode.IsFind = true;

            InitRank(new List<Node> { StartNode });
        }

        /// <summary>初始化点阵的Rank </summary>
        /// <param name="srcs">节点集合</param>
        private void InitRank(IEnumerable<Node> srcs)
        {
            var nextNode = new List<Node>();
            foreach (var node in srcs)
            {
                foreach (var edge in node.LE)
                {
                    edge.CurrentNode.SetRank(node);
                    if (edge.CurrentNode.Rank == (node.Rank + 1) && !nextNode.Contains(edge.CurrentNode))
                        nextNode.Add(edge.CurrentNode);
                }
            }
            if (nextNode.Count > 0) InitRank(nextNode);
        }

        /// <summary>查找</summary>
        /// <param name="srcs">开始结点集合</param>
        /// <param name="dest">结束节点</param>
        private bool FindMin(List<Node> srcs, Node dest)
        {
            dest.GetRank();
            var minLen = 0;
            var isFind = false;
            var nextNodes = new List<Node>();
            string tmpPath;
            foreach (var node in srcs)
            {
                if (node.Equals(dest)) return false;
                foreach (var edge in node.LE)
                {
                    var tempDestRank = edge.CurrentNode.Rank;
                    if (tempDestRank != (node.Rank + 1)) continue;

                    if (!nextNodes.Contains(edge.CurrentNode))
                    {
                        nextNodes.Add(edge.CurrentNode);
                    }
                    edge.CurrentNode.MinDistance = node.MinDistance + edge.Weight;
                    if (!edge.CurrentNode.Equals(dest)) continue;

                    minLen = node.MinDistance + edge.Weight;
                    isFind = true;
                    break;
                }
            }

            if (isFind)
            {
                foreach (var node in srcs)
                {
                    tmpPath = FindMinx(node, dest, node.MinDistance, node.Rank, "", ref minLen);
                    if (tmpPath == "") continue;
                    dest.Path = node.Path + tmpPath;
                    dest.MinDistance = minLen;
                }
            }
            else
            {
                foreach (var next in nextNodes)
                {
                    minLen = -1;
                    foreach (var node in srcs)
                    {
                        if (minLen == -1) minLen = next.MinDistance;
                        tmpPath = FindMinx(node, next, node.MinDistance, node.Rank, "", ref minLen);
                        if (tmpPath == "") continue;
                        next.Path = node.Path + tmpPath;
                        next.MinDistance = minLen;
                    }
                }
                if (nextNodes.Count == 0) return false;
                FindMin(nextNodes, dest);
            }

            return isFind;
        }

        /// <summary>
        /// 寻找起始节点到目标节点的最小路径,此处采用递归查找。目标节点固定,起始节点递归。
        /// </summary>
        /// <param name="src">起始节点,为临时递归节点</param>
        /// <param name="dest">查找路径中的目标节点</param>
        /// <param name="minx">当前查找最小路径值,此值在递归中共享</param>
        /// <param name="startDist">当前节点以src节点的距离</param>
        /// <param name="srcRank">源节点src的级别</param>
        /// <param name="path">查找中经过的路径</param>
        private string FindMinx(Node src, Node dest, int startDist, int srcRank, string path, ref int minx)
        {
            var goalPath = "";
            var tmpPath1 = "," + path + ",";
            var tmpPath2 = "," + src.Path + ",";
            foreach (var node in src.LE)
            {
                string tmpPath = path;
                node.CurrentNode.SetRank(src);
                var tmpRank = node.CurrentNode.Rank;
                var tmpNodeName = "," + node.CurrentNode.Name + ",";
                //扩散级别大于等于目标级别并且是未走过的节点。
                if (tmpRank <= srcRank || tmpPath1.IndexOf(tmpNodeName, StringComparison.Ordinal) != -1 ||
                    tmpPath2.IndexOf(tmpNodeName, StringComparison.Ordinal) != -1) continue;
                var tmpLength = node.Weight + startDist;
                if (node.CurrentNode.Equals(dest))
                {
                    if (minx > tmpLength)
                    {
                        minx = tmpLength;
                        tmpPath += "," + node.CurrentNode.Name;
                        goalPath = tmpPath;
                    }
                    else if (minx == tmpLength)
                    {
                        tmpPath += "," + node.CurrentNode.Name;
                        goalPath = tmpPath;
                    }
                }
                else
                {
                    if (tmpLength >= minx) continue;
                    //路程小于最小值,查询下个子节点
                    tmpPath += "," + node.CurrentNode.Name;
                    tmpPath = FindMinx(node.CurrentNode, dest, tmpLength, srcRank, tmpPath, ref minx);
                    if (tmpPath != "")
                        goalPath = tmpPath;
                }
            }
            return goalPath;
        }

        /// <summary>初始化图</summary>
        /// <param name="list">图点集合</param>
        private ConcurrentDictionary<String, Node> InitNode(IEnumerable<Map> list)
        {
            var node = new ConcurrentDictionary<String, Node>();

            foreach (var item in list)
            {
                Node n1;
                Node n2;
                if (!node.ContainsKey(item.N1))
                {
                    n1 = new Node(item.N1);
                    node.TryAdd(item.N1, n1);
                }
                else
                {
                    n1 = node[item.N1];
                }
                if (!node.ContainsKey(item.N2))
                {
                    n2 = new Node(item.N2);
                    node.TryAdd(item.N2, n2);
                }
                else
                {
                    n2 = node[item.N2];
                }
                n1.LE.Add(new Edge(item.N2, item.Weight, n2));
            }
            return node;
        }

        #region 拷贝
        public object Clone()
        {
            return MemberwiseClone();
        }

        /// <summary>浅拷贝</summary>
        public Dijkstra CloneEntity()
        {
            return Clone() as Dijkstra;
        }
        #endregion
    }

    /// <summary>
    /// 节点
    /// </summary>
    public class Node : ICloneable
    {
        /// <summary>节点名称</summary>
        public String Name { get; set; }

        /// <summary>节点边集合</summary>
        public List<Edge> LE { get; set; }

        /// <summary>节点级别</summary>
        public Int32 Rank { get; set; }

        /// <summary>最短距离</summary>
        public Int32 MinDistance { get; set; }

        /// <summary>路径</summary>
        public String Path { get; set; }

        /// <summary>查询标识</summary>
        public bool IsFind { get; set; }

        public Node(String name)
        {
            Name = name;
            IsFind = false;
            Rank = -1;
            MinDistance = 0;
            LE = new List<Edge>();
        }

        /// <summary>设置节点级别</summary>
        /// <param name="parentNode">父节点</param>
        public void SetRank(Node parentNode)
        {
            if (Rank != -1) return;

            Rank = parentNode != null ? parentNode.Rank + 1 : 0;
        }

        /// <summary>获取节点级别</summary>
        public Int32 GetRank()
        {
            return Rank;
        }

        #region 拷贝
        public object Clone()
        {
            return MemberwiseClone();
        }

        /// <summary>浅拷贝</summary>
        public Node CloneEntity()
        {
            return Clone() as Node;
        }
        #endregion
    }

    /// <summary>
    /// 节点边
    /// </summary>
    public class Edge : ICloneable
    {
        /// <summary>边名称</summary>
        public String Name { get; set; }

        /// <summary>权值,代价 ,距离</summary>
        public Int32 Weight { get; set; }

        /// <summary>当前向量终点节点</summary>
        public Node CurrentNode { get; set; }

        public Edge(String name, Int32 weight, Node node)
        {
            Name = name;
            Weight = weight;
            CurrentNode = node;
        }

        /// <summary>设置当前节点</summary>
        /// <param name="node">当前向量终点节点</param>
        public void SetCurrentNode(Node node)
        {
            CurrentNode = node;
        }

        #region 拷贝
        public object Clone()
        {
            return MemberwiseClone();
        }

        /// <summary>浅拷贝</summary>
        public Edge CloneEntity()
        {
            return Clone() as Edge;
        }
        #endregion

    }

    /// <summary>图型</summary>
    public class Map : ICloneable
    {
        /// <summary>节点1</summary>
        public string N1 { get; set; }

        /// <summary>节点2</summary>
        public string N2 { get; set; }

        /// <summary>权值,代价 ,距离</summary>
        public int Weight { get; set; }

        public Map()
        {
        }

        public Map(string n1, string n2, int weight)
        {
            N1 = n1;
            N2 = n2;
            Weight = weight;
        }

        #region 拷贝
        public object Clone()
        {
            return MemberwiseClone();
        }

        /// <summary>浅拷贝</summary>
        public Map CloneEntity()
        {
            return Clone() as Map;
        }
        #endregion

    }

}

用法:

private IEnumerable<Map> InitMap()
        {
            var list = new List<Map>
            {
                new Map("A", "B", 3),
                new Map("A", "C", 5),
                new Map("A", "D", 2),
                new Map("B", "A", 3),
                new Map("B", "C", 4),
                new Map("B", "E", 10),
                new Map("C", "A", 5),
                new Map("C", "B", 4),
                new Map("C", "D", 2),
                new Map("C", "F", 1),
                new Map("C", "G", 6),
                new Map("D", "A", 2),
                new Map("D", "C", 2),
                new Map("D", "H", 3),
                new Map("E", "B", 10),
                new Map("E", "F", 4),
                new Map("E", "I", 2),
                new Map("F", "C", 1),
                new Map("F", "E", 4),
                new Map("F", "K", 8),
                new Map("F", "L", 2),
                new Map("G", "C", 6),
                new Map("G", "H", 8),
                new Map("G", "L", 2),
                new Map("H", "D", 3),
                new Map("H", "G", 8),
                new Map("I", "E", 2),
                new Map("I", "K", 6),
                new Map("I", "J", 1),
                new Map("J", "I", 1),
                new Map("J", "K", 9),
                new Map("K", "J", 9),
                new Map("K", "I", 6),
                new Map("K", "F", 8),
                new Map("K", "L", 5),
                new Map("L", "K", 5),
                new Map("L", "F", 2),
                new Map("L", "G", 2)
            };
            return list;
        }

void 调用(){

var dij = new Dijkstra(InitMap(), start, end);
dij.Find();
var _path = string.Format("最短距离:{0} 路径:{1}{2}  总耗时:{3} 毫秒 \r\n", dij.EndNode.MinDistance, start,  dij.EndNode.Path, sw.ElapsedMilliseconds); //在界面显示结果

}
时间: 2024-10-11 00:32:00

C# 迪杰斯特拉算法 Dijkstra的相关文章

迪杰斯特拉算法(Dijkstra) (基础dij+堆优化) BY:优少

首先来一段百度百科压压惊... 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题.迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 让我来翻译一下:Dijkstra可以求出一个点到一个图中其他所有节点的最短路径,故也称对于单源最短路径的一种解法 算法实现步骤: a.初始时,只包括源点,即S = {v},v的距离为0.U包含除v以外的其他顶点,即

算法--迪杰斯特拉算法 Dijkstra

https: //www.bilibili.com/video/av47427754?from=search&seid=10869921304007190819 import java.util.*; public class djstl { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); // n个点 m条边 x为开始点 如1到6 1为开始点

十大基础实用算法之迪杰斯特拉算法、最小生成树和搜索算法

迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算). 此外,引进两个集合S和U.S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离). 初始时,S中只有起点s:U中是除s之外的顶点,并且U中顶点的路径是"起点s

普里姆算法,克鲁斯卡尔算法,迪杰斯特拉算法,弗洛里德算法

做数据结构的课程设计顺便总结一下这四大算法,本人小白学生一枚, 如果总结的有什么错误,希望能够告知指正 普里姆算法如图所示prim 找出最短的边,再以这条边构成的整体去寻找与之相邻的边,直至连接所有顶点,生成最小生成树,时间复杂度为O(n2) 克鲁斯卡尔算法如图所示kruskal 克鲁斯卡尔算法,假设连通网N=(N,{E}),则令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{}),图中每个顶点 自成一个连通分量.在E中选择代价最小的边,若该边依附的定顶点落在T中不同的连通分量上,

最短路径算法——迪杰斯特拉算法(Dijkstra)

图结构中应用的最多的就是最短路径的查找了,关于最短路径查找的算法主要有两种:迪杰斯特拉算法(Dijkstra)和Floyd算法. 其中迪杰斯特拉算法(Dijkstra)实现如下: 原理就是不断寻找当前的最优解: void main() { int V[Max][Max]={0,8,32,Infinity,Infinity, 12,0,16,15,Infinity, Infinity,29,0,Infinity,13, Infinity,21,Infinity,0,7, Infinity,Infi

最短路径之迪杰斯特拉(Dijkstra)算法

对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点为源点,最后一个顶点为终点.最短路径的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd)算法.本文先来讲第一种,从某个源点到其余各顶点的最短路径问题. 这是一个按路径长度递增的次序产生最短路径的算法,它的大致思路是这样的. 初始时,S中仅含有源.设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度.D

迪杰斯特拉(dijkstra)算法的简要理解和c语言实现(源码)

迪杰斯特拉(dijkstra)算法:求最短路径的算法,数据结构课程中学习的内容. 1 . 理解 算法思想::设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将 加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中.在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v

[小明学算法]4.Dijkstra(迪杰斯特拉)算法

1.定义概念 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.值得注意的是,该算法要求图中不存在负权边. 2.基本思想 设置顶点集合S,初始时,S中仅含有起始点,把从起始点到u且中间只经过S中顶点的路称为从起始点到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径的长度.Dijkstra算法每次从S外取出对应dist值最小的节点u,将其添加到S中,并对所有与u点直接相连

算法-迪杰斯特拉算法(dijkstra)-最短路径

迪杰斯特拉算法(dijkstra)-最短路径 简介: 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 算法思想: 设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中