两种比较常见的最短路径问题 一个是求某个原点到其余各个顶点的最短路径,另一种是求每一对顶点之间的最短路径,相对应的就是Dijkstra算法与Floyd算法 本文测试样例如下图
Dijkstra算法
迪杰斯特拉算法是一个按路径长度递增的次序产生最短路径的算法
代码如下
#include <iostream>
#include<algorithm>
using namespace std;
#define MVNum 100 //最大顶点数
#define MAXInt 10086 //极大值
typedef struct Mgraph
{
char vexs[MVNum]; //顶点表
int arcs[MVNum][MVNum]; //邻接矩阵
int vexnum; //图的当前点数
int arcnum; //图的当前边数
}AMGraph;//Adjacency Matrix Graph
int LocateVex(AMGraph* G, char v)//找到结点V在图G中的位置 即下标
{
for (int i = 0; i < G->vexnum; i++)
{
if (G->vexs[i] == v)
{
return i;
}
}
cout << "没找到" << endl;
return 0;
}
/*因为是有向网 所以赋权值的时候不应G->arcs[i][j] = G->arcs[j][i] = w; 应该G->arcs[i][j] = w;即可*/
void CreatAMG(AMGraph* G)//邻接矩阵表示法创建有向网
{
cout << "请输入图的总顶点数与总边数: ";
cin >> G->vexnum >> G->arcnum;//输入总顶点数 总边数
cout << "输入点的信息: ";
for (int i = 0; i < G->vexnum; i++)
{
cin >> G->vexs[i];
}
for (int i = 0; i < G->vexnum; i++)//初始化
{
for (int j = 0; j < G->vexnum; j++)
{
G->arcs[i][j] = MAXInt;
}
}
char v1, v2;//相连结点
int w;//权值
cout << "输入相连结点及边的权值" << endl;
for (int k = 0; k < G->arcnum; k++)//构造邻接矩阵
{
cin >> v1 >> v2 >> w;//表示v1有通往v2的路 即v1->v2
int i = LocateVex(G, v1);
int j = LocateVex(G, v2);
G->arcs[i][j]= w;
}
cout << "邻接矩阵如下" << endl;
for (int i = 0; i < G->vexnum; i++)
{
for (int j = 0; j < G->vexnum; j++)
{
cout << G->arcs[i][j] << " ";
}
cout << "\n";
}
return;
}
bool S[MVNum];//记录从原点v0到终点vi是否已被确定最短路径 true表示确定
int Path[MVNum];//记录从原点到终点vi的当前最短路径上vi的直接前驱顶点序号 否则为-1
int D[MVNum];//记录从原点到终点vi的当前最短路径 有弧则为权值 否则为∞
void ShortestPath_DIJ(AMGraph* G, int v0)
{
int n = G->vexnum;
int v = 0;
for (int i = 0; i < n; i++)//初始化
{
S[i] = false; //S初始化为空集
D[i] = G->arcs[v0][i]; //将V0到各个终点的最短路径长度初始化为弧上的权值
if (D[i] < MAXInt) //如果v0到v之间有弧则将v的前驱置为v0
Path[i] = v0; //无弧则置为-1
else
Path[i] = -1;
}
S[v0] = true; //将v0并入S集
D[v0] = 0; //源点到源点的距离为0
/*------------主循环 每次求得v0到某个顶点v的最短路径 并将V加入S集*/
for (int i = 1; i < n; i++)
{
int min = MAXInt;
for (int w = 0; w < n; w++)
{
if (!S[w] && D[w] < min)
{
v = w;
min = D[w];
} //选择一条当前最短路径,终点为v
S[v] = true; //将V加入S
for (int w = 0; w < n; w++)//更新最短路径长度
{
if (!S[w] && D[v] + G->arcs[v][w] < D[w])
{
D[w] = D[v] + G->arcs[v][w];//更新D[w]
Path[w] = v;//更新前驱
}
}
}
}
}
int main()
{
AMGraph* G = (AMGraph*)malloc(sizeof(AMGraph));
if (G == NULL)
{
cout << "空间不足 创建失败" << endl;
return 0;
}
CreatAMG(G);
ShortestPath_DIJ(G, 0);
for (int i = 0; i < G->vexnum; i++)
{
cout << G->vexs[0] << "--" << G->vexs[i] << "的最短路径为:" << D[i] << endl;
}
return 0;
}
测试结果如下
此程序设置的极大值MAX为10086
Floyd算法
代码如下 可以大致将Floyd算法看成是Dijkstra算法Plus
#include <iostream>
#include<algorithm>
using namespace std;
#define MVNum 100 //最大顶点数
#define MAXInt 10086 //极大值
typedef struct Mgraph
{
char vexs[MVNum]; //顶点表
int arcs[MVNum][MVNum]; //邻接矩阵
int vexnum; //图的当前点数
int arcnum; //图的当前边数
}AMGraph;//Adjacency Matrix Graph
int LocateVex(AMGraph* G, char v)//找到结点V在图G中的位置 即下标
{
for (int i = 0; i < G->vexnum; i++)
{
if (G->vexs[i] == v)
{
return i;
}
}
cout << "没找到" << endl;
return 0;
}
/*因为是有向网 所以赋权值的时候不应G->arcs[i][j] = G->arcs[j][i] = w; 应该G->arcs[i][j] = w;即可*/
void CreatAMG(AMGraph* G)//邻接矩阵表示法创建有向网
{
cout << "请输入图的总顶点数与总边数: ";
cin >> G->vexnum >> G->arcnum;//输入总顶点数 总边数
cout << "输入点的信息: ";
for (int i = 0; i < G->vexnum; i++)
{
cin >> G->vexs[i];
}
for (int i = 0; i < G->vexnum; i++)//初始化
{
for (int j = 0; j < G->vexnum; j++)
{
G->arcs[i][j] = MAXInt;
}
}
char v1, v2;//相连结点
int w;//权值
cout << "输入相连结点及边的权值" << endl;
for (int k = 0; k < G->arcnum; k++)//构造邻接矩阵
{
cin >> v1 >> v2 >> w;//表示v1有通往v2的路 即v1->v2
int i = LocateVex(G, v1);
int j = LocateVex(G, v2);
G->arcs[i][j] = w;
}
cout << "邻接矩阵如下" << endl;
for (int i = 0; i < G->vexnum; i++)
{
for (int j = 0; j < G->vexnum; j++)
{
cout << G->arcs[i][j] << " ";
}
cout << "\n";
}
return;
}
int Path[MVNum][MVNum];
int D[MVNum][MVNum];
void ShortestPath_Floyd(AMGraph* G)
{
for (int i = 0; i < G->vexnum; i++)
{
for (int j = 0; j < G->vexnum; j++)
{
D[i][j] = G->arcs[i][j];
if (D[i][j] < MAXInt && i != j)//i j 有弧 则将j的前驱置为i
Path[i][j] = i;
else
Path[i][j] = -1;//否则置位-1
}
}
for (int k = 0; k < G->vexnum; k++)
{
for (int i = 0; i < G->vexnum; i++)
{
for (int j = 0; j < G->vexnum; j++)
{
if (D[i][k] + D[k][j] < D[i][j])// i 经过 k 到达 j 的一条路径更短
{
D[i][j] = D[i][k] + D[k][j];//更新D[i][j]
Path[i][j] = k;//将j的前驱置为k
}
}
}
}
}
int main()
{
AMGraph* G = (AMGraph*)malloc(sizeof(AMGraph));
if (G == NULL)
{
cout << "空间不足 创建失败" << endl;
return 0;
}
CreatAMG(G);
ShortestPath_Floyd(G);
for (int i = 0; i < G->vexnum; i++)
{
for (int j = 0; j < G->vexnum; j++)
{
cout << G->vexs[i] << "-->" << G->vexs[j] << "的最短路径为" << D[i][j]<<endl;
}
}
return 0;
}
测试结果如下