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算法写了一个, ...
随机推荐
- bjfu1250 模拟
这题貌似是蓝桥杯的一题改了个题面. 就是模拟啦,应该有比我的更简洁的方法. 我的方法是把所有的人(蚂蚁)按位置排完序以后从左往右看,每次有一个向左走的,就会把最左边的t出,这个变成向右中,同时,从左端 ...
- SQL 的一些概念问答
1.触发器的作用? 答:触发器是一中特殊的存储过程,主要是通过事件来触发而被执行的.它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化.可以联级运算.如, ...
- 白盒测试之gmock入门篇
一.gmock是什么 gmock是google公司推出的一款开源的白盒测试工具.gmock是个很强大的东西,测试一个模块的时候,可能涉及到和其他模块交互,可以将模块之间的接口mock起来,模拟交互过程 ...
- CSS基础知识—【结构、层叠、视觉格式化】
结构和层叠 选择器的优先级顺序: style[内联元素]选择器>Id选择器>类选择器 属性选择器>元素选择器>通配器选择器 重要性:@important 有这个标记的属性值,优 ...
- C#学习1
一.C#可以干什么? 1.桌面应用程序,WinForm 2.Internet应用程序,ASP.Net 3.手机开发,WindowsPhone8 二..Net开发学习路线 C#语言——>简单的Wi ...
- 【转】VC6.0附带小工具软件一览
)ActiveX Control Test Container称为"ActiveX 控件测试容器",顾名思义,此工具的主要功能就是测试ActiveX 控件,可以通过改变Active ...
- Hbase物理模型
Hbase 一种高可靠,面向列,可伸缩,事实读写的分布式数据库. 利用HDFS作为其文件存储系统. MapReduce处理数据. Zookeeper分布式协同服务. 数据结构 Row Key:行 ...
- 时间都去哪了?——安卓GTD工具
GTD是英文Getting Things Done的缩写,是一种行为管理的方法,也是David Allen写的一本书的书名. GTD的主要原则在于一个人需要通过记录的方式把头脑中的各种任务移出来.通过 ...
- GUI、模块化与结对编程(homework-03)
摘要: 在本次作业博客里,我将主要阐述作业3的收获.作业3表面是将之前的程序转换为图形界面(之前程序见http://www.cnblogs.com/shone/p/3348372.html),然而本质 ...
- Oracle 表数据去重
Oracle数据库中重复数据怎么去除?使用数据表的时候经常会出现重复的数据,那么要怎么删除呢?下面我们就来说一说去除Oracle数据库重复数据的问题.今天我们要说的有两种方法. 一.根据rowid来去 ...