【算法导论05】贪心算法-Dijkstra算法

05贪心算法-Dijkstra算法

问题描述:
请设计一个算法,实现在一个有向图中,给出一个源点,计算该源点到其他所有顶点的单源最短路径。

算法描述:
Dijkstra算法的目的是寻找单源最短路径,其具有以下最优子结构性质:最短路径上的子路径也是两个顶点的最短路径,此性质可以用cut&paste反证(见笔记),因此,该算法满足贪心算法性质,局部最优解也是全局最优解,属于贪心算法的一种。基于此思想,若想找到源点s到v的最短路径,只需要找到s到u的最短路径+u到v的最短路径,u是s到v最短路径上的一个顶点。

变量定义:
s:源点
w[i][j]:i到j的最短路径
S[i]:i点是否加入最短路径集合,=1,加入;=0,未加入。
d[i]:源点到i点的距离
n:顶点个数
m:边个数

算法描述:
设G为包含图中所有顶点的集合,S为包含最短路径顶点的集合。源点s一定在S中(距离为0),算法的目的就是从g中找到到s点距离最短的顶点集合,并将它们加入S中。
源点到i 的最短路径 = d[v]+w[v][i];

笔记:(-from MIT算法导论课程)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Dijkstra算法代码:

//dijkstra算法
#include<stdio.h>
#include<stdlib.h>

int w[1000][1000];//i到j的最短路径
int S[1000],d[1000];//最短路径点集合,0:没有加入 1:加入;源点到i最短路径
int n,m;//n个点,m条边

void init(){
	
	//所有点初值设置为∞
	for(int i=0;i<1000;i++)
		for(j=0;j<1000;j++)
			w[i][j] = 65535;
		
	//自己到自己的距离是0		
	for(int x=0;x<n;x++)
		w[x][x] = 0;
}

void getg(){
	int u,v,w;//u、v点,权值w
	for(int t=1;t<=n;t++){
		scanf("%d%d%d",&u,&v,&w);
		if(w[u][v]>w){
			w[u][v] = w;
			w[v][u] = w;
		}
	}
	
}

void dijkstra(int s){
	for(int y=0;y<1000;y++)
	S[y] = 0;//初始没有最短路径顶点加入
	
	//将源点s到所有顶点的距离放到d数组中
	for (int t=1;t<n;t++)
		d[t] = w[s][t];
	
	S[s] = 1;//表不为空,因为存在源点到源点
	
	//对所有点进行循环,其中包含两个循环,一个用来找源点到目标点最短路径,另一个用来更新源点到目标点的最短路径
	forint x=1;x<n;x++{
	int min = 65535,temp=0;
	for(int i=1;i<n;i++){
		if(!S[i]&&d[i]<min){//点没有加入并且比上一个距离小
			min = d[i];
			temp = i;//临时存放最短路径点
		}
		S[tmep]=1;//最短路径点已经加入;
	}
	
	for(int i=1;i<=n;i++){
		if(d[temp]+w[temp][i]<d[i])//只有当源点到最短路径点距离+最短路径到该点距离<源点到该点距离时,才对d数组进行更新
			d[i] = d[temp]+w[temp][i];
	}
		
}
}
}
int main(){
	printf("请输入顶点个数和边的个数:\n");
	scanf("%d%d",&n,&m);
	
	init();
	getg();
	int s;
	scanf("%d",&s);//源点
	dijkstra(s);

	return 0;
	
}

20201022更新:
该算法简述:每次都从原点出发,遍历所有没有加入最短路径的顶点,并找到权值最小的顶点,加入最短路径,然后更新改顶点到其他顶点距离,每次可以找到一个最短路径顶点。最后循环该过程n次,n为顶点个数。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值