第十七章 优先队列优化Dijkstra算法

news2024/11/14 17:59:17

第十七章 优先队列优化Dijkstra算法

  • 一、普通dijkstra算法的缺陷
    • 1、选出最小距离的过程:
    • 2、松弛所有点的过程:
  • 二、如何优化
    • 1、代码模板
      • (1)问题:
      • (2)模板:
    • 2、详细解读
  • 三、优化分析
    • 1、使用条件:
    • 2、常见问题:
      • (1)什么样的路径才能进优先队列
      • (2)重边的处理
      • (3)时间复杂度

一、普通dijkstra算法的缺陷

作者在这里建议,不太懂dijkstra算法的同学可以去看看作者对该算法的详细讲解以及通俗证明,这样大家就能够体会到原算法的缺陷。
传送门:第十六章 Dijkstra算法的讲解以及证明(与众不同的通俗证明)

1、选出最小距离的过程:

     int t=-1;
     for(int j=1;j<=n;j++)
     {
         if(!s[j]&&(t==-1||dis[j]<dis[t]))t=j;
     }

我们的dijkstra算法会选出所有松弛后所得距离的最小值。而我们之前的代码是遍历所有点来确定的,时间复杂度是O(N)。但是我们知道,我们在一堆数中选出一个最小值,只需要使用我们之前学过的数据结构:堆。假设我们插入一个最小值,那么堆选出这个值的时间复杂度是O(logN)。那么形成一个堆的话,即插入n个数的时间复杂度,并不是nlogn,而是O(N)
推导如下:
在这里插入图片描述

数据结构堆就是STL中的优先队列:priority_queue

2、松弛所有点的过程:

        
        for(int j=1;j<=n;j++)
        {
            dis[j]=min(dis[j],g[t][j]+dis[t]);
        }

通过我们第十五章对dijkstra算法的证明,我们发现,每次松弛过程得到有效更新的点,都是我们中间点的邻接点。也就是说,我们只需要去松弛该点的邻接点即可,不用去松弛所有点。因此,我们只需要去松弛该点的邻接点。那么这个时候,我们用邻接表就会便于我们去访问了。因为邻接表中将一个点的所有邻接点都记录在了链表中。我们只需要遍历对应点的链表即可。

二、如何优化

1、代码模板

(1)问题:

在这里插入图片描述

(2)模板:

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=1e6+10;
int h[N],e[N],ne[N],idx,w[N];
bool s[N];
int dis[N];
int n,m,a,b,c;
void add(int a,int b,int c)
{
    e[idx]=b;ne[idx]=h[a];w[idx]=c;h[a]=idx++;
}
int dijkstra()
{
    memset(dis,0x3f,sizeof dis);
    dis[1]=0;
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
    q.push(make_pair(0,1));
    while(!q.empty())
    {
        auto t=q.top();
        q.pop();
        if(s[t.second])continue;
        s[t.second]=true;

        for(int i=h[t.second];i!=-1;i=ne[i])
        {
            if(dis[e[i]]>t.first+w[i])
            {
                dis[e[i]]=t.first+w[i];
                q.push({dis[e[i]],e[i]});
            }
        }
    }
    if(dis[n]==0x3f3f3f3f)return -1;
    else return dis[n];
}
int main()
{
    memset(h,-1,sizeof h);
    cin>>n>>m;
    while(m--)
    {
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
    }
    cout<<dijkstra();
    return 0;
}

2、详细解读

在这里插入图片描述

三、优化分析

1、使用条件:

我们这道题中的图是稀疏图,所以我们可以使用邻接表,从而优化这个代码。但是要是稠密图的话,我们可能还是需要用邻接矩阵来存储,这样的话一般使用的是朴素的dijkstra算法。

2、常见问题:

(1)什么样的路径才能进优先队列

只有一个点得到有效更新的时候,我们才会让这个点进堆。我们一开始是正无穷,那么源点的邻接点一定会得到有效的更新,那么我们让这些点进堆。那么第二次我们遍历的邻接点中,如果还包含上一次松弛后的点,而恰好本次也没有更新成功,那么我们让这个点进堆的话,堆中就会出现两个一样的数据。这样就造成了重复。而我们让不更新的点进堆,并不是说这个点已经确定了,而是说这个点的状态在之前的更新过程中已经进堆了。

所以,我们只让那些松弛成功的点进堆。

(2)重边的处理

我们的邻接矩阵存储图的时候,会通过min函数存储重边中的最小边。但是我们的邻接表会存储所有重边。这其实是没关系的。比如我们a,b点内存储了3,1,2。三个长度的边。一开始可能会让3+x这个距离进堆,但是我们当再次遍历到1这个边,松弛成功后我们就会让1+x进堆。而1+x存在后,3+x就不会成堆顶,所以就不会对结果产生影响。那么当我们的1+x出堆后,说明这个点的最短路已经确定了。那么我们直接标记一下,所以当1+x删除后,轮到3+x出堆的时候,由于我们已经标记了。所以通过continue就可以直接删除3+x这个数据。而后续的2+x也会在轮到它出堆的时候,删除掉。

(3)时间复杂度

寻找路径最短的点(形成一个堆的过程):O(n)

加入集合ST:O(n)

更新距离:O(mlogn)

所以总的时间复杂度是:O(mlogn)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/69365.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5G赋能行业应用,助推数智化转型!

导语 | 5G 技术的蓬勃发展推动其行业应用的巨轮乘风破浪、扬帆启航&#xff0c;5G 技术不断落地布局于各行各业&#xff0c;基础建设也不断完善&#xff0c;5G to B 的时代已经到来。此次&#xff0c;我们邀请到了中国电信研究院工业互联网技术研发部主任、腾讯云 TVP 谭华老师…

知识图谱-KGE-语义匹配-双线性模型(打分函数用到了双线性函数)-2014:TATEC

【paper】 Effective Blending of Two and Three-way Interactions for Modeling Multi-relational Data 【简介】 本文是法国 Antoine Bordes 团队发表在 ECML-PKDD 2014 上的工作&#xff0c;提出了 TATEC&#xff08;Two and Three-way Embeddings Combination&#xff09;…

ERP+MES集成管理系统重要性有哪些?

随着企业信息化观念的提升&#xff0c;管理方式也愈来愈信息化&#xff0c;因此以信息化推动企业的不断发展趋势已变成企业存活和发展的主要核心理念。其中E&#xff32;P 系统和 MES 系统在企业发展和改革中起着非常重要的作用。当各种信息化系统在企业内各个部门顺利执行的同…

RabbitMQ安装教程(超详细)

本教程是在centos8下试验的&#xff0c;其实linux系统的都差不多 RabbitMQ官方&#xff1a;Messaging that just works — RabbitMQ RabbitMQ是开源AMQP实现&#xff0c;服务器端用Erlang语言编写&#xff0c;Python、Ruby、 NET、Java、JMS、c、PHP、action screcrive AMQP …

python 爬虫入门该怎么学习?

前言 1、什么是爬虫和爬虫的基本逻辑 “爬虫”是一种形象的说法。互联网比喻成一张大网&#xff0c;爬虫是一个程序或脚本在这种大网上爬走。碰到虫子&#xff08;资源&#xff09;&#xff0c;若是所需的资源就获取或下载下来。这个资源通常是网页、文件等等。可以通过该资源…

Android NDK 开发之 CMake 必知必会

Android Studio 从 2.2 版本起开始支持 CMake ,可以通过 CMake 和 NDK 将 C/C 代码编译成底层的库&#xff0c;然后再配合 Gradle 的编译将库打包到 APK 中。 这意味就不需要再编写 .mk 文件来编译 so 动态库了。 CMake 是一个跨平台构建系统&#xff0c;在 Android Studio 引…

12月7日 补充数据库链式操作,只生成sql语句,不执行sql的几种函数以及thinkphp中验证器

补充知识&#xff1a; 生成sql语句但是不会执行sql语句 public function fetchSqlTest(){$result Db::name(user)->fetchSql(true)->select();//dump($result);//使用正常select查询默认中select(true&#xff09;改为false即可返回sql语句$result Db::name(user)->…

UNIX/LINUX操作系统内核结构

通用操作系统的现状和分类 UNIX操作系统的根本特点&#xff1a;分时多用户、开放性 基本功能特征 系统结构 操作系统核心 系统调用的集合及实现系统调用的内部算法就形成操作系统核心 系统调用 以函数形式提供给核外的命令和上层应用系统使用的一组程序&#xff0c;涵…

观察者模式

目录 一、观察者模式解决了哪些问题&#xff1a; 二、体检的小栗子 三、什么是观察者模式 四、代码实现 一、观察者模式解决了哪些问题&#xff1a; 对象之间的一对多依赖关系应该在不使对象紧密耦合的情况下定义。应该确保当一个对象改变状态时&#xff0c;自动更新无限数…

5-5:显示系统的通知

通知列表 显示评论、点赞、关注三种类型的通知。 通知详情 分页显示某一类主题所包含的通知。 未读消息 在页面头部显示所有的未读消息数量 通知存在message表里面 修改MessageMapper.java package com.nowcoder.community.dao;import com.nowcoder.community.entity.Messa…

毕业2年,跳槽到我们公司拿18K,这就是00后卷王带来的压迫感吗?

内卷&#xff0c;是现在热度非常高的一个词汇&#xff0c;随着热度不断攀升&#xff0c;隐隐到了“万物皆可卷”的程度。 在程序员职场上&#xff0c;什么样的人最让人反感呢? 是技术不好的人吗?并不是。技术不好的同事&#xff0c;我们可以帮他。 是技术太强的人吗?也不…

AI 也会写代码了,但我并不担心

如果你比较关注人工智能&#xff0c;可能会注意到最近圈子的人都在刷屏一个 AI 玩意&#xff0c;叫 ChatGPT 。我一直关注的和菜头在他的公众号槽边往事上就接连写了几篇文章。为什么和菜头是男的&#xff0c;读者却要叫他“婶婶”怎么把AI逼到生气水文与干货如果看完上面的第一…

一行代码 网页变灰

背景 想必大家都感受到了&#xff0c;很多网站、APP 在昨天都变灰了。 先来感受一下变灰后的效果。 让网页变为黑白配色&#xff0c;是个常见的诉求。而且往往是突如其来的诉求&#xff0c;是无法预知的。 当发生这样的需求时&#xff0c;我们需要迅速完成变更发布。 这种…

机器学习 决策树 随机森林

文章目录参考决策树指标基尼系数基础公式公式理解引入划分后的公式划分后公式的理解信息熵、信息增益如何理解信息熵两种指标的对比总结参考 b站视频 【决策树、随机森林】附源码&#xff01;&#xff01;超级简单&#xff0c;同济大佬手把手带你学决策树决策树模型及案例&…

收藏 外贸企业必备的跨境电商B2B出口报关完整指南

跨境企业想要将货物出口到国外&#xff0c;报关是重要步骤之一&#xff0c;它是货物合法进出国境的通行证。许多初入跨境电商行业的B2B企业在报关上由于无人指引走了许多弯路&#xff0c;浪费了时间。 一.跨境出口模式 根据海关总署规定&#xff0c;跨境电商出口的监管模式分为…

QDataStream(数据流)

QDataStream类实现将QIODevice的二进制数据串行化。一个数据流就是一个二进制编码信息流&#xff0c;独立于主机的操作系统&#xff0c;CPU或字节顺序。QDataStream可以实现c的基本数据类型的串行化。 构造函数&#xff1a; 常用函数 &#xff1a; atEnd()是否到达结束位置re…

基于jsp+ssm的旅游活动报名系统-计算机毕业设计

项目介绍 本系统主要采JSP语言进行编写&#xff0c;本系统数据库采用数据处理功能强大的MySQL来建立 管理员可以通过结伴休闲平台进行旅行社管理、个人活动管理、旅行社活动管理、客户管理、用户管理等。个人用户则可通过结伴休闲平台对进行发布活动、结伴活动等。旅行社用户…

STC15 - ExternalRAM_enable()/InternalRAM_enable()

文章目录STC15 - ExternalRAM_enable()/InternalRAM_enable()概述实验环境MCU的规格区别IAP15F2K61S2的使用限制实验的组合公用测试代码1. 没有焊接外部RAM ExternalRAM_enable()2. 没有焊接外部RAM InternalRAM_enable()3. 焊接外部RAM ExternalRAM_enable()4. 焊接外部RAM…

世界杯狂欢季,家居品牌仅靠4位UP增长2000wB站声量

时隔四年&#xff0c;2022年卡塔尔世界杯于11月21日正式开始&#xff0c;直至目前比赛进度已过半程&#xff0c;这场世界赛事备受各国瞩目&#xff0c;全网有关于“足球”的运动信息接踵而至。 飞瓜数据&#xff08;B站版&#xff09;显示&#xff0c;B站平台带有“世界杯”标…

React源码之概念篇

React主要的三部分 这是从ReactDom.render后触发的步骤 调度协调渲染 设计理念 首先在React中需要在浏览器刷新一次就需要执行如下的步骤&#xff1a; JS脚本执行->样式布局->样式绘制&#xff0c;如果js执行时间超过了16.6ms&#xff0c;那么就没有时间留给样式布局…