Dijkstra最短路径算法[贪心]
Dijkstra算法的标记和结构与prim算法的用法十分相似。它们两者都会从余下顶点的优先队列中选择下一个顶点来构造一颗扩展树。但千万不要把它们混淆了。它们解决的是不同的问题,因此,所操作的优先级也是以不同的方式计算的:Dijkstra算法比较路径的长度,因此必须把边的权重相加,而prim算法则直接比较给定的权重。
源最短路径问题
给定一个带权有向图 G=(V,E) ,其中每条边的权是一个非负实数。另外,还给定 V 中的一个顶点,称为源。现在我们要计算从源到所有其他各顶点的最短路径长度。这里的长度是指路上各边权之和。这个问题通常称为单源最短路径问题。
前面Bellman-Ford最短路径算法讲了单源最短路径的Bellman-Ford算法(动态规划算法)。这里介绍另外一个更常见的算法Dijkstra算法。
Dijkstra算法和 最小生成树Prim算法最小生成树算法非常类似,大家可以先熟悉下个算法。两个算法都是基于贪心算法。虽然Dijkstra算法相对来说比Bellman-Ford 算法更快,但是不适用于有负权值边的图,贪心算法决定了它的目光短浅。而Bellman-Ford 算法从全局考虑,可以检测到有负权值的回路。
这里模仿MST(Minimum Spanning Tree)的Prim算法,我们创建一个SPT(最短路径树),最初只包含源点。我们维护两个集合,一组已经包含在SPT(最短路径树)中的顶点S集合,另一组是未包含在SPT内的顶点T集合。每次从T集合中选择到S集合路径最短的那个点,并加入到集合S中,并把这个点从集合T删除。直到T集合为空为止。
举例说明,如下图所示的图:

S集合最初为空,然后选取源点0,S集合为 {0},源点到其它所有点的距离为 {0, 4, INF, INF, INF, INF, 8, INF} 。图中蓝色表示 SPT,迭代的过程如下

最终得到 SPT(最短路径树) 如下:

算法C++实现:
我们使用Boolean 数组sptSet[] (也有习惯用visit[]命名,表示是否访问过),来表示顶点是否为有SPT中。sptSet[v]=true,说明顶点v在SPT中。 dist[] 用来存储源点到其它所有点的最短路径。
#include<iostream>
#include<stdio.h>
#include<limits.h>
using namespace std; const int V=;
//从未包含在SPT的集合T中,选取一个到S集合的最短距离的顶点
int getMinIndex(int dist[V],bool sptSet[V])
{
int min=INT_MAX,min_index;
for(int v=;v<V;v++)
{
if(!sptSet[v]&&dist[v]<min)
min=dist[v],min_index=v;
}
return min_index;
} //打印结果 void printSolution(int dist[],int n)
{
printf("Vertex Distance from Source\n");
for(int i=;i<V;i++)
printf("%d\t\t %d\n",i,dist[i]);
} //source 代表顶点
void dijkstra(int graph[V][V],int source)
{
int dist[V];// 存储结果,从源点到 i的距离
bool sptSet[V]; // sptSet[i]=true 如果顶点i包含在SPT中 // 初始化. 0代表不可达
for(int i=;i<V;i++)
{
dist[i]=(graph[source][i]==)?INT_MAX:graph[source][i];
sptSet[i]=false;
}
// 源点,距离总是为0. 并加入SPT
dist[source]=;
sptSet[source]=true; // 迭代V-1次,因此不用计算源点了,还剩下V-1个需要计算的顶点。
for(int count=;count<V-;count++)
{
// u,是T集合中,到S集合距离最小的点,u开始在T集合中,然后加入到S集合
int u=getMinIndex(dist,sptSet);
// 加入SPT中
sptSet[u]=true;
for(int v=;v<V;v++)
{
//满足以下4个条件
//1. 点v还没有加入到spt中
//2. 点u和v之间可达
//3. 点u是可达的,距离不是无穷
//4. 经过点u之后的距离小于直接到达点v的距离
if(!sptSet[v]&&graph[u][v]&&dist[u]!=INT_MAX&&dist[u]+graph[u][v]<dist[v])
dist[v]=dist[u]+graph[u][v];
}
}
printSolution(dist,V);
} int main()
{
int graph[V][V]={ { , , , , , , , , },
{ , , , , , , , , },
{, , , , , , , , },
{ , , , , , , , , },
{ , , , , , , , , },
{ , , , , , , , , },
{ , , , , , , , , },
{ , , , , , , , , },
{ , , , , , , , , }
}; dijkstra(graph, ); return ;
}
运行结果如下:输出源点0到其它各个顶点的最短距离:

Dijkstra最短路径算法[贪心]的更多相关文章
- 数据结构(c++)(第二版) Dijkstra最短路径算法 教学示范代码出现重大问题!
前言 去年在数据结构(c++)的Dijkstra教学算法案例中,发现了一个 bug 导致算法不能正常的运行,出错代码只是4行的for循环迭代代码. 看到那里就觉得有问题,但书中只给了关键代码的部分,其 ...
- Java邻接表表示加权有向图,附dijkstra最短路径算法
从A到B,有多条路线,要找出最短路线,应该用哪种数据结构来存储这些数据. 这不是显然的考查图论的相关知识了么, 1.图的两种表示方式: 邻接矩阵:二维数组搞定. 邻接表:Map<Vertext, ...
- 练习 Dijkstra 最短路径算法。
练习 Dijkstra 最短路径算法. #coding: utf-8 # Author: woodfox, Oct 14, 2014 # http://en.wikipedia.org/wiki/Di ...
- 一篇文章讲透Dijkstra最短路径算法
Dijkstra是典型最短路径算法,计算一个起始节点到路径中其他所有节点的最短路径的算法和思想.在一些专业课程中如数据结构,图论,运筹学等都有介绍.其思想是一种基础的求最短路径的算法,通过基础思想的变 ...
- Python 图_系列之纵横对比 Bellman-Ford 和 Dijkstra 最短路径算法
1. 前言 因无向.无加权图的任意顶点之间的最短路径由顶点之间的边数决定,可以直接使用原始定义的广度优先搜索算法查找. 但是,无论是有向.还是无向,只要是加权图,最短路径长度的定义是:起点到终点之间所 ...
- Dijkstra 最短路径算法 秒懂详解
想必大家一定会Floyd了吧,Floyd只要暴力的三个for就可以出来,代码好背,也好理解,但缺点就是时间复杂度高是O(n³). 于是今天就给大家带来一种时间复杂度是O(n²),的算法:Dijkstr ...
- Dijkstra最短路径算法实例
#include <stdio.h>#include <stdlib.h>/* Dijkstra算法 */#define VNUM 5#define MV 65536int P ...
- 关于Dijkstra最短路径算法
Dijkstra算法,不是很明白,今天找了一些博客看了一下,决定自己也写一个为以后忘记的时候可以看做准备. 实际上,如果理解没错的话,该算法实际上和枚举法有点像,只不过,在选取出发路径的路径都是最短路 ...
- SRM 583 Div II Level Three:GameOnABoard,Dijkstra最短路径算法
题目来源:http://community.topcoder.com/stat?c=problem_statement&pm=12556 用Dijkstra实现,之前用Floyd算法写了一个, ...
随机推荐
- 【转】Ofbiz学习经验谈
不可否认,OFBiz这个开源的系统功能是非常强大的,涉及到的东西太多了,其实对我们现在而言,最有用的只有这么几个:实体引擎.服务引擎.WebTools.用户权限管理.最先要提醒各位的是,在配置一个OF ...
- 微信多媒体上传图片,创建卡券上传 LOGO
//*****************************************多媒体上传图片 begin******************************************** ...
- List转换成Json、对象集合转换Json等
#region List转换成Json /// <summary> /// List转换成Json /// </summary> public static string Li ...
- Python 笔记 : 类和继承
# -*- coding= utf-8 -*- # 文件编码定义的语法规则是: coding[:=]/s*([-/w.]+) # 未指定编码将默认为 : ASCII # 同时要注意物理文件的编码也要 ...
- [.NET源码学习]实例化Font,遭遇字体不存在的情况。
实例化Font类时,当传入参数为不存在或未安装的字体时,Windows系统会用Microsoft Sans Serif字体替代该字体. Msdn: "For more information ...
- 使用jQuery Mobile实现通讯录
jQuery Mobile 通讯录 拨打电话作者:方倍工作室 地址: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional/ ...
- mvc bundle功能(2)
配置好Bundle,注册好之后,再是调用 <head> <meta charset="utf-8"> <meta http-equiv="X ...
- hive-mysql安装配置
默认情况下,hive的元数据信息存储在内置的Derby数据中.Facebook将hive元数据存储在关系数据库 1.安装好mysql ,sudo apt-get install mysql-serve ...
- Linux服务器集群系统(一)(转)
add by zhj:虽然是2002年的文章,但读来还是收益良多.在 章文嵩:谈LVS及阿里开源背后的精彩故事 中LVS发起人及主要贡献者谈了LVS的开发过程及阿里开源的一些故事 原文:http:// ...
- cocos2d-x 3.0 创建工程的模板
将下面的代码拷贝到文本文件中,重命名文件为 cocos3.0创建工程.bat @echo off echo -------------------------create project with p ...