Dijkstra 算法概述

算法学习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;
}





                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值