问题描述:
最短路径算法的实现,编写算法对带权有向图中从源点到其他各点的最短路径。
比如这张有向图。
首先要采用邻接矩阵表示法创建这张图的有向网,然后使用迪杰斯特拉算法就最短路径。
创建有向网
采用邻接矩阵的方法创建有向网:
邻接矩阵结构体
typedef char VerTexType; //顶点数据类型
typedef int ArcType; //边权值类型
typedef struct
{
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum, arcnum; //图的当前点数和边数
}AMGraph;
//采用邻接矩阵表示法创建有向网
void createUFN(AMGraph& g)
{
cout << "输入总顶点数和总边数:" << endl;
cin >> g.vexnum >> g.arcnum;
//依次输入点的信息
cout << "依次输入点的信息:" << endl;
for (int i = 0; i < g.vexnum; i++)
{
cin >> g.vexs[i];
}
//初始化邻接矩阵,边的权值都设为极大值MaxInt
for (int i = 0; i < g.vexnum; i++)
for (int j = 0; j < g.vexnum; j++)
g.arcs[i][j] = MaxInt;
//构造邻接矩阵
cout << "输入一条边依附的起始节点、终止节点和边的权值:" << endl;
char v1, v2;
int w,a,b;
for (int k = 0; k < g.arcnum; k++)
{
cin >> v1 >> v2 >> w;
for (int u = 0; u < g.vexnum; u++)
{
if (g.vexs[u] == v1)
a = u;
if (g.vexs[u] == v2)
b = u;
}
g.arcs[a][b] = w; //将边<v1,v2>的权值设置为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 << endl;
}
}
这里可以求得邻接矩阵的表现形式为(其中用12767代表无穷大)
12767 | 2 | 12767 | 12767 | 10 |
12767 | 12767 | 3 | 12767 | 7 |
4 | 12767 | 12767 | 4 | 12767 |
12767 | 12767 | 12767 | 12767 | 5 |
12767 | 12767 | 3 | 12767 | 12767 |
Dijkstra算法
不懂迪杰斯特拉算法的可以去B站看下面这个视频,讲的确实好,我当时看一遍就醒悟了。
【算法】最短路径查找—Dijkstra算法_哔哩哔哩_bilibili
//dijkstra
void ShortPath_DIJ(AMGraph g, int v0)
{
int n = g.vexnum;
/*bool S[n];*/
bool* S = new bool[n];
/*int D[n],path[n];*/
int* D = new int[n];
int* path = new int[n];
for(int v = 0;v<n;v++)
{
S[v] = false;
D[v] = g.arcs[v0][v];
if(D[v]<MaxInt)
path[v]=v0;
else
path[v] = -1;
}
S[v0] = true;
D[v0] = 0;
//初始化结束,开始主循环,每次求得v0到某个顶点v的最短路径,将v加入S
for(int i=1;i<n;i++)
{
int min = MaxInt;
int v;
//选择一条当前的最短路径,终点为v
for(int w=0;w<n;w++)
{
if(!S[w]&&D[w]<min)
{
v = w;
min = D[w];
}
}
S[v] = true; //将v加入S
for(int w=0;w<n;w++) //更新从v0出发到集合v-s上所有顶点最短路径长度
{
if(!S[w]&&(D[v]+g.arcs[v][w]<D[w]))
{
D[w] = D[v]+g.arcs[v][w]; //更新D[w]
path[w] = v; //更改w的前驱为v
}
}
}
cout << "到各点的最短路径为:" << endl;
for (int r = 0; r < n; r++)
{
cout << D[r] << ' ';
}
}
测试
int main()
{
AMGraph g;
createUFN(g);
ShortPath_DIJ(g, 0);
return 0;
}
按照之前那个图输入
5个节点8个边,节点分别叫1,2,3,4,5
运行结果:
输入总顶点数和总边数:
5 8
依次输入点的信息:
1 2 3 4 5
输入一条边依附的起始节点、终止节点和边的权值:
1 2 2
1 5 10
2 3 3
2 5 7
3 1 4
3 4 4
4 5 5
5 3 3
邻接矩阵:
12767 2 12767 12767 10
12767 12767 3 12767 7
4 12767 12767 4 12767
12767 12767 12767 12767 5
12767 12767 3 12767 12767
到各点的最短路径为:
0 2 5 9 9
完整代码
#include <iostream>
using namespace std;
#define MaxInt 12767
#define MVNum 100
typedef char VerTexType; //顶点数据类型
typedef int ArcType; //边权值类型
typedef struct
{
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum, arcnum; //图的当前点数和边数
}AMGraph;
//采用邻接矩阵表示法创建有向网
void createUFN(AMGraph& g)
{
cout << "输入总顶点数和总边数:" << endl;
cin >> g.vexnum >> g.arcnum;
//依次输入点的信息
cout << "依次输入点的信息:" << endl;
for (int i = 0; i < g.vexnum; i++)
{
cin >> g.vexs[i];
}
//初始化邻接矩阵,边的权值都设为极大值MaxInt
for (int i = 0; i < g.vexnum; i++)
for (int j = 0; j < g.vexnum; j++)
g.arcs[i][j] = MaxInt;
//构造邻接矩阵
cout << "输入一条边依附的起始节点、终止节点和边的权值:" << endl;
char v1, v2;
int w,a,b;
for (int k = 0; k < g.arcnum; k++)
{
cin >> v1 >> v2 >> w;
for (int u = 0; u < g.vexnum; u++)
{
if (g.vexs[u] == v1)
a = u;
if (g.vexs[u] == v2)
b = u;
}
g.arcs[a][b] = w; //将边<v1,v2>的权值设置为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 << endl;
}
}
//dijkstra
void ShortPath_DIJ(AMGraph g, int v0)
{
int n = g.vexnum;
/*bool S[n];*/
bool* S = new bool[n];
/*int D[n],path[n];*/
int* D = new int[n];
int* path = new int[n];
for(int v = 0;v<n;v++)
{
S[v] = false;
D[v] = g.arcs[v0][v];
if(D[v]<MaxInt)
path[v]=v0;
else
path[v] = -1;
}
S[v0] = true;
D[v0] = 0;
//初始化结束,开始主循环,每次求得v0到某个顶点v的最短路径,将v加入S
for(int i=1;i<n;i++)
{
int min = MaxInt;
int v;
//选择一条当前的最短路径,终点为v
for(int w=0;w<n;w++)
{
if(!S[w]&&D[w]<min)
{
v = w;
min = D[w];
}
}
S[v] = true; //将v加入S
for(int w=0;w<n;w++) //更新从v0出发到集合v-s上所有顶点最短路径长度
{
if(!S[w]&&(D[v]+g.arcs[v][w]<D[w]))
{
D[w] = D[v]+g.arcs[v][w]; //更新D[w]
path[w] = v; //更改w的前驱为v
}
}
}
cout << "到各点的最短路径为:" << endl;
for (int r = 0; r < n; r++)
{
cout << D[r] << ' ';
}
}
int main()
{
AMGraph g;
createUFN(g);
ShortPath_DIJ(g, 0);
return 0;
}