最短路径解决了求解一个图中两顶点之间最短的路径问题。其中Dijkstra算法应用贪心法求解单源点到其余各点的最短路径问题;而Floyd算法则解决了图中任意两点间的最短路径问题。
/*Dijkstra算法
时间复杂度O(n^2)
1.当前源点到任意点路径长度集合dist中的最短路径(v,vk)必为源点v到vk的最短路径,
因为源点v再经由其他点到vk必定比当前路径长度长
2.取min{(v,vi)当前长度,(v,vk)当前长度+(vk,vi)长度}为当前长度,反证法可知其贪心正确性
3.更新后将vk标记,下次不再查询
4.重复上述步骤直到每个点都查询一遍*/
struct vertex
{
int v;
string vex;
};
vertex Vertex[MAX];
int Groph[MAX][MAX];
void Dijkstra(int v, int n)
{
vector<int> dist;//存储当前源点到任意点最短路长度
vector<string> path;//存储当前源点到任意点最短路径
vector<int> s;//存储源点与已经生成的终点的集合
for (int i = 0; i < n; ++i)
{
dist.push_back(Groph[v][i]);
if (dist[i] == INF)
path.push_back(Vertex[v].vex + Vertex[i].vex);
else
path.push_back("");
}
s.push_back(v);
dist[v] = 0;
int num = 1;
while (num < n)
{
int k = 0;
for (int i = 0; i < n; ++i)
if (dist[i] != 0 && dist[i] < dist[k])//找dist中的最小值k
k = i;
cout << dist[k] << " " << path[k] << endl;
s.push_back(k);//加入集合s
++num;
for (int i = 0; i < n; ++i)
{
if (dist[i]>dist[k]+Groph[k][i])//若源点经由k到其他点路径长度比当前路径长度小则修改dist和path
{
dist[i] = dist[k] + Groph[k][i];
path[i] = path[k] + Vertex[i].vex;
}
}
dist[k] = 0;//标记为已完成终点
}
}
/*Floyd算法
时间复杂度O(n^3)
*/
struct vertex
{
int v;
string vex;
};
vertex Vertex[MAX];
int Groph[MAX][MAX];
void Floyd(int n)
{
int dist[MAX][MAX];//distk[i][j]=min{dist(k-1)[i][j], dist(k-1)[i][k]+dist(k-1)[k][j]},0<=k<=n-1
string path[MAX][MAX];
for (int i = 0; i < n; ++i)//初始化dist和path
for (int j = 0; j < n; ++j)
{
dist[i][j] = Groph[i][j];
if (dist[i][j] != INF)
path[i][j] = Vertex[i].vex + Vertex[j].vex;
else
path[i][j] = "";
}
for (int k = 0; k < n; ++k)//进行n次迭代
for (int i = 0; i < n; ++i)//顶点i,j之间是否经过k点
for (int j = 0; j < n; ++j)
if (dist[i][k] + dist[k][j] < dist[i][j])
{
dist[i][j] = dist[i][k] + dist[k][j];
path[i][j] = path[i][k] + path[k][j];
}
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
cout << path[i][j] << dist[i][j] << endl;
}