最短路径
迪杰斯特拉(Dijkstra)算
最短路径问题是图论研究中的一个经典算法问题,旨在寻找图(由结点和路径组成的)中两结点之间的最短路径,大致可以分为如下几种问题,可无论如何分类问题,其本质思想还是不变的,即,求两点间的最短距离。
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
#define INFINITY 65535//无边时的权值
#define MAX_VERTEX_NUM 10//最大顶点数
typedef struct MGraph {
string vexs[10];//顶点信息
int arcs[10][10];//邻接矩阵
int vexnum, arcnum;//顶点数和边数
} MGraph;
int LocateVex(MGraph G, string u) { //返回顶点u在图中的位置
for(int i=0; i<G.vexnum; i++)
if(G.vexs[i]==u)
return i;
return -1;
}
void CreateDN(MGraph &G) { //构造有向网
string v1, v2;
int w;
int i, j, k;
cout<<"请输入顶点数和边数:";
cin>>G.vexnum>>G.arcnum;
cout<<"请输入顶点:";
for(i=0; i<G.vexnum; i++)
cin>>G.vexs[i];
for(i=0; i<G.vexnum; i++)
for(j=0; j<G.vexnum; j++)
G.arcs[i][j]=INFINITY;
cout<<"请输入边和权值:"<<endl;
for(k=0; k<G.arcnum; k++) {
cin>>v1>>v2>>w;
i=LocateVex(G, v1);
j=LocateVex(G, v2);
G.arcs[i][j]=w;
}
}
//迪杰斯特拉算法求有向网G的v0顶点到其余顶点v的最短路径p[v]及带权长度D[v]
//p[][]=-1表示没有路径,p[v][i]存的是从v0到v当前求得的最短路径经过的第i+1个顶点(这是打印最短路径的关键),则v0到v的最短路径即为p[v][0]到p[v][j]直到p[v][j]=-1,路径打印完毕。
//final[v]为true当且仅当v∈S,即已经求得从v0到v的最短路径。
void ShortestPath_DIJ(MGraph G, int v0, int p[][MAX_VERTEX_NUM], int D[]) {
int v, w, i, j, min;
bool final[10];
for(v=0; v<G.vexnum; v++) {
final[v]=false;//设初值
D[v]=G.arcs[v0][v];//D[]存放v0到v得最短距离,初值为v0到v的直接距离
for(w=0; w<G.vexnum; w++)
p[v][w]=-1;//设p[][]初值为-1,即没有路径
if(D[v]<INFINITY) { //v0到v有直接路径
p[v][0]=v0;//v0到v最短路径经过的第一个顶点
p[v][1]=v;//v0到v最短路径经过的第二个顶点
}
}
D[v0]=0;//v0到v0距离为0
final[v0]=true;//v0顶点并入S集
for(i=1; i<G.vexnum; i++) { //其余G.vexnum-1个顶点
//开始主循环,每次求得v0到某个顶点v的最短路径,并将v并入S集,然后更新p和D
min=INFINITY;
for(w=0; w<G.vexnum; w++)//对所有顶点检查
if(!final[w] && D[w]<min) { //在S集之外(即final[]=false)的顶点中找离v0最近的顶点,将其赋给v,距离赋给min
v=w;
min=D[w];
}
final[v]=true;//v并入S集
for(w=0; w<G.vexnum; w++) { //根据新并入的顶点,更新不在S集的顶点到v0的距离和路径数组
if(!final[w] && min<INFINITY && G.arcs[v][w]<INFINITY && (min+G.arcs[v][w]<D[w])) {
//w不属于S集且v0->v->w的距离<目前v0->w的距离
D[w]=min+G.arcs[v][w];//更新D[w]
for(j=0; j<G.vexnum; j++) { //修改p[w],v0到w经过的顶点包括v0到v经过的所有顶点再加上顶点w
p[w][j]=p[v][j];
if(p[w][j]==-1) { //在p[w][]第一个等于-1的地方加上顶点w
p[w][j]=w;
break;
}
}
}
}
}
}
int main() {
int i, j;
MGraph g;
CreateDN(g);
int p[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//最短路径数组p
int D[MAX_VERTEX_NUM];//最短距离数组D
ShortestPath_DIJ(g, 0, p, D);
cout<<"最短路径数组p[i][j]如下:"<<endl;
for(i=0; i<g.vexnum; i++) {
for(j=0; j<g.vexnum; j++)
cout<<setw(3)<<p[i][j]<<" ";
cout<<endl;
}
cout<<g.vexs[0]<<"到各顶点的最短路径及长度为:"<<endl;
for(i=0; i<g.vexnum; i++) {
if(i!=0 && D[i]!=INFINITY) {
cout<<g.vexs[0]<<"-"<<g.vexs[i]<<"的最短路径长度为:"<<D[i];
cout<<" 最短路径为:";
for(j=0; j<g.vexnum; j++) {
if(p[i][j]>-1)
cout<<g.vexs[p[i][j]]<<" ";
}
cout<<endl;
} else if(D[i]==INFINITY)
cout<<g.vexs[0]<<"-"<<g.vexs[i]<<":"<<"不可达"<<endl;
}
return 0;
}
首先初始化距离矩阵,然后从第一个点开始逐渐更新矩阵点值。d[i][j]表示从i点到j点的距离。第k次更新时,判断d[i][k]+d[k][j]与d[i][j]的大小,如果前者小,则更新这个值,否则不变。
#include <stdio.h>
#include <stdlib.h>
#define MAXVEX 9
#define INFINITY 65535
struct MGraph {
int numVertexes;
int *vex;
int arc[MAXVEX][MAXVEX];
};
typedef int PathMatrix[MAXVEX][MAXVEX];
typedef int ShortPathTable[MAXVEX][MAXVEX];
void ShortestPath_Floyd(MGraph *G,PathMatrix *P,ShortPathTable *D) {
int v,w,k;
//初始化
for(v=0; v<G->numVertexes; ++v) {
for(w=0; w<G->numVertexes; ++w) {
(*D)[v][w]=G->arc[v][w];
(*P)[v][w]=w;
}
}
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] ) { // (v到w的距离) VS (v到k的距离+k到w的距离)
(*D)[v][w]=(*D)[v][k]+(*D)[k][w];
(*P)[v][w]=(*P)[v][k]; //若从v出发,要去w,则先要从v去到k,“再作下一步打算(下一步即(*P)[k][w])”
}
}
}
}
}
void main() {
MGraph *my_g=(struct MGraph*)malloc(sizeof(struct MGraph));
int i,j;
int t=0;
int v0=0;
int vv=8;
my_g->numVertexes=MAXVEX;
my_g->vex=(int*)malloc(sizeof(char)*my_g->numVertexes);
if(!my_g->vex) return;
for(i=0; i<my_g->numVertexes; ++i) //一维数组(图中各结点)初始化{0,1,2,3,4,5,6,7,8}
my_g->vex[i]=i++;
for(i=0; i<my_g->numVertexes; ++i)
for(j=0; j<my_g->numVertexes; ++j)
my_g->arc[i][j]=INFINITY;
// 无向图的权值二维数组为对称矩阵
my_g->arc[0][1]=1;
my_g->arc[0][2]=5;
my_g->arc[1][2]=3;
my_g->arc[1][3]=7;
my_g->arc[1][4]=5;
my_g->arc[2][4]=1;
my_g->arc[2][5]=7;
my_g->arc[3][4]=2;
my_g->arc[3][6]=3;
my_g->arc[4][5]=3;
my_g->arc[4][6]=6;
my_g->arc[4][7]=9;
my_g->arc[5][7]=5;
my_g->arc[6][7]=2;
my_g->arc[6][8]=7;
my_g->arc[7][8]=4;
for(i=0; i<my_g->numVertexes; ++i)
for(j=0; j<=i; ++j) {
if(i==j) {
my_g->arc[i][j]=0;
continue;
}
my_g->arc[i][j]=my_g->arc[j][i];
}
for(i=0; i<my_g->numVertexes; ++i) { //二维数组表示图中各结点间连接边的weight
for(j=0; j<my_g->numVertexes; ++j)
printf("%5d ",my_g->arc[i][j]);
printf("\n");
}
printf("\n\n");
PathMatrix D;
ShortPathTable P;
ShortestPath_Floyd(my_g,&P,&D);
for(i=0; i<MAXVEX; ++i) { //二维数组表示图中各结点间连接边的weight
for(j=0; j<MAXVEX; ++j)
printf("%5d ",P[i][j]);
printf("\n");
}
printf("\n\n");
free(my_g->vex);
}
撒花,完结!