Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径,主要特点是以起点为中心向外层扩展,直到扩展到终点为止.该算法要求图中不存在负权边.
设G=(V,E)是一个带权的有向图, 把图中顶点集合分为两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径,就将加入到集合S中,直到全部顶点都加到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按照最短路径长度的递增次序依次把第二组的顶点加入到S中,在加入过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度, 此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包含S中的顶点为中间顶点的当前最短路径长度.
代码如下:
void Dijkstra(AdjList *G,int start,int disk[],int path[][MAXVEX]) { int i,j,mindist,k,t; ArcNode *p; for(i=1;i<=G->vexnum;i++){ //初始化最短路径数组disk,和标记此顶点是否已经找到最短路径的path[i][0],等于0表示没有找到,等于1表示找到. disk[i]=INFINE; path[i][0]=0; } p=G->vertex[start].head->next; while(p){ //保存源点到和此源点相关的顶点的路径. disk[p->adjvex]=p->weight; path[p->adjvex][1]=start; path[p->adjvex][2]=p->adjvex; path[p->adjvex][3]=0; p=p->next; } path[start][0]=1; //源点标记为为1,其最短路径为0.此顶点以后不会再用到 for(i=2;i<=G->vexnum;i++){ //选择最最短的路径 mindist=INFINE; for(j=1;j<=G->vexnum;j++){ if(!path[j][0] && disk[j] < mindist){ k=j; mindist=disk[j]; } } if(mindist == INFINE){ //如果没有找到最短的路径,则说明从此源点不能到任何其他顶点,直接返回. return; } path[k][0]=1; //标记找到最小路径的顶点,此顶点以后不会再用到. p=G->vertex[k].head->next; while(p){ if(!path[p->adjvex][0]&& disk[p->adjvex] > disk[k]+ p->weight){ //更新disk,使其从保持从源点到和此顶点相关的顶点的路径最短. //printf("p->ad:%d ",p->adjvex); disk[p->adjvex]=disk[k]+p->weight; t=1; while(path[k][t]!=0) //记录最新的路径 { path[p->adjvex][t]=path[k][t]; t++; } path[p->adjvex][t]=p->adjvex; path[p->adjvex][t+1]=0; //path[i][t+1]之前的都是最短路径所要经过的顶点,从t+1这里停止,作为最后输出路径的判断条件 } p=p->next; } } }
完整代码详见:https://github.com/liuhangyang/Data_Structure_and_Algorithm/blob/master/%E7%AC%AC%E4%B8%83%E7%AB%A0/linjiebiao.c