6.4.2 最短路径
2. 狄克斯特拉(Dikastra)算法
对于求单源点的最短路径问题,狄克斯特拉(Dikastra)提出了一个按路径长度递增的顺序逐步产生最短路径的构造算法。狄克斯特拉的算法思想是:设置两个顶点的集合S和T,集合S中存放已找到最短路径的顶点,集合T中存放当前还未找到最短路径的顶点。初始状态时,集合S中只包含源点,设为v0,然后从集合T中选择到源点v0路径长度最短的顶点u加入到集合S中,集合S中每加入一个新的顶点u都要修改源点v0到集合T中剩余顶点的当前最短路径长度值,集合T中各顶点的新的最短路径长度值为原来的当前最短路径长度值与从源点过顶点u到达该顶点的新的最短路径长度中的较小者。此过程不断重复,直到集合T中的顶点全部加到集合S中为止。
以下图为例:
其对源点1运用Dikastra算法得出的结果如下:
根据邻接链表存储结构实现Dikastra算法:(邻接链表的实现在前面的博客)
public List<VexListNode<T>> Dikastra(GraphAdjList<T> graph, GraphNode<T> node, out int[] weights)
{
List<VexListNode<T>> vexNodes = new List<VexListNode<T>>();
vexNodes.Add(new VexListNode<T>(node));
bool[] marker = new bool[graph.NodeNum];
weights = new int[graph.NodeNum];
int indexer = graph.IsNode(node);
marker[indexer] = true;
weights[indexer] = 0;
while (vexNodes.Count < graph.NodeNum)
{
AdjListNode<T> minAdjNode = null;
int minWeight = 0;
VexListNode<T> minInVexNode=null;
VexListNode<T> minOutVexNode=null;
VexListNode<T> currentVexNode = null;
AdjListNode<T> currentAdjNode = null;
for (int i = 0; i < graph.NodeNum; i++)
{
if (marker[i] == true)
{
currentVexNode = graph.vexList[i];
currentAdjNode = currentVexNode.FirstAdj;
while (currentAdjNode != null)
{
if (marker[currentAdjNode.AdjVexIndex] == false)
{
if (minAdjNode == null || weights[i] + currentAdjNode.Weight < minWeight)
{
minAdjNode = currentAdjNode;
minInVexNode = graph.vexList[currentAdjNode.AdjVexIndex];
minWeight = weights[i] + currentAdjNode.Weight;
minOutVexNode = currentVexNode;
}
}
currentAdjNode = currentAdjNode.Next;
}
}
}
VexListNode<T> vexNode = new VexListNode<T>(minInVexNode.Node);
vexNode.FirstAdj = new AdjListNode<T>(minAdjNode.Name, graph.IsNode(minOutVexNode.Node), minAdjNode.Weight);
vexNodes.Add(vexNode);
marker[minAdjNode.AdjVexIndex] = true;
weights[minAdjNode.AdjVexIndex] = minWeight;
}
return vexNodes;
}
调用代码:
GraphAdjList<int> adjList = new GraphAdjList<int>(100);
//Inial graph object
GraphNode<int> node1 = new GraphNode<int>(1);
GraphNode<int> node2 = new GraphNode<int>(2);
GraphNode<int> node3 = new GraphNode<int>(3);
GraphNode<int> node4 = new GraphNode<int>(4);
GraphNode<int> node5 = new GraphNode<int>(5);
GraphNode<int> node6 = new GraphNode<int>(6);
GraphNode<int> node7 = new GraphNode<int>(7);
GraphNode<int> node8 = new GraphNode<int>(8);
adjList.SetNode(node1);
adjList.SetNode(node2);
adjList.SetNode(node3);
adjList.SetNode(node4);
adjList.SetNode(node5);
adjList.SetNode(node6);
adjList.SetNode(node7);
adjList.SetNode(node8);
adjList.SetEdge(0, node1, node2, 1);
adjList.SetEdge(1,node1, node3, 4);
adjList.SetEdge(2,node1, node5, 6);
adjList.SetEdge(3, node1, node4, 3);
adjList.SetEdge(4, node1, node6, 12);
adjList.SetEdge(5, node2, node4, 4);
adjList.SetEdge(6, node2, node3, 2);
adjList.SetEdge(7, node3, node5, 2);
adjList.SetEdge(8, node4, node2, 1);
adjList.SetEdge(9, node4, node3, 1);
adjList.SetEdge(10, node4, node8, 1);
adjList.SetEdge(11, node4, node7, 8);
adjList.SetEdge(12, node5, node3, 3);
adjList.SetEdge(13, node5, node8, 2);
adjList.SetEdge(14, node6, node4, 1);
adjList.SetEdge(15, node7, node4, 1);
adjList.SetEdge(16, node7, node8, 2);
adjList.SetEdge(17, node7, node6, 2);
adjList.SetEdge(18, node8, node5, 1);
adjList.SetEdge(19, node8, node7, 2);
int[] weights;
var list = adjList.Dikastra(adjList, node1, out weights);
int index = adjList.IsNode(node1);
foreach (var vexNode in list)
{
System.Console.Write("Node:");
System.Console.Write(vexNode.Node.Value);
System.Console.Write(" TotalWeights:");
System.Console.Write(weights[adjList.IsNode(vexNode.Node)]);
if (vexNode.FirstAdj != null)
{
System.Console.Write(" Edage:");
System.Console.Write(adjList.vexList[vexNode.FirstAdj.AdjVexIndex].Node.Value);
System.Console.Write(" -> (");
System.Console.Write(vexNode.FirstAdj.Weight);
System.Console.Write(") -> ");
System.Console.Write(vexNode.Node.Value);
}
System.Console.WriteLine();
}
System.Console.ReadKey();
输出结果:
Node:1 TotalWeights:0
Node:2 TotalWeights:1 Edage:1 -> (1) -> 2
Node:4 TotalWeights:3 Edage:1 -> (3) -> 4
Node:3 TotalWeights:3 Edage:2 -> (2) -> 3
Node:8 TotalWeights:4 Edage:4 -> (1) -> 8
Node:5 TotalWeights:5 Edage:3 -> (2) -> 5
Node:7 TotalWeights:6 Edage:8 -> (2) -> 7
Node:6 TotalWeights:8 Edage:7 -> (2) -> 6