小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
迪杰斯塔拉算法(二)2.2 - 掘金 (juejin.cn)
2.3
根据之前的分析,我们已经得出了代码的大部分构建思路了。现在给出代码。
代码
初始化d数组
int i,j;
for(i=0;i<5;i++){
d[i]=999;
}
d[s]=0;
更新d数组
int x=s;
for(i=0;i<4;i++){
for(j=0;j<5;j++){
if( (g[x][j]+d[x])<d[j]){
d[j]=g[x][j]+d[x];
}
}
d[x]=-d[x];
确定下一点
int k=0;
while(d[k]<=0) k++;
int pos=k;
int value=d[k];
for(;k<5;k++){
if(d[k]<value&&d[k]>0){
pos=k;
value=d[k];
}
}
x=pos;
整体函数代码
void dij(int g[5][5],int s,int d[5]){
int i,j;
for(i=0;i<5;i++){
d[i]=999;
}
d[s]=0;
int x=s;
for(i=0;i<4;i++){
for(j=0;j<5;j++){
if( (g[x][j]+d[x])<d[j]){
d[j]=g[x][j]+d[x];
}
}
d[x]=-d[x];
int k=0;
while(d[k]<=0) k++;
int pos=k;
int value=d[k];
for(;k<5;k++){
if(d[k]<value&&d[k]>0){
pos=k;
value=d[k];
}
}
x=pos;
}
d[x]=-d[x];
}
输出路径
我们现在有了s点到各点的最短路径数组d,但我仍然需要将路径表示出来。我们可以设置一个数组p[5]表示各个节点的前驱。
因为表示的是前驱,所以我们先将p初始化。
p[s]=-1;
这里只用把p[s]置为-1就行了。另外的一个重点就是p的取值时机,经过分析后,我们可以清楚,p的更新与d的更新是保持一致的。因此我们在代码中加上print(p)的函数和主程序后,代码如下:
#include<stdio.h>
#include<stdlib.h>
char str[5]={'s','t','x','y','z'};
void print(int s,int e,int p[]);
void dij(int g[5][5],int s,int d[5],int p[5]){
int i,j;
for(i=0;i<5;i++){
d[i]=999;
}
d[s]=0;
p[s]=-1;
int x=s;
for(i=0;i<4;i++){
for(j=0;j<5;j++){
if( (g[x][j]+d[x])<d[j]){
d[j]=g[x][j]+d[x];
p[j]=x;
}
}
d[x]=-d[x];
int mm;
/*for(mm=0;mm<5;mm++)
printf("%d ",d[mm]);
printf("\n");*/
int k=0;
while(d[k]<=0) k++;
int pos=k;
int value=d[k];
for(;k<5;k++){
if(d[k]<value&&d[k]>0){
pos=k;
value=d[k];
}
}
x=pos;
}
d[x]=-d[x];
int e=4;
while(e>0){
print(0,e,p);
e--;
}
}
void print(int s,int e,int p[]){
int i=e;
printf("%c",str[i]);
while(p[i]!=-1){
printf(" <- %c",str[p[i]]);
i=p[i];
}
printf("\n");
}
int main(){
int g[5][5]={
{999,6,999,4,999},
{999,999,3,2,999},
{999,999,999,999,4},
{999,1,9,999,3},
{7,999,5,999,999}
};
int s=0;
int d[5];
int p[5];
dij(g,s,d,p);
}
输出结果: