最短路径Dijkstra算法
本文取自《数据结构与算法》(C语言版)(第三版)。出版社是清华大学出版社。
本博文作为学习资料整理。
附书的截图:
最短路径的Dijkstra算法的基本思想是:设S为最短路径已确定的顶点集,V-S是最短距离尚未确定的顶点集。初始时,将源点V0加入到顶点集S中,即S={V0}。在当前顶点集V-S中选择一个最短路径最小的顶点来扩充顶点集S,以保证算法按路径长度递增的次序产生各顶点的最短路径。
Dijkstra算法的步骤示意图例如以下:
其程序例如以下:
#include<stdio.h> #include<stdlib.h> #include<string.h> #define MaxVertexNum 100 const int INF=25500000; typedef struct node { int adjvex; int hostvex; struct node *nextrarc; int info; }EdgeNode; typedef struct vnode { char vexdate; int pos; EdgeNode *firstarc; }VertexNode; typedef VertexNode AdjList[MaxVertexNum]; typedef struct { AdjList adjlist; int n,e; }ALGraph; int initGraph(ALGraph* aGraph); int mFind(char aChar, ALGraph* aGraph); int createHead(char aChar, ALGraph* aGraph); void addBody(char aChar, int aPos, ALGraph* aGraph, int weight); void showGraph(ALGraph* aGraph); EdgeNode* isEdge(VertexNode* start, VertexNode* end); void Dijkstra(ALGraph* aGraph, int v); void Dispath(int dist[], int path[], int s[], ALGraph* aGraph, int v); void privatePrintPath(ALGraph* aGraph, int path[], int curr, int v); int main(void) { char a; int isFinish=0; int headPos=-1; char a1='@', a2='@', a3='@', a4='@', a5='@', a6='@', a7='@'; ALGraph g_graph; initGraph(&g_graph); printf("Input arcs like this '(start,end:weight)',end with $ "); while(isFinish==0) { while(1) { a=getchar(); if(a=='$'||a=='#') { if(a=='#') isFinish=1; break; } if(a==' '||a==' ') continue; a1=a2; a2=a3; a3=a4; a4=a5; a5=a6; a6=a7; a7=a; if(a1=='('&&a3==','&&a5==':'&&a7==')') { if((headPos=mFind(a2,&g_graph))==-1) headPos=createHead(a2,&g_graph); addBody(a4,headPos,&g_graph,a6-48); } } } Dijkstra(&g_graph,2); return 0; } EdgeNode* isEdge(VertexNode* start, VertexNode* end) { EdgeNode* temEdge=start->firstarc; while(temEdge!=NULL) { if(temEdge->adjvex==end->pos) return temEdge; temEdge=temEdge->nextrarc; } return NULL; } void Dijkstra(ALGraph* aGraph, int v) { int dist[MaxVertexNum], path[MaxVertexNum]; int s[MaxVertexNum]; int mindis,i,j,u; EdgeNode* temEdge; for(i=0; i<aGraph->n; i++) { dist[i]=INF; s[i]=0; path[i]=-1; } temEdge=aGraph->adjlist[v].firstarc; while(temEdge!=NULL) { dist[temEdge->adjvex]=temEdge->info; path[temEdge->adjvex]=v; temEdge=temEdge->nextrarc; } s[v]=1;path[v]=v;dist[v]=0; for(i=0; i<aGraph->n; i++) { mindis=INF; for(j=0; j<aGraph->n; j++) { if(s[j]==0&&dist[j]<mindis) { u=j; mindis=dist[j]; } } s[u]=1; for(j=0; j<aGraph->n; j++) { if(s[j]==0) { EdgeNode* temEdge=isEdge(&(aGraph->adjlist[u]), &(aGraph->adjlist[j])); if(temEdge!=NULL) { if((dist[u]+temEdge->info)<dist[j]) { dist[j]=dist[u]+temEdge->info; path[j]=u; } } } } } Dispath(dist,path,s,aGraph,v); } void Dispath(int dist[], int path[], int s[], ALGraph* aGraph, int v) { int i; for(i=0; i<aGraph->n; i++) { printf("%c->%c(distance is %d) %c", aGraph->adjlist[v].vexdate, aGraph->adjlist[i].vexdate,dist[i],aGraph->adjlist[v].vexdate); privatePrintPath(aGraph,path,i,v); printf(" "); } } void privatePrintPath(ALGraph* aGraph, int path[], int curr, int v) { char temChar=aGraph->adjlist[curr].vexdate; int temPos=curr; if(curr!=v) { privatePrintPath(aGraph,path,path[temPos],v); printf(" ->%c",temChar); } } void showGraph(ALGraph* aGraph) { int i=0; for(i=0; i<aGraph->n; i++) { EdgeNode* pos; printf(" %c->",aGraph->adjlist[i]); pos=aGraph->adjlist[i].firstarc; while(pos!=NULL) { printf(" %d ",pos->adjvex); pos=pos->nextrarc; } printf(" "); } } void addBody(char aChar, int aPos, ALGraph* aGraph, int weight) { int inversePos; EdgeNode* node=(EdgeNode*) malloc(sizeof(EdgeNode)); node->info=weight; if((node->adjvex=mFind(aChar,aGraph))==-1) node->adjvex=createHead(aChar,aGraph); node->hostvex=aPos; node->nextrarc=NULL; if(aGraph->adjlist[aPos].firstarc==NULL) aGraph->adjlist[aPos].firstarc=node; else { EdgeNode* tail=aGraph->adjlist[aPos].firstarc; while(tail->nextrarc!=NULL) tail=tail->nextrarc; tail->nextrarc=node; } aGraph->e++; inversePos=node->adjvex; node=(EdgeNode*) malloc(sizeof(EdgeNode)); node->info=weight; node->hostvex=inversePos; node->adjvex=aPos; node->nextrarc=NULL; if(aGraph->adjlist[inversePos].firstarc==NULL) aGraph->adjlist[inversePos].firstarc=node; else { EdgeNode* tail=aGraph->adjlist[inversePos].firstarc; while(tail->nextrarc!=NULL) tail=tail->nextrarc; tail->nextrarc=node; } aGraph->e++; } int createHead(char aChar, ALGraph* aGraph) { int currPos=aGraph->n; aGraph->adjlist[currPos].vexdate=aChar; aGraph->adjlist[currPos].pos=currPos; aGraph->n++; return currPos; } int mFind(char aChar, ALGraph* aGraph) { int i=0; for(i=0; i<aGraph->n; i++) { if(aChar==aGraph->adjlist[i].vexdate) return i; } return -1; } int initGraph(ALGraph* aGraph) { int i=0; aGraph->e=0; aGraph->n=0; for(i=0; i<MaxVertexNum; i++) { aGraph->adjlist[i].firstarc=NULL; } return 0; }
在VC2010中 C++控制台程序执行的结果:例如以下图所看到的: