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

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); //在界面显示结果 }

友情连接

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

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

    首先来一段百度百科压压惊... 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最 ...

  2. 图->最短路径->单源最短路径(迪杰斯特拉算法Dijkstra)

    文字描述 引言:如下图一个交通系统,从A城到B城,有些旅客可能关心途中中转次数最少的路线,有些旅客更关心的是节省交通费用,而对于司机,里程和速度则是更感兴趣的信息.上面这些问题,都可以转化为求图中,两 ...

  3. 迪杰斯特拉算法dijkstra(可打印最短路径)

    #include <iostream> #include <iomanip> #include <string> using namespace std; #def ...

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

    迪杰斯特拉(dijkstra)算法:求最短路径的算法,数据结构课程中学习的内容. 1 . 理解 算法思想::设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合 ...

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

    迪杰斯特拉(Dijkstra)算法主要是针对没有负值的有向图,求解其中的单一起点到其他顶点的最短路径算法.本文主要总结迪杰斯特拉(Dijkstra)算法的原理和算法流程,最后通过程序实现在一个带权值的 ...

  6. dijkstra算法(迪杰斯特拉算法)

    dijkstra算法(迪杰斯特拉算法) 用途:有向图最短路径问题 定义:迪杰斯特拉算法是典型的算法,一般的表述通常有两种方式,这里均采用永久和临时标号的方式,该算法要求图中不存在负权边 用永久和临时标 ...

  7. 理解最短路径——迪杰斯特拉(dijkstra)算法

    原址地址:http://ibupu.link/?id=29 1.       迪杰斯特拉算法简介 迪杰斯特拉(dijkstra)算法是典型的用来解决最短路径的算法,也是很多教程中的范例,由荷兰计算机科 ...

  8. Dijkstra【迪杰斯特拉算法】

    有关最短路径的最后一个算法——Dijkstra 迪杰斯特拉算法是由荷兰计算机科学家迪杰斯特拉于1959 年提出的,因此又叫迪杰斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路 ...

  9. c/c++ 图的最短路径 Dijkstra(迪杰斯特拉)算法

    c/c++ 图的最短路径 Dijkstra(迪杰斯特拉)算法 图的最短路径的概念: 一位旅客要从城市A到城市B,他希望选择一条途中中转次数最少的路线.假设途中每一站都需要换车,则这个问题反映到图上就是 ...

随机推荐

  1. 使用lnmp一键安装包后yum源出现的问题与解决

    遇到一个问题就是执行 Yum update 或使用yum安装软件等命令的时候会有一个链接报404,使用find查找到该链接与kbsingh-CentOS-Extras.repo这个包有关,删除后yum ...

  2. 树链剖分+线段树 BZOJ 1036 [ZJOI2008]树的统计Count

    题目链接 题意: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节 ...

  3. self.automaticallyAdjustsScrollViewInsets

    导航视图内Push进来的以“TableView”(没有ScrollView截图,就将就一下)为主View的视图,本来我们的cell是放在(0,0)的位置上的,但是考虑到导航栏.状态栏会挡住后面的主视图 ...

  4. 利用轮播原理结合hammer.js实现简洁的滑屏功能

    最近有个任务,做一个非常小的h5的应用,只有2屏,需要做横向的全屏滑动切换和一些简单的动画效果,之前做这种东西用的是fullpage.js和jquery,性能不是很好,于是就想自己动手弄一个简单的东西 ...

  5. trie字典树详解及应用

    原文链接    http://www.cnblogs.com/freewater/archive/2012/09/11/2680480.html Trie树详解及其应用   一.知识简介        ...

  6. java接口的嵌套

    java接口 1.接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值 2.接口中的方法默认都是 public abstract ...

  7. 常见bug及解决方案

    1.外边距叠加 一.发生在一个div内 <!DOCTYPE> <html> <head> <meta http-equiv=Content-Type cont ...

  8. Daily Scrum02 12.10

    不同于往常,今天我们在中午体育课后,就简单的进行了一次小组会议,主要是讨论了一下,我们的单词软件的查询功能的优化的进度与暂时达到的效果,界面的各个按钮等元素的素材的准备有点拖慢,由于要反复修改,查看效 ...

  9. python与正则表达式

    匹配一个字符: . 任意非\n字符 [...] \d \D digit \s \S space \w \W word 匹配前一个字符的多个: * 0->> + 1->> ? 0 ...

  10. CSS实现元素水平/垂直居中的方法

    首先,我们来了解水平居中,它有很多种方法,我们暂时先来了解其中的几种: 1.    在实现方案中,我们最熟悉的莫过于给元素定义一个宽度,然后使用margin: 1 2 3 4 body{     wi ...