您的位置:首页 > 其它

最短路径

2011-08-13 16:28 162 查看
<1>假设用带权的邻接矩阵arcs来表示带权有向图,arcs[i][j]表示弧<vi,vj>上的权值 若<vi,vj>不存在 则置arc[i][j]为∞ S为以找到从v出发的最短路径的集合,它的初始状态为空集

那么,从v出发到图上其余各顶点(终点),可能达到的最短路径长度的初值为:D[i]=arcs[getLocateVex(G,v)][i] vi∈V

<2>选择vj 使得 D[j]=Min{D[i]|vi∈V-S} vj就是当前求得的一条从v出发的最短路径的终点 令S=SU{j}

<3>修改从v出发到集合V-S上任一顶点vk可达到最短路径长度 如果 D[j]+arcs[j][k]<D[k] 则修改D[k]为 D[k]=D[j]+arcs[j][k]

<4>重复操作<2><3>共n-1次 由此得到从v到图上其余个顶点的最短路径是依路径长度递增的序列

废话少说 上代码
/*
*最短路径
*/
#include<stdio.h>//EOF(=^Z或F6),NULL
#include<stdlib.h>
#include<limits.h>//INT_MAX
#include<string.h>

#define MAX_NAME 5//顶点字符串最大长度+1
#define MAX_INFO 20//相关信息字符串的最大长度+1

typedef int VRType;
typedef char InfoType;
typedef char VertexType[MAX_NAME];

#define INFINITY INT_MAX//用整型最大值代替∞
#define MAX_VEX_NUM 20

typedef struct
{
VRType adj;//顶点关系类型
InfoType *info;//该弧相关信息的指针
}ArcCell,AdjMatrix[MAX_VEX_NUM][MAX_VEX_NUM];
typedef struct
{
VertexType vexs[MAX_VEX_NUM];
AdjMatrix arcs;
int vexnum,arcnum;//当前顶点数和弧数
}MGraph;

typedef int PathMatrix[MAX_VEX_NUM][MAX_VEX_NUM];
typedef int ShortPathTable[MAX_VEX_NUM];

/* 初始条件:图G存在,u和G中顶点有相同特征 */
/* 操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 */
int getLocateVex(MGraph G,VertexType u)
{
int i;

for(i=0;i<G.vexnum;++i)
{
if(strcmp(u,G.vexs[i])==0)
{
return i;
}
}
return -1;
}
/* 采用数组(邻接矩阵)表示法,构造有向网G */
int createDN(MGraph *G)
{
int i,j,k,w,IncInfo;
char s[MAX_INFO],*info;
VertexType va,vb;

printf("请输入有向图G的顶点数 弧数 弧是否含有其他信息(是:1 否:0):");
scanf("%d%d%d",&(*G).vexnum,&(*G).arcnum,&IncInfo);

printf("请输入%d顶点的值(<%d个字符):\n",(*G).vexnum,MAX_NAME);
for(i=0;i<(*G).vexnum;++i)//构造顶点向量
scanf("%s",(*G).vexs[i]);

for(i=0;i<(*G).vexnum;++i)//初始化邻接矩阵
{
for(j=0;j<(*G).vexnum;++j)
{
(*G).arcs[i][j].adj=INFINITY;//网
(*G).arcs[i][j].info=NULL;
}
}

printf("请输入%d条弧的弧头 弧尾 权值(以空格作为间隔):\n",(*G).arcnum);
for(k=0;k<(*G).arcnum;++k)
{
scanf("%s%s%d%*c",va,vb,&w);//%*c吃掉回车符
i=getLocateVex(*G,va);
j=getLocateVex(*G,vb);
(*G).arcs[i][j].adj=w;//有向网

if(IncInfo)
{
printf("请输入该弧的相关(<%d个字符):",MAX_INFO);
gets(s);
w=strlen(s);
if(w)
{
info=(char *)malloc((w+1)*sizeof(char));
strcpy(info,s);
(*G).arcs[i][j].info=info;//有向
}
}
}
return 1;
}
/* 用Dijkstra算法求有向网G的v0顶点到其余顶点v的最短路径P[v]及带权长度 */
/* D[v] 若P[v][w]为TRUE,则w是从v0到v当前求得最短路径上的顶点         */
/* final[v]为TRUE当且仅当v∈S ,即已经求得从v0到v的最短路径           */
void ShortestPath_DIJ(MGraph G,int v0,PathMatrix *P,ShortPathTable *D)
{
int v,w,i,j,min;
int final[MAX_VEX_NUM];

for(v=0;v<G.vexnum;++v)
{
final[v]=0;
(*D)[v]=(G).arcs[v0][v].adj;

for(w=0;w<G.vexnum;++w)
(*P)[v][w]=0;//设空路径

if((*D)[v]<INFINITY)
{
(*P)[v][v0]=1;
(*P)[v][v]=1;
}
}
(*D)[v0]=0;
final[v0]=1;//初始化 v0顶点属于S集
/*其余G.vexnum-1个顶点*/
for(i=1;i<G.vexnum;++i)//开始主循环 每次求得v0到某个v顶点的最短路径 并加v到S集
{
min=INFINITY;//当前所知离v0顶点的最近距离
for(w=0;w<G.vexnum;++w)
if(!final[w])//w顶点在V-S中
if((*D)[w]<min)//w顶点离v0顶点更近
{
v=w;
min=(*D)[w];
}
final[v]=1;
for(w=0;w<G.vexnum;++w)//更新当前最短路径及距离
{
if(!final[w]&&min<INFINITY&&G.arcs[v][w].adj<INFINITY&&(min+G.arcs[v][w].adj<(*D)[w]))/* 修改D[w]和P[w],w∈V-S */
{
(*D)[w]=min+G.arcs[v][w].adj;
for(j=0;j<G.vexnum;++j)
(*P)[w][j]=(*P)[v][j];
(*P)[w][w]=1;
}
}
}
}
int main()
{
int i,j,v0=0;//v0为源点
MGraph G;
PathMatrix p;
ShortPathTable d;

createDN(&G);
ShortestPath_DIJ(G,v0,&p,&d);

printf("最短路径数组p[i][j]如下:\n");
for(i=0;i<G.vexnum;++i)
{
for(j=0;j<G.vexnum;++j)
printf("%2d",p[i][j]);
printf("\n");
}

printf("%s到各个顶点的最短路径长度为:\n",G.vexs[0]);
for(i=1;i<G.vexnum;++i)
printf("%s-%s:%d\n",G.vexs[0],G.vexs[i],d[i]);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: