您的位置:首页 > 其它

dijkstra算法求最短路径

2016-10-27 18:39 176 查看
希望大家能看完prim算法后再来看这个算法,因为两者思路差不多。

先来看一下自定义的结构体

typedef char VexType;
typedef int AdjType;
typedef struct{
int n;
VexType vexs[MaxNode];//保存节点
AdjType arcs[MaxNode][MaxNode];//从矩阵获得节点与节点间的距离
}GraphMatrix;
typedef struct{
AdjType length;//边长
int prevex;//先驱节点
}path;


主程序

void main()
{
GraphMatrix *mygraph;
path *mydist;
//  Edge *mymst;
mygraph = (GraphMatrix*)malloc(sizeof(GraphMatrix));
//mymst = (Edge*)malloc(sizeof(Edge));
mydist = (path*)malloc(sizeof(path));
CreateGraph(mygraph,6);
printf("testing creategraph\n");
dijkstra(mygraph,mydist);
printf("testing dijkstra:\n");
print_path(mygraph,mydist);

}


creategraph函数是从txt里读取矩阵的函数,我写在了prim算法的帖子里,大家可以去看一下,这里就不说了。

来看一下dikstra算法

void dijkstra(GraphMatrix *graph,path *dist)
{
int i,j,min;
AdjType minw;
dist[0].length = 0;
dist[0].prevex = 0;
graph->arcs[0][0] = 1;//表示v0加入集合
for(i=1;i<graph->n;i++)//从V1节点开始
{
dist[i].length = graph->arcs[0][i];//初始化v0到各个节点的距离
if(dist[i].length!=Max)
{
dist[i].prevex = 0;//不等于Max说明V0可以到Vi节点
}
else
{
dist[i].prevex = -1;//V0到Vi没有路径
}
}
for(i=1;i<graph->n;i++)//一次循环就会找到V0到其中一个顶点的最短距离,所以循环节点数-1次
{
minw = Max;
min = 0;
for(j=1;j<graph->n;j++)
{
if((graph->arcs[j][j]==0)&&(dist[j].length<minw))//==0说明节点j还未加入
{
minw = dist[j].length;
min = j;
}
}
if(min==0)//如果都不等于0,说明所有节点都已加入,也就是已经调整好了,如果都大于minw说明所有路径已经达到最短
{
break;
}
graph->arcs[min][min]=1;//将顶点为min的顶点加入集合,此时V0到Vmin的节点的最短距离已经找到,下面
b431
进行调整时就是判断通过Vmin点再到其他点距离是否会减少
for(j=1;j<graph->n;j++)
{
if(graph->arcs[j][j]==1)
{
continue;//V0到节点Vi的最短路径已经找到,不在进行调整
}
if(dist[j].length>dist[min].length+graph->arcs[min][j])//V0到Vmin的距离+Vmin到Vj的距离
{
dist[j].length = dist[min].length+graph->arcs[min][j];//变更路径长度
dist[j].prevex = min;//V0到Vj的先驱节点从V0变更成Vmin
}
}
}
}


dist数组的元素是V0节点到其他各点的路径。如果二维数组的graph->arcs[i][i]的值为0,说明此时Vi节点还没加入我们的判断范围,就是说我们求得最短路径里不能经过Vi节点,所以我们一开始默认V0节点加入判断范围,也就是说,我们求得路径就是V0节点到其他节点的最短路径,所以for循环是从1开始的。以为不用求V0到V0的最短路径

先初始化V0到其他各节点的距离,这些距离是从txt里存储的矩阵中读取的。如果两个节点之间没有路径,就默认路径距离为1000.路径前驱节点为-1.

1.初始化完成后,进行fo循环来寻找最短路径。先找一条最短路径(当前数组元素里length最小的).if((graph->arcs[j][j]==0)&&(dist[j].length

void print_path(GraphMatrix* graph, path* dist)
{
int i,j;
for(i=1;i<graph->n;i++)
{
j = i;
if(dist[i].length==Max)
{
printf("V0到V%d没有路径\n",i);//设定床为MAX说明没有路径
}
else
{
printf("V%d到V0的路径为:  %d ",i,i);
while(dist[j].prevex!=0)//Vj的前驱节点不是V0说明经过其他节点Vx,V0到Vx的路径中的前驱节点为dist[j].prevex,循环验证
{
printf("%d ",dist[j].prevex);
j = dist[j].prevex;
}
printf("0");
printf("\nV%d到V0的路径长度为%d\n",i,dist[i].length);
printf("\n\n");
}
}
}


这里其实就是把数组元素的一些成员打印出来。数组下标i就代表V0到Vi的最短路径.

需要说明两点.

1.上面已经提到了,如果路径长度等于MAX(1000)。说明两个节点之间没有路径。

2.我们找的最短路径是V0到其他节点的最短路径。如果第i条路径的前驱节点不是V0,假设为Vj,说明V0到这个节点的最短路径是经过其他节点的。这个时候我们还要找第J条路径,就这样往前找,知道前驱节点为V0.

最后看一下运行截图

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