最短路问题 —— 若网络中的每条边都有一个数值(长度、成本、时间等),找出两节点之间总权和最小的路径
数据结构课代码实现 之 最短路问题
简要理解
Dijkstra算法:一个顶点到其余各顶点的最短路算法
Floyd算法:求多源汇最短路
Dijkstra算法
主要思想为维护一个 dist数组 保存起点到其余各点的最短路长度
初始化时将 dist数组中每个 dist[j] 初始化为起点到 j点的边长 (无边则初始化为INFINITY)
之后每次选择 dist数组 中最小的元素 将其对应点设置为已确定最短路径
并用其更新其余所有未确定最短路径的点的最短路长度
n - 1
次操作后即可更新所有点的最短路
Floyd算法
用中转点 k 更新 点 i 到 点 j 的最短路径
d[i][j] = d[i][k] + d[k][j]
代码实现
用邻接矩阵存图
Dijkstra算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| typedef struct ArcNode { struct ArcNode* next; int vex; }ArcNode;
struct Path { ArcNode* first; int num; }path[MAX_VERTEX_NUM];
bool final[MAX_VERTEX_NUM];
void dijkstra(MGraph &G, int v0, Path* p, int d[]) { for(int i = 0;i < G.vexnum;i++) { final[i] = false; p[i].num = 1; p[i].first = (ArcNode *)malloc(sizeof(ArcNode)); p[i].first->vex = v0; d[i] = G.arcs[v0][i].adj; if(d[i] < INFINITY) { p[i].first->next = (ArcNode *)malloc(sizeof(ArcNode)); p[i].first->next->vex = i; p[i].num = 2; } } int poi;
for(int i = 1;i < G.vexnum;i++) { int min = INFINITY; for(int j = 0;j < G.vexnum;j++) { if(!final[j]) { if(d[j] < min) { poi = j; min = d[j]; } } }
final[poi] = true;
for(int j = 0;j < G.vexnum;j++) { if(!final[j] && (min + G.arcs[poi][j].adj < d[j])) { d[j] = min + G.arcs[poi][j].adj; ArcNode* clean = p[j].first;
for(int i = 0;i < path[j].num;i++) { ArcNode* last = clean; clean = clean->next; free(last); }
p[j].first = (ArcNode *)malloc(sizeof(ArcNode));
ArcNode* tep = p[j].first; ArcNode* tmp = p[poi].first;
for(int k = 0;k < p[poi].num;k++, tep = tep->next, tmp = tmp->next) { tep->vex = tmp->vex; tep->next = (ArcNode *)malloc(sizeof(ArcNode)); }
p[j].num = p[poi].num; tep->vex = j; p[j].num++; } } } }
int main() { MGraph a; CreateGraph(a); int d[a.vexnum]; dijkstra(a, 0, path, d);
int x, y; cout << "请输入起点与要查询的点(输入点的储存值):"; cin >> x >> y; x = LocateVex(a, x); y = LocateVex(a, y);
cout << x << "号结点到" << y << "号结点的最短路长度为:"; cout << d[y] << endl;
cout << x << "号结点到" << y << "号结点的最短路路径长度为:"; cout << path[y].num << endl;
ArcNode* j = path[y].first; cout << "记录的路径为:" << endl; for(int i = 0;i < path[y].num;i++, j = j->next) { cout << j->vex << endl; } return 0; }
|
Floyd算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
| typedef struct ArcNode { struct ArcNode* next; int vex; }ArcNode;
struct Path { ArcNode* first; int num; }**path;
void Floyd(MGraph &G, Path** p, int** d) { for(int i = 0;i < G.vexnum;i++) { for(int j = 0;j < G.vexnum;j++) { p[i][j].num = 1; p[i][j].first = (ArcNode *)malloc(sizeof(ArcNode)); p[i][j].first->vex = i; d[i][j] = G.arcs[i][j].adj; if(d[i][j] < INFINITY) { p[i][j].first->next = (ArcNode *)malloc(sizeof(ArcNode)); p[i][j].first->next->vex = j; p[i][j].num = 2; } } } for(int i = 0;i < G.vexnum;i++) { for(int j = 0;j < G.vexnum;j++) { for(int k = 0;k < G.vexnum;k++) { if(d[i][k] + d[k][j] < d[i][j]) { d[i][j] = d[i][k] + d[k][j];
ArcNode* clean = p[i][j].first;
for(int u = 0;u < path[i][j].num;u++) { ArcNode* last = clean; clean = clean->next; free(last); }
p[i][j].first = (ArcNode *)malloc(sizeof(ArcNode));
ArcNode* tep = p[i][j].first; ArcNode* tmp = p[i][k].first;
for(int u = 0;u < p[i][k].num;u++, tep = tep->next, tmp = tmp->next) { tep->vex = tmp->vex; tep->next = (ArcNode *)malloc(sizeof(ArcNode)); }
tmp = p[k][j].first->next; for(int u = 0;u < p[k][j].num - 1;u++, tep = tep->next, tmp = tmp->next) { tep->vex = tmp->vex; tep->next = (ArcNode *)malloc(sizeof(ArcNode)); }
p[i][j].num = p[i][k].num + p[k][j].num - 1; } } } } }
int main() { MGraph a; CreateGraph(a); int** d; path = (Path**)malloc(a.vexnum * sizeof(Path*)); for(int i = 0;i < a.vexnum;i++) path[i] = (Path*)malloc(a.vexnum * sizeof(Path));
d = (int**)malloc(a.vexnum * sizeof(int*)); for(int i = 0;i < a.vexnum;i++) d[i] = (int*)malloc(a.vexnum * sizeof(int)); Floyd(a, path, d);
int x, y; cout << "请输入查询的起点与终点(输入点的储存值):"; cin >> x >> y;
x = LocateVex(a, x); y = LocateVex(a, y);
cout << x << "号结点到" << y << "号结点的最短路长度为:"; cout << d[x][y] << endl;
cout << x << "号结点到" << y << "号结点的最短路路径长度为:"; cout << path[x][y].num << endl;
ArcNode* tep = path[x][y].first; cout << "记录的路径为:" << endl; for(int u = 0;u < path[x][y].num;u++, tep = tep->next) cout << tep->vex << endl; return 0; }
|