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. Lighting System Design

    题意:从小到大给出额定功率,给出该功率费用,和灯泡的数量和单价,现在灯泡能在比他额定功率大的功率运行,求让所有灯泡正常工作的最小费用 分析: 问题转化为求用哪几个功率运行灯泡最小费用,dp[i]前i个 ...

  2. CSAPP(1):数字的计算机表示——课后题

    2.65 int even_ones(unsigned x) 要求:return 1 when x contains an even number of 1s; 0 otherwise. 假设int ...

  3. PHP:PHP5.4连接SQLSERVER

    在PHP5.4的环境下要连接SQLSERVER(2005/2008)数据库,需要以下步骤: 1.下载PHP5.4连接SQLSERVER的驱动(两个动态连接库)http://www.microsoft. ...

  4. Mahout应用(一)

    Mahout应用(一) Mahout 是应用于hadoop上的数据挖掘工具(废话不多说) 这里先简单介绍一下mahout的一般使用方法. 拿kmeans为列子 Mahout中的kmeans所需要的输入 ...

  5. 【sgu282】Isomorphism

    题意: 给出n(n<=53)点的无向完全图 要将每条边染上m(m<=1000)种颜色的一种 只改变顶点编号的图视为同种方案 求本质不同方案数%p(p>n且为质树)的值 题解: 这题貌 ...

  6. 在Windows上,如何卸载RabbitMQ服务

    打开运行->CMD->sc delete RabbitMQ 如果报错..... 打开运行->regedit 找到RabbitMQ节点,删掉即可.(右侧看到的都是启动服务时,需要的配置 ...

  7. mysql repair data 语句

    1. 这条语句主要是用来修复一个表中的数据 , 在另一个统计表中没有统计时,进行修改统计表的操作 update expert_count ec inner join ( select sum(e.EF ...

  8. ORM 是一种讨厌的反模式

    本文由码农网 – 孙腾浩原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! (“Too Long; Didn’t Read.”太长不想看,可以看这段摘要 )ORM是一种讨厌的反模式,违背 ...

  9. Android实例-获取安卓手机WIFI信息(XE8+小米2)

    结果: 1.必须打开Access wifi state权限,不打开权限会出图二的错误. 相关资料: http://blog.csdn.net/lyf_lyf/article/category/1735 ...

  10. 关于Aazure 使用以前保留的vhd创建虚拟机的基本步骤

    1. 删除vm保留vhd(只删除虚拟机记录,不删除磁盘)2. 拷贝vhd以及status文件到指定的存储账号3. 使用拷贝的VHD创建disk4. 从disk创建vm,指定指定vnet以及cloud ...