带权图分为有向和无向,无向图的有求最小生成树的prime算法和kruskal算法,链接:https://blog.csdn.net/qq_35247337/article/details/107319361
有向图的最短路径算法有dijkstra算法和floyd算法。这里记录dijkstra算法。
------------------
Dijkstra 算法找到了从任意指定顶点到任何其他顶点的最短路径,而且证实可以到达图中的所有其他顶点。它使用了通常被称为贪心的策略或算法。贪心算法把问题分解成小块或步骤,并且在每一步中确定最优解,用这些最优解合并生成最终的解。
Dijkstra 算法的思想就是首先把起点到所有点的距离存下来找个最短的,之后把这个距离最短的点作为中转站再来遍历一遍更新所有点的距离,这样把所有的点找遍之后就存下了起点到其他所有点的最短距离。
具体的过程详解我推荐一篇文章,写的蛮仔细的:https://www.cnblogs.com/jason2003/p/7222182.html
这里写一下C#实现的代码:
//记录原始顶点与远距离顶点之间的关系
public class DistOriginal
{
public int distance;
public int parentVert;
public DistOriginal(int pv, int d)
{
distance = d;
parentVert = pv;
}
}
public class Vertex
{
public string label;
public bool isInTree;
public Vertex(string lab)
{
label = lab;
isInTree = false;
}
}
public class Graph
{
private const int max_verts = 20;
int infinity = 1000000;
Vertex[] vertexList;//所有顶点集合
int[,] adjMat;//邻接矩阵
int nVerts;//当前拥有的顶点数量
int nTree;//当前树中拥有的顶点数量
DistOriginal[] sPath;
int currentVert;
int startToCurrent;
public Graph()
{
vertexList = new Vertex[max_verts];
adjMat = new int[max_verts, max_verts];
nVerts = 0;
nTree = 0;
for (int j = 0; j <= max_verts - 1; j++)
for (int k = 0; k <= max_verts - 1; k++)
adjMat[j, k] = infinity;
sPath = new DistOriginal[max_verts];
}
public void AddVertex(string lab)
{
vertexList[nVerts] = new Vertex(lab);
nVerts++;
}
public void AddEdge(int start, int theEnd, int weight)
{
adjMat[start, theEnd] = weight;
}
public void Path()
{
int startTree = 0;
vertexList[startTree].isInTree = true;
nTree = 1;
for (int j = 0; j <= nVerts; j++)
{
int tempDist = adjMat[startTree, j];
sPath[j] = new DistOriginal(startTree, tempDist);
}
while (nTree < nVerts)
{
int indexMin = GetMin();
int minDist = sPath[indexMin].distance;
currentVert = indexMin;
startToCurrent = sPath[indexMin].distance;
vertexList[currentVert].isInTree = true;
nTree++;
AdjustShortPath();
}
DisplayPaths();
nTree = 0;
for (int j = 0; j <= nVerts - 1; j++)
vertexList[j].isInTree = false;
}
public int GetMin()
{
int minDist = infinity;
int indexMin = 0;
for (int j = 1; j <= nVerts - 1; j++)
{
if (!(vertexList[j].isInTree) && sPath[j].distance < minDist)
{
minDist = sPath[j].distance;
indexMin = j;
}
}
return indexMin;
}
public void AdjustShortPath()
{
int column = 1;
while (column < nVerts)
if (vertexList[column].isInTree)
column++;
else
{
int currentToFring = adjMat[currentVert, column];
int startToFringe = startToCurrent + currentToFring;
int sPathDist = sPath[column].distance;
if (startToFringe < sPathDist)
{
sPath[column].parentVert = currentVert;
sPath[column].distance = startToFringe;
}
column++;
}
}
}