算法 – Dijistra (求最短路径)
先赞后看,养成好习惯。有帮助的话,点波关注!我会坚持更新,感谢您的支持!
需求:学习迪杰斯特拉算法原理,并复现。
参考:
迪杰斯特拉算法(求最短路径)
一. 核心思想
1. 核心函数:
void DijkstraMinTree(MGraph G, int v0, int p[V], int D[V])
2. 核心步骤:
1)初始化
2)选点
:选择本轮循环中权值最小的顶点,即为本次能确定最短路径的顶点
3)标记
4)更新
:利用已标记顶点,向下延伸
二. 代码
#include <stdio.h>
#include <iostream>
#define V 20 // 最大顶点个数
#define INF 65535 // 无穷大
// 无项有权图数据结构
typedef struct {
int vexs[V]; // 顶点
int arcs[V][V]; // 边
int vexnum, arcnum; //顶点数,边数
} MGraph;
//根据顶点本身数据,判断出顶点在二维数组中的位置
int LocateVex(MGraph *G, const int &v) {
int i = 0;
for (; i < G->vexnum; ++i) {
if (G->vexs[i] == v) {
break;
}
}
// 如果找不到
if (i > G->vexnum) {
std::cerr << "no such vertex" << std::endl;
return -1;
}
return i;
}
//构造无向有权图
void CreateDG(MGraph *G) {
std::cout << "输入图的顶点数和边数:" << std::endl;
scanf("%d %d", &(G->vexnum), &(G->arcnum));
std::cout << "输入各个顶点: " << std::endl;
for (int i = 0; i < G->vexnum; ++i) {
scanf("%d", &(G->vexs[i]));
}
for (int i = 0; i < G->vexnum; ++i) {
for (int j = 0; j < G->vexnum; ++j) {
G->arcs[i][j] = INF;
}
}
printf("输入各个边的数据:\n");
for (int i = 0; i < G->arcnum; ++i) {
int v1, v2, w;
scanf("%d %d %d", &v1, &v2, &w);
int n = LocateVex(G, v1);
int m = LocateVex(G, v2);
if (m == -1 || n == -1) {
return;
}
G->arcs[n][m] = w;
G->arcs[m][n] = w;
}
}
//迪杰斯特拉算法,v0表示有向网中起始点所在数组中的下标
void DijkstraMinTree(MGraph G, int v0, int p[V], int D[V]) {
int final[V]; // 标记数据,是否确认为最短路径
// 初始化
for (int i = 0; i < G.vexnum; ++i) {
final[i] = 0;
p[i] = 0;
D[i] = G.arcs[v0][i];
}
// v0 作为初始点
D[v0] = 0;
final[v0] = 1;
int k = 0;
for (int i = 0; i < G.vexnum; ++i) {
int min = INF;
/* 选择到各顶点权值最小的顶点,即为本次能确定最短路径的顶点 */
for (int w = 0; w < G.vexnum; ++w) {
if (!final[w]) {
if (D[w] < min) {
k = w; // 记录下标
min = D[w];
}
}
}
// 标记
final[k] = 1;
// 更新
for (int w = 0; w < G.vexnum; ++w) {
if (!final[w] && (min + G.arcs[k][w] < D[w])) {
D[w] = min + G.arcs[k][w];
p[w] = k; //记录上一个最短路径顶点
}
}
}
}
// 网站中的测试用例
void TestDG(MGraph *G){
G->vexnum = 7;
G->arcnum = 9;
for (int i = 0; i < G->vexnum; ++i) {
for (int j = 0; j < G->vexnum; ++j) {
G->arcs[i][j] = INF;
}
}
for (int i = 0; i < G->vexnum; ++i) {
G->vexs[i] = i;
}
G->arcs[0][1] = 2;
G->arcs[1][0] = 2;
G->arcs[0][2] = 6;
G->arcs[2][0] = 6;
G->arcs[1][3] = 5;
G->arcs[3][1] = 5;
G->arcs[2][3] = 8;
G->arcs[3][2] = 8;
G->arcs[3][5] = 15;
G->arcs[5][3] = 15;
G->arcs[3][4] = 10;
G->arcs[4][3] = 10;
G->arcs[4][5] = 6;
G->arcs[5][4] = 6;
G->arcs[4][6] = 2;
G->arcs[6][4] = 2;
G->arcs[5][6] = 6;
G->arcs[6][5] = 6;
}
int main() {
MGraph G;
// CreateDG(&G);
TestDG(&G);
int p[V] = {0};
int D[V] = {0};
DijkstraMinTree(G, 0, p, D);
std::cout << "最短路径为:" << std::endl;
for (int i = 1; i < G.vexnum; ++i) {
std::cout << i << "-0 的最短路径为";
std::cout << i;
int j = i;
while (p[j] != 0) {
std::cout << "-"<< p[j];
j = p[j];
}
std::cout <<"-0" << std::endl;
}
for(int i = 0; i< G.vexnum; ++i){
std::cout << "p["<< i<< "]:" << p[i] << std::endl;
}
std::cout << "原点到各顶点的最短路径长度为:" << std::endl;
for (int i = 1; i < G.vexnum; ++i) {
std::cout << G.vexs[0] << "-" << G.vexs[i] << ": " << D[i] << std::endl;
}
return 0;
}