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最短路径算法[贪心]的更多相关文章

  1. 数据结构(c++)(第二版) Dijkstra最短路径算法 教学示范代码出现重大问题!

    前言 去年在数据结构(c++)的Dijkstra教学算法案例中,发现了一个 bug 导致算法不能正常的运行,出错代码只是4行的for循环迭代代码. 看到那里就觉得有问题,但书中只给了关键代码的部分,其 ...

  2. Java邻接表表示加权有向图,附dijkstra最短路径算法

    从A到B,有多条路线,要找出最短路线,应该用哪种数据结构来存储这些数据. 这不是显然的考查图论的相关知识了么, 1.图的两种表示方式: 邻接矩阵:二维数组搞定. 邻接表:Map<Vertext, ...

  3. 练习 Dijkstra 最短路径算法。

    练习 Dijkstra 最短路径算法. #coding: utf-8 # Author: woodfox, Oct 14, 2014 # http://en.wikipedia.org/wiki/Di ...

  4. 一篇文章讲透Dijkstra最短路径算法

    Dijkstra是典型最短路径算法,计算一个起始节点到路径中其他所有节点的最短路径的算法和思想.在一些专业课程中如数据结构,图论,运筹学等都有介绍.其思想是一种基础的求最短路径的算法,通过基础思想的变 ...

  5. Python 图_系列之纵横对比 Bellman-Ford 和 Dijkstra 最短路径算法

    1. 前言 因无向.无加权图的任意顶点之间的最短路径由顶点之间的边数决定,可以直接使用原始定义的广度优先搜索算法查找. 但是,无论是有向.还是无向,只要是加权图,最短路径长度的定义是:起点到终点之间所 ...

  6. Dijkstra 最短路径算法 秒懂详解

    想必大家一定会Floyd了吧,Floyd只要暴力的三个for就可以出来,代码好背,也好理解,但缺点就是时间复杂度高是O(n³). 于是今天就给大家带来一种时间复杂度是O(n²),的算法:Dijkstr ...

  7. Dijkstra最短路径算法实例

    #include <stdio.h>#include <stdlib.h>/* Dijkstra算法 */#define VNUM 5#define MV 65536int P ...

  8. 关于Dijkstra最短路径算法

    Dijkstra算法,不是很明白,今天找了一些博客看了一下,决定自己也写一个为以后忘记的时候可以看做准备. 实际上,如果理解没错的话,该算法实际上和枚举法有点像,只不过,在选取出发路径的路径都是最短路 ...

  9. SRM 583 Div II Level Three:GameOnABoard,Dijkstra最短路径算法

    题目来源:http://community.topcoder.com/stat?c=problem_statement&pm=12556 用Dijkstra实现,之前用Floyd算法写了一个, ...

随机推荐

  1. <转>写给浮躁的IT同仁(请不要做浮躁的人)

    1.不要看到别人的回复第一句话就说:给个代码吧!你应该想想为什么.当你自己想出来再参考别人的提示,你就知道自己和别人思路的差异. 2.初学者请不要看太多太多的书那会误人子弟的,先找本系统的学,很多人用 ...

  2. linux 常用命令基础

    linux常用的命令 shell 是命令语句,命令解释程序以及程序设计语言的统称,它不仅仅拥有自己内建的shell命令集,同时也能被系统中其他应用程序所调用 shell 的一个重要特性是它本身就是一个 ...

  3. 【原】Kryo序列化篇

    Kryo是一个快速有效的对象图序列化Java库.它的目标是快速.高效.易使用.该项目适用于对象持久化到文件或数据库中或通过网络传输.Kryo还可以自动实现深浅的拷贝/克隆. 就是直接复制一个对象对象到 ...

  4. CentsOS7 网络自动启动

    虚拟机中安装完成CentOS7后,网络总是需要手工启动才可使用,设置为自动连接的方式如下: cd /etc/sysconfig/network-scripts/ls #找到类似的文件:ifcfg-et ...

  5. Codeforces Round #375 (Div. 2) ABCDE

    A - The New Year: Meeting Friends 水 #include<iostream> #include<algorithm> using namespa ...

  6. Java IO (4) - Writer

    Java IO (4) - Writer 前言 JavaIO一共包括两种,一种是stream,一种是reader/writer,每种又包括in/out,所以一共是四种包.Java 流在处理上分为字符流 ...

  7. log4j中的MDC和NDC

    NDC和MDC NDC(Nested Diagnostic Context)和MDC(Mapped Diagnostic Context)是log4j种非常有用的两个类,它们用于存储应用程序的上下文信 ...

  8. HDU 3966 Aragorn's Story (树链点权剖分,成段修改单点查询)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 树链剖分的模版,成段更新单点查询.熟悉线段树的成段更新的话就小case啦. //树链剖分 边权修 ...

  9. 解决iPhone上select时常失去焦点,随意跳到下一个输入框,影响用户操作

    window.addEventListener('load', function() { FastClick.attach(document.body); }, false); //300s延迟,解决 ...

  10. 漫谈云计算与SOA (1)

    SOA是什么? 英语直译是基于服务的架构,就是一种技术框架,促使企业内部与外部所有相关的系统公开和访问定义良好的服务和绑定于服务的信息,进一步抽象成流程层和组合应用,从而构成解决方案. 说人话:重用服 ...