关于贝尔曼福特算法,假设有n个顶点,我们只需要遍历n-1轮,因为在包含n个顶点的图中,任意两点之间的最短路径最多包含n-1条边。原理我就不多说了。互联网上有很多很棒的博客。我将在这里为您提供一些有用的信息:
1.最原始的Bellman Ford算法,时间复杂度为O(NM):
#include#include#include#include#include#include#include#include#define mem(a,b) memset(a,b,sizeof(a))
#定义最大数3010
#定义inf0x3f3f3f
使用命名空间std;
int main()
{
int dis[10],n,m,u[10],v[10],w[10],检查,标志;
//读取顶点数和边数
scanf("%d%d",n,m);
//读入边
for(int i=1; i=m; i++)
scanf("%d%d%d",u[i],v[i],w[i]);
//初始化dis数组
for(int i=1; i=n; i++)
dis[i]=inf;
dis[1]=0;
//贝尔曼-福特算法(Bellman-Ford)的核心语句
for(int k=1; k=n-1; k++)
{check=0;//本轮松弛是否更新标记数组dis
for(int i=1; i=m; i++)
if(dis[u[i]]+w[i]的适用范围:给定的图中存在负权重边,这时候Dijkstra等算法就没地方用了,而且Bellman-福特算法太高了,SPFA算法派上用场了,我们一致认为有向加权图G中不存在负权环,即最短路径一定存在,当然我们可以在执行之前做一下拓扑排序。判断是否的算法但这不是我们讨论的重点。
算法思想:我们用数组d来记录每个节点的最短路径估计,用邻接表来存储图G。我们采用的方法是动态逼近法:建立一个先进先出队列来保存待优化的节点。优化时,我们每次取出头节点u,并使用u点当前的最短路径估计来离开u点。 v 指向的节点经历松弛操作。如果调整了点v的最短路径估计并且点v不在当前队列中,则将点v放置在队列的末尾。这样不断从队列中取出节点进行松弛操作,直到队列为空。
SPFA(最短路径更快算法)【图存储在邻接表中】
它是贝尔曼-福特算法的队列实现,减少了不必要的冗余计算。
该算法的大致过程是使用队列进行维护。源最初已排队。每次从队列中取出一个元素,
并松弛与其相邻的所有点。如果相邻点成功放宽,则会将其添加到队列中。当队列为空时算法结束。
它可以在O(kE)的时间复杂度内找到从源点到所有其他点的最短路径,并且可以处理负边沿。
SPFA在形式上与BFS非常相似。不同之处在于,在BFS 中,一旦点击退出队列,就无法重新进入队列,而在SPFA 中
点出队后可以再次放入队列。即一个点改进了其他点后,可能经过一段时间就被修改了。
一旦方法改进了,再用它来改进其他点,不断迭代。
判断是否存在负环:如果某个点进入队列超过V次,则存在负环(SPFA无法处理有负环的图)。
与Dijkstra算法思想上最大的区别在于,每次都是从源点s开始进行“松弛”更新操作,而Dijkstra则是从源点开始向外扩展,逐一处理相邻的点。节点不会被重复处理。这里也可以看出Dijkstra的效率相对来说要高一些。
Bellman Ford算法的队列优化,时间复杂度为O(N):
#include#include#include#include#include#include#include#include#define mem(a,b) memset(a,b,sizeof(a))
#定义最大数3010
#定义inf0x3f3f3f
使用命名空间std;
int dis[最大数量],n,m,u[最大数量],v[最大数量],w[最大数量];
int 第一个[最大数量],下一个[最大数量],vis[最大数量];
int main()
{
队列q;
//读取顶点数和边数
scanf("%d%d",n,m);
//初始化dis数组
for(int i=1; i=n; i++)
dis[i]=inf;
dis[1]=0;
//初始化vis,一开始不在队列中
for(int i=1; i=n; i++)
vis[i]=0;
//初始化first的下标为-1,表示顶点1~n暂时没有边。
for(int i=1; i=n; i++)
第一个[i]=-1;
//读取边并创建邻接表
for(int i=1; i=m; i++)
{
scanf("%d%d%d",u[i],v[i],w[i]);
下一个[i]=第一个[u[i]];
首先[u[i]]=i;
}
//1号顶点入队
可见[1]=1;
q.push(1);
while(!q.empty())
{
int k=first[q.front()];
while(k!=-1)//扫描当前顶点的所有边
{
if(dis[u[k]]+w[k] 摘要
1、广度优先算法BFS主要适用于在无权有向图中重新搜索从源点到终点的步数最少的路径。当方向图有权重时,就不再适用。
2. Dijkstra算法主要用于搜索带权方向图中的最短路径,但不适用于带负权值的情况。对于环图,我个人的感觉和BFS是一样的。标记处理过的节点,避免进入死循环,可以支持
3、Bellman-Ford算法Bellman-Ford主要用于带负权值的方向图(不带负权值也可以使用,但效率比Dijkstra低很多),搜索源点到各个节点的最短路径。
关于深入解析:高效编程必备的数据结构知识的内容到此结束,希望对大家有所帮助。
【深入解析:高效编程必备的数据结构知识】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
学习数据结构感觉很有挑战,但掌握了这些知识,程序开发水平就提升一个档次!
有5位网友表示赞同!
数据结构是编程的基础,想写出高效、干净代码就得认真理解啊。
有15位网友表示赞同!
数据结构太抽象了,有时候看不懂老师讲的,还是要多练习才能看懂吧!
有15位网友表示赞同!
我觉得树形结构很有意思,把复杂的数据组织成层级关系很直观!
有17位网友表示赞同!
图论部分有点难啃,感觉现实生活中很少用到。
有8位网友表示赞同!
数据算法和数据结构简直是黄金搭档!
有16位网友表示赞同!
想要成为一名优秀的软件工程师,数据结构是一门必修课。
有9位网友表示赞同!
理解链表后我觉得很多编程问题都容易解决多了!
有15位网友表示赞同!
最近在练习堆的数据结构,感觉很有用处 。
有9位网友表示赞同!
每次做题的时候都能学到数据结构的新知识点,这感觉真好!
有5位网友表示赞同!
数据结构的应用范围还是很广泛的,不仅仅是编程领域。
有16位网友表示赞同!
想写出高效代码,了解不同数据结构的特点很重要!
有16位网友表示赞同!
学习数据结构可以锻炼逻辑思维能力,这对未来的软件开发很有帮助!
有5位网友表示赞同!
感觉掌握了数据结构后,对计算机的底层机制理解更加深了。
有10位网友表示赞同!
希望在工作中也能有机会用到数据结构!
有11位网友表示赞同!
数据结构是一个非常重要的话题。
有12位网友表示赞同!
学习数据结构需要大量的练习和经验积累。
有8位网友表示赞同!