单源最短路径——dijkstra算法
1.先说说prim算法的思想:
众所周知,prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的点集合A,另一个集合为未加入生成树的点B,它的具体实现过程是:
第1步:所有的点都在集合B中,A集合为空。
第2步:任意以一个点为开始,把这个初始点加入集合A中,从集合B中减去这个点(代码实现很简单,也就是设置一个标示数组,为false表示这个点在B中,为true表示这个点在A中),寻找与它相邻的点中路径最短的点,如后把这个点也加入集合A中,从集合B中减去这个点(代码实现同上)。
第3步:集合A中已经有了多个点,这时两个集合A和B,只要找到A集合中的点到B集合中的点的最短边,可以是A集合中的与B集合中的点的任意组合,把这条最短边有两个顶点,把在集合B中的顶点加入到集合A中,(代码实现的时候有点技巧,不需要枚举所有情况,也就是更新操作)。
第4步:重复上述过程。一直到所有的点都在A集合中结束。
2.说说dijkstra算法的过程:
这个算法的过程有比prim算法的过程稍微多一点点步骤,但是思想确实巧妙的,也是贪心原理,它的目的是求某个源点到目的点的最短距离,总的来说,dijkstra算法也就是求某个源点到目的点的最短路,求解的过程也就是求源点到整个图的最短距离,次短距离,第三短距离等等(这些距离都是源点到某个点的最短距离)。。。。。求出来的每个距离都对应着一个点,也就是到这个点的最短距离,求的也就是原点到所有点的最短距离,并且存在了一个二维数组中,最后给出目的点就能直接通过查表获得最短距离。
第1步:以源点(假设是s1)为开始点,求最短距离,如何求呢? 与这个源点相邻的点与源点的距离全部放在一个数组dist[]中,如果不可达,dist[]中为最大值,这里说一下,为什么要是一维数组,原因是默认的是从源点到这个一维数组下标的值,只需要目的点作为下标就可以,这时从源点到其他点的最短的“一”条路径有了,只要选出dist[]中最小的就行(得到最短路径的另一个端点假设是s2)。
第2步:这时要寻找源点(假设是s1)到另外点的次短距离,这个距离或者是dist[]里面的值,或者是从第1步中选择的那个最短距离 + 从找到点(假设是s2)出发到其他点的距离(其实这里也是一个更新操作,更新的是dist[]里面的值),如果最短距离 + 从这点(假设是s2)到其他点的距离,小于dist[]里面的值,就可以更新dist[]数组了,然后再从dist[]数组中选一个值最小的,也就是第“二”短路径(次短路径)。
第3步:寻找第“三”短路径,这时同上,第二短路径的端点(s3)更新与之相邻其他的点的dist[]数组里面的值。
第4步:重复上述过程n - 1次(n指的是节点个数),得出结果,其实把源点到所有点的最短路径求出来了,都填在了dist[]表中,要找源点到哪个点的最短路,就只需要查表了。
/*Dijkstra求单源最短路径 2010.8.26*/ #include <iostream>
#include<stack>
#define M 100
#define N 100
using namespace std; typedef struct node
{
int matrix[N][M]; //邻接矩阵
int n; //顶点数
int e; //边数
}MGraph; void DijkstraPath(MGraph g,int *dist,int *path,int v0) //v0表示源顶点
{
int i,j,k;
bool *visited=(bool *)malloc(sizeof(bool)*g.n);
for(i=;i<g.n;i++) //初始化
{
if(g.matrix[v0][i]>&&i!=v0)
{
dist[i]=g.matrix[v0][i];
path[i]=v0; //path记录最短路径上从v0到i的前一个顶点
}
else
{
dist[i]=INT_MAX; //若i不与v0直接相邻,则权值置为无穷大
path[i]=-;
}
visited[i]=false;
path[v0]=v0;
dist[v0]=;
}
visited[v0]=true;
for(i=;i<g.n;i++) //循环扩展n-1次
{
int min=INT_MAX;
int u;
for(j=;j<g.n;j++) //寻找未被扩展的权值最小的顶点
{
if(visited[j]==false&&dist[j]<min)
{
min=dist[j];
u=j;
}
}
visited[u]=true;
for(k=;k<g.n;k++) //更新dist数组的值和路径的值
{
if(visited[k]==false&&g.matrix[u][k]>&&min+g.matrix[u][k]<dist[k])
{
dist[k]=min+g.matrix[u][k];
path[k]=u;
}
}
}
} void showPath(int *path,int v,int v0) //打印最短路径上的各个顶点
{
stack<int> s;
int u=v;
while(v!=v0)
{
s.push(v);
v=path[v];
}
s.push(v);
while(!s.empty())
{
cout<<s.top()<<" ";
s.pop();
}
} int main(int argc, char *argv[])
{
int n,e; //表示输入的顶点数和边数
while(cin>>n>>e&&e!=)
{
int i,j;
int s,t,w; //表示存在一条边s->t,权值为w
MGraph g;
int v0;
int *dist=(int *)malloc(sizeof(int)*n);
int *path=(int *)malloc(sizeof(int)*n);
for(i=;i<N;i++)
for(j=;j<M;j++)
g.matrix[i][j]=;
g.n=n;
g.e=e;
for(i=;i<e;i++)
{
cin>>s>>t>>w;
g.matrix[s][t]=w;
}
cin>>v0; //输入源顶点
DijkstraPath(g,dist,path,v0);
for(i=;i<n;i++)
{
if(i!=v0)
{
showPath(path,i,v0);
cout<<dist[i]<<endl;
}
}
}
return ;
}
测试数据:
运行结果:
单源最短路径——dijkstra算法的更多相关文章
- 单源最短路径Dijkstra算法,多源最短路径Floyd算法
1.单源最短路径 (1)无权图的单源最短路径 /*无权单源最短路径*/ void UnWeighted(LGraph Graph, Vertex S) { std::queue<Vertex&g ...
- 单源最短路径 dijkstra算法实现
本文记录一下dijkstra算法的实现,图用邻接矩阵表示,假设图为无向图.而且连通,有向图,不连通图的做法相似. 算法简述: 首先确定"单源"的源.假设是第0个顶点. 维护三个数组 ...
- 单源最短路径——Dijkstra算法学习
每次都以为自己理解了Dijkstra这个算法,但是过没多久又忘记了,这应该是第4.5次重温这个算法了. 这次是看的胡鹏的<地理信息系统>,看完之后突然意识到用数学公式表示算法流程是如此的好 ...
- 单源最短路径-Dijkstra算法
1.算法标签 贪心 2.算法描述 具体的算法描述网上有好多,我觉得莫过于直接wiki,只说明一些我之前比较迷惑的. 对于Dijkstra算法,最重要的是维护以下几个数据结构: 顶点集合S : 表示已经 ...
- [数据结构与算法-15]单源最短路径(Dijkstra+SPFA)
单源最短路径 问题描述 分别求出从起点到其他所有点的最短路径,这次主要介绍两种算法,Dijkstra和SPFA.若无负权优先Dijkstra算法,存在负权选择SPFA算法. Dijkstra算法 非负 ...
- matlab练习程序(单源最短路径Dijkstra)
图的相关算法也算是自己的一个软肋了,当年没选修图论也是一大遗憾. 图像处理中,也有使用图论算法作为基础的相关算法,比如图割,这个算法就需要求最大流.最小割.所以熟悉一下图论算法对于图像处理还是很有帮助 ...
- 单源最短路径---Bellman-Ford算法
传送门: Dijkstra Bellman-Ford SPFA Floyd 1.Dijkstra算法的局限性 像上图,如果用dijkstra算法的话就会出错,因为如果从1开始,第一步dist[2] = ...
- 洛谷P3371单源最短路径Dijkstra版(链式前向星处理)
首先讲解一下链式前向星是什么.简单的来说就是用一个数组(用结构体来表示多个量)来存一张图,每一条边的出结点的编号都指向这条边同一出结点的另一个编号(怎么这么的绕) 如下面的程序就是存链式前向星.(不用 ...
- 单源最短路径Dijkstra和优先级算法
百度百科:迪杰斯特拉算法. 代码实现如下: import java.util.Comparator; import java.util.PriorityQueue; import java.util. ...
随机推荐
- 精美的HTML5 Loadding页面
以前我们大部分的Loading动画都是利用gif图片实现的,这种图片实现Loading动画的方法虽然也很不错,但是作为HTML5开发者来说,如果能利用HTML5和CSS3实现这些超酷的Loading动 ...
- hdu2955 Robberies 01背包+概率
link:http://acm.hdu.edu.cn/showproblem.php?pid=2955 首先,这个题目的背包容量不能是概率.1.精度不清楚.2.把概率相加有什么意义呢?所以,转换一下, ...
- c 深度剖析 4
1 预处理 1#define 1.不能用 #define 定义注释,因为注释先于预处理被处理. 2 .宏定义表达式 1,注意展开后结合顺序,尽量多加括号 2,常量定义时注意是否溢出 1 #define ...
- Hibernate的三种常用检索方式
Hibernate 提供了以下几种检索对象的方式 ¨ 导航对象图检索方式: 根据已经加载的对象导航到其他对象 ¨ OID 检索方式: 按照对象的 OID 来检索对象 ¨ ...
- cloudera安装报错 socket.gaierror: [Errno -2] Name or service not known
有时候安装cloudera会报socket.gaierror: [Errno -2] Name or service not known,或者服务器可能IP或mac地址冲突会引发次错误.导致机器服务不 ...
- JSBinding + SharpKit / Important Notes
Serialization of List<T> is not supported. 1 public int v; // SUPPORTED 2 public GameObject go ...
- Ubuntu 安装和配置redis数据库
Ubuntu 14.04下安装和配置redis数据库 小编现在在写一个分布式爬虫,要用到这个数据库,所以分享一下小编是如何安装和配置的,希望对大家有帮助. 工具/原料 Ubuntu 系统电脑一台 ...
- 使用 Fluent API 配置/映射属性和类型
使用 Fluent API 配置/映射属性和类型 使用实体框架 Code First 时,默认行为是使用一组 EF 中内嵌的约定将 POCO 类映射到表.但是,有时您无法或不想遵守这些约定,需要将实体 ...
- Asp.net MVC的actionlink到Areas里action
<li>@Html.ActionLink("Home", "Index", "Home", new { area = " ...
- OpenJudge计算概论-二维数组右上左下遍历
/*====================================================================== 二维数组右上左下遍历 总时间限制: 1000ms 内存 ...