相关文献:
数据结构与算法(一):基础理论
数据结构与算法(二):线性表的实现
数据结构与算法(三):线性表算法设计练习
数据结构与算法(四):斐波那契数列
数据结构与算法(五):LRU
数据结构与算法(六):栈
数据结构与算法(七):栈/队列的算法解题思想
数据结构与算法(八):队列
数据结构与算法(九):树形结构/二叉树/线索化二叉树
数据结构与算法(十):哈夫曼树
数据结构与算法(十一):图形结构
数据结构与算法(十二):图的应用-最小生成树-Prim/Kruskal
数据结构与算法(十三):图的应用-最短路径-Dijkstra/Floyd
数据结构与算法(十四):图的应用-拓扑排序/关键路径
一、最短路径
当你从一个城市去到另一个城市,可以选择中间跨越不同的地方,选择不一样的路径,最终到达终点。
最短路径就是从起点到达终点怎么走是最短的,但是会面临两种情况:1.带权值的网图;2.不带权值的连通图。
- 1.带权值的网图:从起点到终点所累积的权值总和最小(权值可理解成路程);
- 2.不带权值的连通图:从起点到终点的边数总和最小。
举例网图:
![](https://img.haomeiwen.com/i1487527/b5c00f0d1303b140.png)
要从V0出发到V8
![](https://img.haomeiwen.com/i1487527/26615cd1da6d0ae8.png)
最短路径: V0 — V1 — V2 — V4 — V3 —V6 —V7 — V8
最短路径权值和: 1 + 3 + 1 + 2 +3 + 2 + 4 = 16
二、最短路径 - 迪迦斯特(Dijkstra)算法
![](https://img.haomeiwen.com/i1487527/b5c00f0d1303b140.png)
用邻接矩阵存储网图
![](https://img.haomeiwen.com/i1487527/573777b2dac21c72.png)
1.算法分析
定义三个数组去记录
从0开始:
//V0到V0是没有路径的.
final[v0] = 1;
//V0到V0的路径为0
(*D)[v0] = 0;
//V0到V0是没有路径的.所以-1;
(*P)[v0] = -1;
final数组
:表示V0 到某个顶点 Vw 是否已经求得了最短路径的标记;
如果V0 到 Vw 已经有结果,则final[w] = 1。(避免往回走的情况)
![](https://img.haomeiwen.com/i1487527/f2457813699bb390.png)
D数组
:表示V0 到某些顶点的路径,∞表示暂时还不能直接到达;
此时的数据是此时是V0所能到达顶点。
![](https://img.haomeiwen.com/i1487527/2fb2be524f4aa4bc.png)
现在D数组是V0到其它顶点的直接路径,但是我们代码回去修改数组的数据,变成间接路径。
p数组
:存储当前顶点的前驱顶点的下标。-1表示V0出发还没有前驱。
![](https://img.haomeiwen.com/i1487527/0dcb6ce484877ab8.png)
第1次执⾏
:看找到V1是怎么记录的
![](https://img.haomeiwen.com/i1487527/bdbcb6022e35f428.png)
V0->V1的权值 = 1
V0->V2的权值 = 5
在D数组中V1的权值更小(1<5,0不考虑是因为final标记过为1),所以min=1 (min记录上一次边权值)。
![](https://img.haomeiwen.com/i1487527/338963b29d0e1d4c.png)
final数组:
V0->V1存在最短路径 final[1] = 1 标记好防止往回找。
此时V1能直接到的地方:V0、V2、V3、V4,由于V0在final数组中已经标记过了不能回流,所以此时只剩下V2、V3、V4
D数组:
V0->V1->V2的权值 = min+3 = 4 < 5,此刻D[2] = 4代替掉原本的5;
V0->V1->V3的权值 = min+7 = 8 < ∞,此刻D[3] = 8代替掉原本的∞;
V0->V1->V4的权值 = min+5 = 6 < ∞,此刻D[4] = 6代替掉原本的∞。
p数组:
![](https://img.haomeiwen.com/i1487527/eb2f6d3378b34468.png)
p数组记录V2、V3、V4的前驱顶点是V1。
第2次执⾏
:看找到V2是怎么记录的
![](https://img.haomeiwen.com/i1487527/27e6a364e81a9cb2.png)
看D数组中的数据:
V0->V1->V2的权值 = 4
V0->V1->V3的权值 = 8
V0->V1->V4的权值 = 6
在D数组中V2的权值更小(4<6<8),所以min=4 (min记录上一次边权值)。
![](https://img.haomeiwen.com/i1487527/4f1502dcefbbb63f.png)
final数组:
在V0->V1->V2存在最短路径 final[2] = 1 标记好防止往回找。
此时V2能直接到的地方:V0、V1、V4、V5,由于V0/V1在final数组中已经标记过了不能回流,所以此时只剩下V4、V5。
D数组:
V0->V1->V2->V4的权值 = min+1 = 5 < 6,此刻D[4] = 5代替掉原本的6;
V0->V1->V2->V5的权值 = min+7 = 11 < ∞,此刻D[5] = 11代替掉原本的∞;
p数组:
![](https://img.haomeiwen.com/i1487527/64ee4ae760994cd1.png)
p数组记录V4、V5的前驱顶点是V2。
第3次执⾏
:看找到V4是怎么记录的
![](https://img.haomeiwen.com/i1487527/1961b9e706de4e64.png)
看D数组中的数据:
由于final标记了V0、V1、V2存在最短路径,无需看在D数组中的V0、V1、V2:
V0->V1->V3的权值 = 8
V0->V1->V2->V4的权值 = 5
V0->V1->V2->V5的权值 = 11
在D数组中V4的权值更小(5<8<11),所以min=5 (min记录上一次边权值)。
![](https://img.haomeiwen.com/i1487527/d17e83288c2c9641.png)
final数组:
在V0->V1->V2->V4存在最短路径 final[4] = 1 标记好防止往回找。
此时V2能直接到的地方:V1、V2、V3、V5、V6、V7,由于V1/V2在final数组中已经标记过了不能回流,所以此时只剩下V3、V5、V6、V7。
D数组:
V0->V1->V2->V4->V3的权值 = min+2 = 7 < 8,此刻D[3] = 7代替掉原本的8;
V0->V1->V2->V4->V5的权值 = min+3 = 8 < 11,此刻D[5] = 8代替掉原本的11;
V0->V1->V2->V4->V6的权值 = min+6 = 11 < ∞,此刻D[6] = 11代替掉原本的∞;
V0->V1->V2->V4->V7的权值 = min+9 = 14 < ∞,此刻D[7] = 14代替掉原本的∞。
p数组:
![](https://img.haomeiwen.com/i1487527/e900bcd01bffacef.png)
p数组记录V3、V5、V6、V7的前驱顶点是V4。
第4次执⾏
:看找到V3是怎么记录的
![](https://img.haomeiwen.com/i1487527/3251fd6e1f17f7bc.png)
看D数组中的数据:
由于final标记了V0、V1、V2、V4存在最短路径,无需看在D数组中的V0、V1、V2、V4:
V0->V1->V2->V4->V3的权值 = 7
V0->V1->V2->V4->V5的权值 = 8
V0->V1->V2->V4->V6的权值 = 11
V0->V1->V2->V4->V7的权值 = 14
在D数组中V4的权值更小(7<8<11<14),所以min=7 (min记录上一次边权值)。
![](https://img.haomeiwen.com/i1487527/3d77d56a8479d0ad.png)
final数组:
在V0->V1->V2->V4->V3存在最短路径 final[3] = 1 标记好防止往回找。
此时V3能直接到的地方:V1、V4、V6,由于V1/V4在final数组中已经标记过了不能回流,所以此时只剩下V6。
D数组:
V0->V1->V2->V4->V3->V6的权值 = min+3 = 10 <11,此刻D[6] = 10代替掉原本的11。
p数组:
![](https://img.haomeiwen.com/i1487527/b859d0580c7c542b.png)
p数组记录V6的前驱顶点是V3。
第5次执⾏
:看找到V6后,为啥去找V5->V7
![](https://img.haomeiwen.com/i1487527/1aa48a1a3414b931.png)
看D数组中的数据:
由于final标记了V0、V1、V3、V2、V4存在最短路径,无需看在D数组中的V0、V1、V3、V2、V4:
V0->V1->V2->V4->V5的权值 = 8
V0->V1->V2->V4->V3->V6的权值 = 10
V0->V1->V2->V4->V7的权值 = 14
在D数组中V4的权值更小(8<10<14),所以min=8 (min记录上一次边权值)。
![](https://img.haomeiwen.com/i1487527/cf49879ad985944e.png)
final数组:
在V0->V1->V2->V4->V5存在最短路径 final[5] = 1 标记好防止往回找。
此时V4能直接到的地方:只剩下V5、V6、V7(因为其它位已被final标记)。
D数组:
V0->V1->V2->V4->V5的权值 = min+3 = 11 > 8,此刻D[5]依旧为8;
V0->V1->V2->V4->V6的权值 = min+6 = 14 <10,此刻D[6]依旧为10;
V0->V1->V2->V4->V7的权值 = min+9 = 17 <14,此刻D[7] 依旧为14;
V0->V1->V2->V4->V5->V7的权值 = min+5 = 13 < 14,此刻D[7] = 13代替掉原本的14。
p数组:
![](https://img.haomeiwen.com/i1487527/486e3a9aece0635c.png)
p数组记录V7的前驱顶点是V5。
第6次执⾏
:权衡V5/V6,决定V6->V7
![](https://img.haomeiwen.com/i1487527/7b0483946435222e.png)
看D数组中的数据:
由于final标记了V0、V1、V2、V3、V4、V5存在最短路径,无需看在D数组中的V0、V1、V2、V3、V4、V5:
V0->V1->V2->V4->V3->V6的权值 = 10
V0->V1->V2->V4->V5->V7的权值 = 13
在D数组中V6的权值更小(0<13),所以min=10 (min记录上一次边权值)。
![](https://img.haomeiwen.com/i1487527/15beaa8cc003fb62.png)
final数组:
在V0->V1->V2->V4->V3->V6存在最短路径 final[6] = 1 标记好防止往回找。
此时V6能直接到的地方:只剩下V7、V8(因为V3/V4已被final标记)。
D数组:
V0->V1->V2->V4->V3->V6->V7的权值 = min+2 = 12 < 13,此刻D[7] = 12代替掉原本的13;
V0->V1->V2->V4->V6->V8的权值 = min+7 = 17 < ∞,此刻D[8] = 17代替掉原本的∞。
p数组:
![](https://img.haomeiwen.com/i1487527/efc72485d9b76f74.png)
p数组记录V7、V8的前驱顶点是V6。
第7次执⾏
:权衡V6/V7,决定V7->V8
![](https://img.haomeiwen.com/i1487527/07d47d89096756a4.png)
看D数组中的数据:
由于final标记了V0、V1、V2、V3、V4、V5、V6存在最短路径,无需看在D数组中的V0、V1、V2、V3、V4、V5、V6:
V0->V1->V2->V4->V3->V6->V7的权值 = 12
V0->V1->V2->V4->V3->V6->V8的权值 = 17
在D数组中V6的权值更小(12<17),所以min=12 (min记录上一次边权值)。
![](https://img.haomeiwen.com/i1487527/fc95569b9941e0d9.png)
final数组:
在V0->V1->V2->V4->V3->V6->V7存在最短路径 final[7] = 1 标记好防止往回找。
此时V7能直接到的地方:只剩下V8。
D数组:
V0->V1->V2->V4->V3->V6->V7->V8的权值 = min+4 = 16 < 17,此刻D[7] = 16代替掉原本的17。
p数组:
![](https://img.haomeiwen.com/i1487527/3e1140f0817ef96a.png)
p数组记录V8的前驱顶点是V7。
第8次执⾏
:确定V8的路径
由于此时final数组里只有V8没有被标记,所以min=16 == 16
![](https://img.haomeiwen.com/i1487527/19567683fa46f9c6.png)
final数组:
在V0->V1->V2->V4->V3->V6->V7->V8存在最短路径 final[8] = 1。
D数组、p数组都不变
![](https://img.haomeiwen.com/i1487527/1806867cd514f30a.jpg)
此时D数组存储的就是V0到每一个顶点的最短路径的权值之和;
此时p数组存储的就是V0出发,每一个顶点的前驱。
2.算法实现
- 通过邻接矩阵创建图
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXEDGE 20
#define MAXVEX 20
#define INFINITYC 65535
typedef int Status;
typedef struct
{
int vexs[MAXVEX];
int arc[MAXVEX][MAXVEX];
int numVertexes, numEdges;
}MGraph;
/*用于存储最短路径下标的数组*/
typedef int Patharc[MAXVEX];
/*用于存储到各点最短路径权值的和*/
typedef int ShortPathTable[MAXVEX];
/*10.1 创建邻近矩阵*/
void CreateMGraph(MGraph *G)
{
int i, j;
G->numEdges=16;
G->numVertexes=9;
for (i = 0; i < G->numVertexes; i++)
{
G->vexs[i]=i;
}
for (i = 0; i < G->numVertexes; i++)
{
for ( j = 0; j < G->numVertexes; j++)
{
if (i==j)
G->arc[i][j]=0;
else
G->arc[i][j] = G->arc[j][i] = INFINITYC;
}
}
G->arc[0][1]=1;
G->arc[0][2]=5;
G->arc[1][2]=3;
G->arc[1][3]=7;
G->arc[1][4]=5;
G->arc[2][4]=1;
G->arc[2][5]=7;
G->arc[3][4]=2;
G->arc[3][6]=3;
G->arc[4][5]=3;
G->arc[4][6]=6;
G->arc[4][7]=9;
G->arc[5][7]=5;
G->arc[6][7]=2;
G->arc[6][8]=7;
G->arc[7][8]=4;
for(i = 0; i < G->numVertexes; i++)
{
for(j = i; j < G->numVertexes; j++)
{
G->arc[j][i] =G->arc[i][j];
}
}
}
- Dijkstra算法实现
/*10.2 求得网图中2点间最短路径
Dijkstra 算法
G: 网图;
v0: V0开始的顶点;
p[v]: 前驱顶点下标;
D[v]: 表示从V0到V的最短路径长度和;
*/
void ShortestPath_Dijkstra(MGraph G, int v0, Patharc *P, ShortPathTable *D)
{
int v,w,k,min;
k = 0;
/*final[w] = 1 表示求得顶点V0~Vw的最短路径*/
int final[MAXVEX];
/*1.初始化数据*/
for(v=0; v<G.numVertexes; v++)
{
//全部顶点初始化为未知最短路径状态0
final[v] = 0;
//将与V0 点有连线的顶点最短路径值;
(*D)[v] = G.arc[v0][v];
//初始化路径数组p = 0;
(*P)[v] = 0;
}
//V0到V0的路径为0
(*D)[v0] = 0;
//V0到V0 是没有路径的.
final[v0] = 1;
//v0到V0是没有路径的
(*P)[v0] = -1;
//2. 开始主循环,每次求得V0到某个顶点的最短路径
for(v=1; v<G.numVertexes; v++)
{
//当前所知距离V0顶点最近的距离
min=INFINITYC;
/*3.寻找离V0最近的顶点*/
for(w=0; w<G.numVertexes; w++)
{
if(!final[w] && (*D)[w]<min)
{
k=w;
//w顶点距离V0顶点更近
min = (*D)[w];
}
}
//将目前找到最近的顶点置为1;
final[k] = 1;
/*4.把刚刚找到v0到v1最短路径的基础上,对于v1 与 其他顶点的边进行计算,得到v0与它们的当前最短距离;*/
for(w=0; w<G.numVertexes; w++)
{
//如果经过v顶点的路径比现在这条路径长度短,则更新
if(!final[w] && (min + G.arc[k][w]<(*D)[w]))
{
//找到更短路径, 则修改D[W],P[W]
//修改当前路径的长度
(*D)[w] = min + G.arc[k][w];
(*P)[w]=k;
}
}
}
}
int main(void)
{
printf("最短路径-Dijkstra算法\n");
int i,j,v0;
MGraph G;
Patharc P;
ShortPathTable D;
v0=0;
CreateMGraph(&G);
ShortestPath_Dijkstra(G, v0, &P, &D);
printf("最短路径路线:\n");
for(i=1;i<G.numVertexes;++i)
{
printf("v%d -> v%d : ",v0,i);
j=i;
while(P[j]!=-1)
{
printf("%d ",P[j]);
j=P[j];
}
printf("\n");
}
printf("\n最短路径权值和\n");
for(i=1;i<G.numVertexes;++i)
printf("v%d -> v%d : %d \n",G.vexs[0],G.vexs[i],D[i]);
printf("\n");
return 0;
}
三、最短路径 - 弗洛伊德(Floyd)算法
1.简化推演公式
![](https://img.haomeiwen.com/i1487527/5261cdd98e6b8379.jpg)
有 V1->V2 = 5
或者 V1->V0->V2 = 3
两种路径;
该图的邻接矩阵就可以有下面这样的演变:
![](https://img.haomeiwen.com/i1487527/86b9474e555be589.png)
![](https://img.haomeiwen.com/i1487527/c61e497a7ef8bdda.png)
于是推演出该公式:
![](https://img.haomeiwen.com/i1487527/f08f5686d2bfa695.png)
2.算法执行过程分析
![](https://img.haomeiwen.com/i1487527/b5c00f0d1303b140.png)
得到初始化的两个临街矩阵 D和P:
/* 1. 初始化D与P 矩阵*/
for(v=0; v<G.numVertexes; ++v) {
for(w=0; w<G.numVertexes; ++w) {
/* D[v][w]值即为对应点间的权值 */
(*D)[v][w]=G.arc[v][w];
/* 初始化P P[v][w] = w*/
(*P)[v][w]=w;
}
}
![](https://img.haomeiwen.com/i1487527/f6e1935ccc98ade3.png)
最短路径的遍历:
//2.K表示经过的中转顶点
for(k=0; k<G.numVertexes; ++k) {
for(v=0; v<G.numVertexes; ++v) {
for(w=0; w<G.numVertexes; ++w) {
/*如果经过下标为k顶点路径⽐原两点间路径更短 */
if ((*D)[v][w]>(*D)[v][k]+(*D)[k][w]) {
/* 将当前两点间权值设为更⼩的⼀个 */
(*D)[v][w]=(*D)[v][k]+(*D)[k][w];
/* 路径设置为经过下标为k的顶点 */
(*P)[v][w]=(*P)[v][k];
}
}
}
}
根据公式去推导
![](https://img.haomeiwen.com/i1487527/d5c90d9e43bb4a54.png)
-
第1次执⾏
:
当 K = 0 时, 也就是所有顶点都经过V0中转, 计算是否有最短路径的变化。所以k=0时,D和P没有发⽣任何变换。 -
第2次执⾏
:
当 K = 1 时, 也就是所有顶点都经过V1 中转
![](https://img.haomeiwen.com/i1487527/a28c097e068a430b.png)
![](https://img.haomeiwen.com/i1487527/437ae38b4e663ccc.png)
![](https://img.haomeiwen.com/i1487527/bb3937df0f46c827.png)
(下面就不画图了,直接给执行过程,并不完全,只是给个套上公式后的推导)
![](https://img.haomeiwen.com/i1487527/ff5260b05df8bc6a.png)
![](https://img.haomeiwen.com/i1487527/8323073c215b942b.png)
![](https://img.haomeiwen.com/i1487527/e4de0a8161f608c9.png)
![](https://img.haomeiwen.com/i1487527/018ab7814947d243.png)
![](https://img.haomeiwen.com/i1487527/d31e814de19a262a.png)
![](https://img.haomeiwen.com/i1487527/07cd3e1eec2be629.png)
![](https://img.haomeiwen.com/i1487527/2f7a90b8e44f8250.png)
![](https://img.haomeiwen.com/i1487527/0250a38965478ad1.png)
这里只分析到K=1的情况,下面还有好多好多....
该算法时间复杂度是 8³。
最终得到的D和P的存储数据如下:
![](https://img.haomeiwen.com/i1487527/e2ee7787713861c0.png)
D矩阵存放了每一个顶点到任意一个顶点的最短路径
,比如V2->V8是12;
以V2->V8来看,P矩阵应该这样看:
V2->V8 经历过V4 (P[2][8])
V2->V4->V8 经历过V3 (P[4][8])
V2->V4->V3->V8 经历过V6 (P[3][8])
V2->V4->V3->V6->V8 经历过V7 (P[6][8])
V2->V4->V3->V6->V7->V8 经历过V8 (P[7][8])
V2->V4->V3->V6->V7->V8才是最终的路径 (P[8][8])
3. 算法实现
- 初始化图
#include <stdio.h>
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXEDGE 20
#define MAXVEX 20
#define INFINITYC 65535
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef struct
{
int vexs[MAXVEX];
int arc[MAXVEX][MAXVEX];
int numVertexes, numEdges;
}MGraph;
typedef int Patharc[MAXVEX][MAXVEX];
typedef int ShortPathTable[MAXVEX][MAXVEX];
/* 11.1 构成邻近矩阵 */
void CreateMGraph(MGraph *G)
{
int i, j;
/* printf("请输入边数和顶点数:"); */
G->numEdges=16;
G->numVertexes=9;
for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
{
G->vexs[i]=i;
}
for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
{
for ( j = 0; j < G->numVertexes; j++)
{
if (i==j)
G->arc[i][j]=0;
else
G->arc[i][j] = G->arc[j][i] = INFINITYC;
}
}
G->arc[0][1]=1;
G->arc[0][2]=5;
G->arc[1][2]=3;
G->arc[1][3]=7;
G->arc[1][4]=5;
G->arc[2][4]=1;
G->arc[2][5]=7;
G->arc[3][4]=2;
G->arc[3][6]=3;
G->arc[4][5]=3;
G->arc[4][6]=6;
G->arc[4][7]=9;
G->arc[5][7]=5;
G->arc[6][7]=2;
G->arc[6][8]=7;
G->arc[7][8]=4;
for(i = 0; i < G->numVertexes; i++)
{
for(j = i; j < G->numVertexes; j++)
{
G->arc[j][i] =G->arc[i][j];
}
}
}
- Floyd算法
/* 11. 2
Floyd算法,求网图G中各顶点v到其余顶点w的最短路径P[v][w]及带权长度D[v][w]。
Patharc 和 ShortPathTable 都是二维数组;
*/
void ShortestPath_Floyd(MGraph G, Patharc *P, ShortPathTable *D)
{
int v,w,k;
/* 1. 初始化D与P 矩阵*/
for(v=0; v<G.numVertexes; ++v)
{
for(w=0; w<G.numVertexes; ++w)
{
/* D[v][w]值即为对应点间的权值 */
(*D)[v][w]=G.arc[v][w];
/* 初始化P P[v][w] = w*/
(*P)[v][w]=w;
}
}
//2.K表示经过的中转顶点
for(k=0; k<G.numVertexes; ++k)
{
for(v=0; v<G.numVertexes; ++v)
{
for(w=0; w<G.numVertexes; ++w)
{
/*如果经过下标为k顶点路径比原两点间路径更短 */
if ((*D)[v][w]>(*D)[v][k]+(*D)[k][w])
{
/* 将当前两点间权值设为更小的一个 */
(*D)[v][w]=(*D)[v][k]+(*D)[k][w];
/* 路径设置为经过下标为k的顶点 */
(*P)[v][w]=(*P)[v][k];
}
}
}
}
}
int main(void)
{
printf("Hello,最短路径弗洛伊德Floyd算法");
int v,w,k;
MGraph G;
Patharc P;
ShortPathTable D; /* 求某点到其余各点的最短路径 */
CreateMGraph(&G);
ShortestPath_Floyd(G,&P,&D);
//打印所有可能的顶点之间的最短路径以及路线值
printf("各顶点间最短路径如下:\n");
for(v=0; v<G.numVertexes; ++v)
{
for(w=v+1; w<G.numVertexes; w++)
{
printf("v%d-v%d weight: %d ",v,w,D[v][w]);
//获得第一个路径顶点下标
k=P[v][w];
//打印源点
printf(" path: %d",v);
//如果路径顶点下标不是终点
while(k!=w)
{
//打印路径顶点
printf(" -> %d",k);
//获得下一个路径顶点下标
k=P[k][w];
}
//打印终点
printf(" -> %d\n",w);
}
printf("\n");
}
//打印最终变换后的最短路径D数组
printf("最短路径D数组\n");
for(v=0; v<G.numVertexes; ++v)
{
for(w=0; w<G.numVertexes; ++w)
{
printf("%d\t",D[v][w]);
}
printf("\n");
}
//打印最终变换后的最短路径P数组
printf("最短路径P数组\n");
for(v=0; v<G.numVertexes; ++v)
{
for(w=0; w<G.numVertexes; ++w)
{
printf("%d ",P[v][w]);
}
printf("\n");
}
return 0;
}
网友评论