/*
* 2014-5-22
* 摘自http://blog.csdn.net/jnu_simba/article/details/8871794
*
*/
#include<iostream>
using namespace std;
#define MAXEDGE 20
#define MAXVEX 20
#define INFINITY 65535
typedef struct
{
int vexs[MAXVEX];
int arc[MAXVEX][MAXVEX];
int numVertexes, numEdges;
} MGraph;
typedef int PathArc[MAXVEX];
typedef int ShortPathTable[MAXVEX];
/* 构建图 */
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] = INFINITY;
}
}
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算法,求有向网G的pos顶点到其余顶点v的最短路径P[v]及带权长度D[v] */
/* P[v]的值为前驱顶点下标,D[v]表示pos到v的最短路径长度和 */
/* pos 取值 0~MG.numVertexs-1 */
void ShortestPath_Dijkstra(MGraph MG, int pos, PathArc P, ShortPathTable D){
int v, w, k, min;
int final[MAXVEX];/* final[w]=1表示求得顶点pos至w的最短路径 */
/*初始化*/
for (v = 0; v < MG.numVertexes; v++){
final[v] = 0;/* 全部顶点初始化为未知最短路径状态 */
D[v] = MG.arc[pos][v];/* 将与pos点有连线的顶点加上权值 */
P[v] = 0;/* 初始化路径数组P为0 */
}
D[pos] = 0; /*说明源点pos自身的长度为0 */
P[pos] = -1; /* -1表示自身无前驱顶点*/
final[pos] = 1;/* pos至pos不需要求路径 */
/* 开始主循环,每次求得pos到某个v顶点的最短路径 */
for (v = 1; v < MG.numVertexes; v++){
min = INFINITY;/* 当前所知离pos顶点的最近距离 */
for (w = 0; w < MG.numVertexes; w++){ /* 寻找剩余未确认路径的节点中,离pos最近的顶点 */
if (final[w]==0 && D[w] < min){
k = w;
min = D[w]; /* w顶点离pos顶点更近 */
}
}
final[k] = 1;/* 将目前找到的最近的顶点置为1 */
for (w = 0; w < MG.numVertexes; w++){/* 修正当前最短路径及距离 若D(pos->k->w)<D(w),则更新*/
if (!final[w] && (min + MG.arc[k][w] < D[w])){
/* 说明找到了更短的路径,修改D[w]和P[w] */
D[w] = min + MG.arc[k][w];/* 修改当前路径长度 */
P[w] = k;
}
}
}
/* 结束循环,若P[w] = pos;说明顶点w的前驱为pos */
}
int main(void)
{
MGraph MG;
PathArc P;
ShortPathTable D;
int i, j, pos = 0;
CreateMGraph(&MG);
ShortestPath_Dijkstra(MG, pos, P, D);
cout << "逆序最短路径如下:" << endl;
for (i = 8; i >= 0; i--)
{
j = i;
while (P[j] != -1 && P[j] != 0)
{
cout << "v" << j << "<-" << "v" << P[j] << " ";
j = P[j];
}
cout << "v" << j << "<-" << "v" << pos << " ";
cout << endl;
}
cout << endl;
return 0;
}
/*
逆序最短路径如下:
v8->v7 v7->v6 v6->v3 v3->v4 v4->v2 v2->v1 v1->v0
v7->v6 v6->v3 v3->v4 v4->v2 v2->v1 v1->v0
v6->v3 v3->v4 v4->v2 v2->v1 v1->v0
v5->v4 v4->v2 v2->v1 v1->v0
v4->v2 v2->v1 v1->v0
v3->v4 v4->v2 v2->v1 v1->v0
v2->v1 v1->v0
v1->v0
v0->v0
*/
D算法是求所有节点到指定节点的方法,下面的Floyed算法是求任一节点到其他所有节点的最短路径问题,问题稍微复杂点,但代码却出奇的简洁。
#include <stdio.h>
#define MAXVEX 20
#define INFINITY 65535
typedef struct
{
int vexs[MAXVEX];
int arc[MAXVEX][MAXVEX];
int numVertexes, numEdges;
}MGraph;
/* 构造图 */
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] = INFINITY;
}
}
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算法,求网图G中各顶点v到其余顶点w的最短路径P[v][w]及带权长度D[v][w]。 */
void ShortestPath_Floyd(MGraph G, int P[][MAXVEX], int D[][MAXVEX])
{
int v,w,k;
for(v=0; v<G.numVertexes; ++v) /* 初始化D与P */
{
for(w=0; w<G.numVertexes; ++w)
{
D[v][w]=G.arc[v][w]; /* D[v][w]值即为对应点间的权值 */
P[v][w]=w; /* 初始化P */
}
}
for(k=0; k<G.numVertexes; ++k)
{
for(v=0; v<G.numVertexes; ++v)
{
for(w=0; w<G.numVertexes; ++w)
{
if (D[v][w]>D[v][k]+D[k][w])
{/* 如果经过下标为k顶点路径比原两点间路径更短 */
D[v][w]=D[v][k]+D[k][w];/* 将当前两点间权值设为更小的一个 */
P[v][w]=P[v][k];/* 路径设置为经过下标为k的顶点 */
}
}
}
}
}
int main(void)
{
int v,w,k;
MGraph G;
int P[MAXVEX][MAXVEX];
int D[MAXVEX][MAXVEX]; /* 求某点到其余各点的最短路径 */
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");
}
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");
}
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;
}