算法学习no1---Dijkstra 方法
1.变量说明:
符号:
V:所求图的点集;
vj:标号为j的点;
E:所求图的边集;
e(i,j):从vi到vj的边;
w(i,j):vi到vj的权重
变量:
i:循环变量
k:当前循环中的点号
建立标记数组
T[k]:点k的暂时权值用于后续比较
P[k]:点k最终的最短权值即最短路径
S(i):表示第i步时,有P标点号的点集
λ[k]:所求点到达点k的路径上,点k的前一个点
2.算法步骤:
a.初始化:
i=0;
S(i)={v0};//假设求v0到其他各点的最短路径
p[0]=0;
λ[0]=0;
for(j=1;j<n;j++)
{
T[j]=+∞;
λ[j]=+∞;
}
k=0;
b.if(S(i)==V) end program;//如果V中所有点完全遍历,算法结束,
//最短路径d(0,v)=p(v);
else goto c;
c.while(e(vk,vj)∈A&&!vj∈S(i))//考查每条从点k出发的边且终点不在S中的终点vj
{
if(T[j]>P[k]+w(k,j))
{
T[j]=P[k]+w(k,j);
λ[j]=k;
}
}
goto d;
d. int t,n;
t=NUM OF min(T[]);//取出T集合中最小值的标号
n=min(T[]);//取出T集合中最小值。
if(n<+∞)
{
T[t]=+∞;//删除T标记
P[t]=n;//该点改为P标记,表示到该点的最短路径已找到。
S(i+1)=S(i)∪{vt};//将该点添加到S集合中
i++;
k=t;//下次循环将从t点开始。
goto b;
}
else end of program;
#include<stdio.h>
#include<stdlib.h>
#define MAX 99999
#define SIZE 700
typedef struct node{
int v;
struct node *next;
}*snode;
int exist(snode s,int j);//判断点j是否在s中存在
int mint(int T[SIZE],int n);//T集合中最小值的标号
int main()
{
int n,m;
int i,j;
int a[SIZE][SIZE];//邻接矩阵
int u,v,l;
snode s;//记录点集
snode p;
int P[SIZE];
int T[SIZE];
int f[SIZE];//lambda
int k;
int count;//s中的点数
s = (snode)malloc(sizeof(struct node));
s->next=NULL;
scanf("%d %d",&n,&m);
for(i=0;i<SIZE;i++)
{
for(j=0;j<SIZE;j++)
{
a[i][j]=MAX;
}
}
for(i=0;i<m;i++)
{
scanf("%d %d %d",&u,&v,&l);
a[u][v]=l;
}
//初始化:
s->next=(snode)malloc(sizeof(struct node));
p=s->next;
p->v=1;
//printf("%d->",s->v);
p->next=NULL;
count=1;
P[1]=0;
f[1]=1;
for(j=2;j<=n;j++)
{
T[j]=MAX;
f[j]=MAX;
}
k=1;
//1
while(count!=n) //如果V中所有点完全遍历,算法结束,
{
//2
j=1;
if(j==k) j++;
while(j<=n)//考查每条从点k出发的边且终点不在S中的终点vj
{
if(a[k][j]!=MAX&&exist(s,j)==0)
{
if(T[j]>P[k]+a[k][j])
{
T[j]=P[k]+a[k][j];
f[j]=k;
}
}
j++;
}
//3
int t,t1;
t=mint(T,n);//取出T集合中最小值的标号
t1=T[t];//取出T集合中最小值。
if(n<MAX)
{
T[t]=MAX;//删除T标记
P[t]=t1;//该点改为P标记,表示到该点的最短路径已找到。
//将该点添加到S集合中
count++;
p->next=(snode)malloc(sizeof(struct node));
p=p->next;
p->v=t;
//printf("%d->",s->v);
p->next=NULL;
k=t;//下次循环将从t点开始。
}
else break;
}
for(i=2;i<=n;i++)
{
printf("%d\n",P[i]);
}
return 0;
}
int exist(snode s,int j)//判断点j是否在s中存在
{
snode p;
p=s;
while(p->next!=NULL)
{
if(j==s->v)return 1;
p=p->next;
}
return 0;
}
int mint(int T[SIZE],int n)//T集合中最小值的标号
{
int i;
int min;
int no;
min=9999;
for(i=2;i<=n;i++)
{
if(T[i]<min)
{
min=T[i];
no=i;
}
}
return no;
}