Dijkstra算法优先队列实现与Bellman_Ford队列实现的理解

简介:
/*
Dijkstra算法用优先队列来实现,实现了每一条边最多遍历一次。 要知道,我们从队列头部找到的都是到
已经"建好树"的最短距离以及该节点编号, 并由该节点去更新 树根 到其他点(被更新的节点可以在队列中
,也可以是非队列中的节点)的距离 。

////如果v节点的到更新,则直接放入队列中(pair<d[v], v>)不会重复放入到队列中

如果某个节点从队列中出来的时候,如果cur.first != dist[cur.second] 就是 cur.second这个节点一开始
被更新的最短距离值 和 现在得到的最短距离的值dist[cur.second] 不想等,说明该节点已经被之前队列中
具有更短距离的节点更新过了, 那么新的节点pair(dist[cur.second], cur.second)再次放入优先队列中,用来跟新其他节点的最短距离。 如果想等,则dist[cur.second]就是cur.second最终的最短距离!
*/
#include<iostream> 
#include<queue>
#include<cstring> 
#define N 1000
using namespace std;

class EDGE
{
  public:
    int u, v, w;
    int next;//和节点 u 相连的下一条边的编号 
};

EDGE edge[2*N];

typedef pair<int, int>pii;//pair<距离,节点号>

int first[N];//最多有N个节点 ,建立每个节点和其相连的边的关系 
int dist[N];//源点到各个点的最短距离 

int n, m;//节点数,边数 

bool operator >(pii a, pii b)
{
   if(a.first==b.first)
     return a.second > b.second;
   return a.first > b.first;//按照最短的距离值在队列的前段
}

priority_queue<pii, vector<pii>, greater<pii> >q; 

void Dijkstra()
{
   pii cur;
   memset(dist, 0x3f, sizeof(dist));
   dist[1]=0;//另节点 1 为源点
   q.push(make_pair(0, 1));
   while(!q.empty()) 
   {
      cur=q.top();
      q.pop();
      if(cur.first != dist[cur.second])  continue;// 不等于的话说明该节点的值已经经过其他节点松弛为更短的距离值了 
      for(int e=first[cur.second]; e!=-1; e=edge[e].next)
        if(dist[edge[e].v]>dist[edge[e].u]+edge[e].w)
        {
               dist[edge[e].v]=dist[edge[e].u]+edge[e].w;
               q.push(make_pair(dist[edge[e].v], edge[e].v));//将更新之后的节点的放入队列之中 
        }
   }
}

int main()
{
   int i;
   cin>>n>>m;
   for(i=1; i<=n; ++i)
     first[i]=-1; 
   for(i=0; i<m; ++i)
   {
       cin>>edge[i].u>>edge[i].v>>edge[i].w;
       edge[edge[i].u].next=first[edge[i].u];
       first[edge[i].u]=i;
   } 
   Dijkstra();
   for(i=2; i<=n; ++i)
     cout<<"1->"<<i<<":"<<dist[i]<<endl; 
   return 0;
/*
Bellman_Ford算法用队列实现和 Dijkstra算法用优先队列来实现相同的地方是,都是 层次 更新到节点的最短距离,
都是将具有最短距离的节点(如果不在队列中)放入队列中
Bellman_Ford算法中实现的是带有负权图的最短距离,因为负权的关系,这样可能使得某个
节点的最短路径的值一直被更新(比如存在负权回路的时候),所以被更新的节点(如果不在队列中)一直会进入队列中 
*/
#include<iostream> 
#include<queue>
#include<cstring> 
#define N 1000
using namespace std;

class EDGE
{
  public:
    int u, v, w;
    int next;//和节点 u 相连的下一条边的编号 
};

EDGE edge[2*N];

int first[N];//最多有N个节点 ,建立每个节点和其相连的边的关系 
int dist[N];//源点到各个点的最短距离 
int cnt[N];//记录每个节点在队列中出现的次数 
int vis[N];//记录当前的节点是否已经在队列中 

int n, m;//节点数,边数 


queue<int>q; 

int Bellman_Ford()
{
   int cur;
   memset(dist, 0x3f, sizeof(dist));
   dist[1]=0;//另节点 1 为源点
   q.push(1);
   while(!q.empty()) 
   {
      cur=q.front();
      q.pop();
      vis[cur]=0;//出队列 
      ++cnt[cur];
      if(cnt[cur]>n-1)//如果不存在负权回路,那么某个节点的最多被更新的次数为 n-1 次 
         return 0;
      for(int e=first[cur]; e!=-1; e=edge[e].next)
        if(dist[edge[e].v]>dist[edge[e].u]+edge[e].w)
        {
               dist[edge[e].v]=dist[edge[e].u]+edge[e].w;
               if(!vis[edge[e].v])//本跟新的节点没有在队列中 
               {
                  q.push(edge[e].v);//将更新之后的节点的放入队列之中 
                  vis[edge[e].v]=1;//放入队列
        } 
        }
   }
   return 1; 
}

int main()
{
   int i;
   cin>>n>>m;
   for(i=1; i<=n; ++i)
     first[i]=-1; 
   for(i=0; i<m; ++i)
   {
       cin>>edge[i].u>>edge[i].v>>edge[i].w;
       edge[edge[i].u].next=first[edge[i].u];
       first[edge[i].u]=i;
   } 
   if(!Bellman_Ford())//表示存在负权回路
      cout<<"不存在最短路径"<<endl;
   else
   {
     for(i=2; i<=n; ++i)
       cout<<"1->"<<i<<":"<<dist[i]<<endl; 
   }
   return 0;
}









本文转自 小眼儿 博客园博客,原文链接:http://www.cnblogs.com/hujunzheng/p/3781817.html,如需转载请自行联系原作者
目录
相关文章
|
11月前
|
存储 运维 监控
基于 C# 语言的 Dijkstra 算法在局域网内监控软件件中的优化与实现研究
本文针对局域网监控系统中传统Dijkstra算法的性能瓶颈,提出了一种基于优先队列和邻接表优化的改进方案。通过重构数据结构与计算流程,将时间复杂度从O(V²)降至O((V+E)logV),显著提升大规模网络环境下的计算效率与资源利用率。实验表明,优化后算法在包含1000节点、5000链路的网络中,计算时间缩短37.2%,内存占用减少21.5%。该算法适用于网络拓扑发现、异常流量检测、故障定位及负载均衡优化等场景,为智能化局域网监控提供了有效支持。
290 5
|
8月前
|
机器学习/深度学习 编解码 算法
【机器人路径规划】基于迪杰斯特拉算法(Dijkstra)的机器人路径规划(Python代码实现)
【机器人路径规划】基于迪杰斯特拉算法(Dijkstra)的机器人路径规划(Python代码实现)
659 4
|
9月前
|
算法 机器人 定位技术
基于机器视觉和Dijkstra算法的平面建筑群地图路线规划matlab仿真
本程序基于机器视觉与Dijkstra算法,实现平面建筑群地图的路径规划。通过MATLAB 2022A读取地图图像,识别障碍物并进行路径搜索,支持鼠标选择起点与终点,最终显示最优路径及长度,适用于智能导航与机器人路径规划场景。
|
运维 监控 算法
企业局域网监控软件中 Java 优先队列算法的核心优势
企业局域网监控软件是数字化时代企业网络安全与高效运营的基石,犹如一位洞察秋毫的卫士。通过Java实现的优先队列算法,它能依据事件优先级排序,确保关键网络事件如异常流量、数据泄露等被优先处理,保障系统稳定与安全。代码示例展示了如何定义网络事件类并使用PriorityQueue处理高优先级事件,尤其在面对疑似风险时迅速启动应急措施。这一核心技术助力企业在复杂网络环境中稳健前行,护航业务腾飞。
208 32
|
缓存 监控 算法
内网监控管理软件:PHP 语言队列算法揭秘
在数字化办公环境中,内网监控管理软件对企业的稳定运行和信息安全至关重要。本文深入介绍PHP中的队列算法及其在内网监控软件中的应用,包括监控数据收集、任务调度和日志记录等场景,通过代码示例展示其实现方法。队列算法可提高性能、保证数据顺序并实现异步处理,为企业提供高效的安全保障。
257 1
|
算法 编译器 C++
【狂热算法篇】探秘图论之Dijkstra 算法:穿越图的迷宫的最短路径力量(通俗易懂版)
【狂热算法篇】探秘图论之Dijkstra 算法:穿越图的迷宫的最短路径力量(通俗易懂版)
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
7月前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
707 0
|
7月前
|
数据采集 分布式计算 并行计算
mRMR算法实现特征选择-MATLAB
mRMR算法实现特征选择-MATLAB
444 2
|
8月前
|
传感器 机器学习/深度学习 编解码
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
366 3

热门文章

最新文章