图的最短路径算法,啊?广度优先搜索不就是求最短路径吗?好吧,广度优先搜索是求的最短节点数到达,但是每个节点到每个节点的距离(权重)不一样,就好比东莞到惠州和东莞到北京。所以这时候就要用迪克斯特拉算法了。
class Vertex {//顶点
public string Name;
public Vertex(string name) {
Name = name;
}
}
class Edge {//边
public Vertex From;
public Vertex To;
public int Weight;
public Edge(Vertex from, Vertex to, int weight) {
From = from;
To = to;
Weight = weight;
}
}
class VisitVertex {//用来记录存在的路径和总权重,简称路径
public int Weight;
public bool IsVisited;
public Vertex Vertex;
public VisitVertex(int weight, bool isVisited,Vertex vertex) {
Weight = weight;
IsVisited = isVisited;
Vertex = vertex;
}
}
class Program
{
static Dictionary<string, Edge[]> dict = new Dictionary<string, Edge[]>();
static void Main(string[] args)
{
Vertex O = new Vertex("O");
Vertex A = new Vertex("A");
Vertex B = new Vertex("B");
Vertex C = new Vertex("c");
//构建权重图
Edge OA = new Edge(O, A, 6);
Edge OB = new Edge(O, B, 3);
dict.Add("O", new Edge[] { OA, OB });
Edge BA = new Edge(B, A, 2);
Edge BC = new Edge(B, C, 9);
dict.Add("B", new Edge[] { BA, BC });
Edge AC = new Edge(A, C, 1);
dict.Add("A", new Edge[] { AC });
SearchLow(C);
Console.ReadKey();
}
static void SearchLow(Vertex x){
Dictionary<Vertex, Vertex> parent = new Dictionary<Vertex, Vertex>();//保存最短节点与节点的关系
Dictionary<Vertex, VisitVertex> weight = new Dictionary<Vertex, VisitVertex>();//记录当前最小权重
//初始化三个字典,起点开始
//获取到起点开始指向的边
Edge[] edges;
dict.TryGetValue("O", out edges);
foreach (Edge e in edges)
{
parent.Add(e.To, e.From);
weight.Add(e.To, new VisitVertex(e.Weight,false,e.To));
}
VisitVertex go = null;
while ((go = GetLowVertex(weight)) != null) {
Edge[] edges2;
dict.TryGetValue(go.Vertex.Name, out edges2);
if (edges2 == null) break;
foreach (Edge ee in edges2) {
int myWeight = go.Weight + ee.Weight;
VisitVertex orightWeight;
weight.TryGetValue(ee.To, out orightWeight);
if (orightWeight == null)
{
//如果没有过该路径,就添加
weight.Add(ee.To, new VisitVertex(myWeight, false, ee.To));
parent.Add(ee.To, ee.From);
}
else {
if (orightWeight.Weight > myWeight)
{
//发现更短的路径,更新权重值,更改为没有访问过,修改父节点(新路径了)
orightWeight.Weight = myWeight;
orightWeight.IsVisited = false;
parent[ee.To] = ee.From;
}
}
}
}
//输出路径和权重总值
VisitVertex finVist;
weight.TryGetValue(x, out finVist);
Console.WriteLine("总权重值:" + finVist.Weight);
Console.WriteLine(x.Name);
Vertex cur = x;
while (true) {
Vertex aaa;
parent.TryGetValue(cur, out aaa);
cur = aaa;
if (aaa == null)
{
break;
}
Console.WriteLine(aaa.Name);
}
}
//获取总权重值最小,又没有被访问过路径
static VisitVertex GetLowVertex(Dictionary<Vertex, VisitVertex> d) {
int val = Int32.MaxValue;
VisitVertex visit = null;
foreach (var i in d) {
if (i.Value.IsVisited == false) {
if (i.Value.Weight < val) {//新路径比旧路径权重值小
val = i.Value.Weight;
visit = i.Value;
}
}
}
if (visit != null) {
//标志该路径以被访问过
visit.IsVisited = true;
}
return visit;
}
}这种算法也有限制,就是图中不能出现环图,也不能出现负权重。
详情看:吃菜网-迪克斯特拉算法