std::priority_queue 与 std::set 的 Dijkstra 最短路径算法性能

2023-12-20

我想了解这些容器在时间复杂度方面的主要区别。 我尝试了 Dijkstra 算法的 3 种实现,如下所述:

1-使用一个简单的数组作为队列

2-使用STLpriority_queue

3-带有STL集

我测试过的图相当大,它包含超过 150000 个顶点,有方向且所有边的权重均为正。

我得到的结果如下:

1 - 使用数组时,算法相当慢 --> 这是预期的

2 - 使用 STLpriority_queue 算法运行速度比数组快很多 --> 这也是预期的

3 - 使用STL设置,算法运行得非常快,我说的是比priority_queue快100倍 --> 我没想到会看到如此巨大的性能......

知道 std::priority_queue 和 std::set 是存储元素的数据容器,并且两者都具有基本相同的插入复杂度 O(log n),我不明白它们之间的性能差异如此之大。对此你有什么解释吗?

感谢您的帮助,

Edited:这是我的实现的摘要:

与 std::set:

unsigned int Graphe::dijkstra(size_t p_source, size_t p_destination) const {

....


set<pair<int, size_t>> set_vertices;


vector<unsigned int> distance(listAdj.size(),
        numeric_limits<unsigned int>::max());


vector < size_t
        > predecessor(listAdj.size(),
                numeric_limits < size_t > ::max());


distance[p_source] = 0;
set_vertices.insert( { 0, p_source });


while (!set_vertices.empty()) {

    unsigned int u = set_vertices.begin()->second;


    if (u == p_destination) {
        break;
    }

    set_vertices.erase( { distance[u],
            u });


    for (auto itr = listAdj[u].begin();
            itr != listAdj[u].end(); ++itr) {


        int v = itr->destination;
        int weigth = itr->weigth;


        if (distance[v]
                > distance[u] + weigth) {


            if (distance[v]
                    != numeric_limits<unsigned int>::max()) {
                set_vertices.erase(
                        set_vertices.find(
                                make_pair(distance[v],
                                        v)));
            }

            distance[v] = distance[u] + weigth;

            set_vertices.insert( { distance[v],
                    v });

            predecessor[v] = u;
        }
    }
}

....

return distance[p_destination];}

和优先级队列:

unsigned int Graphe::dijkstra(size_t p_source, size_t p_destination) const {

...

typedef pair<size_t, int> newpair;

priority_queue<newpair, vector<newpair>, greater<newpair> > PQ;

vector<unsigned int> distance(listAdj.size(),
        numeric_limits<unsigned int>::max());


vector < size_t
        > predecessor(listAdj.size(),
                numeric_limits < size_t > ::max());


distance[p_source] = 0;
PQ.push(make_pair(p_source, 0));

while (!PQ.empty()) {


    unsigned int u = PQ.top().first;


    if (u == p_destination) {
        break;
    }

    PQ.pop();


    for (auto itr = listAdj[u].begin();
            itr != listAdj[u].end(); ++itr) {


        int v = itr->destination;
        int weigth = itr->weigth;


        if (distance[v]
                > distance[u] + weigth) {

            distance[v] = distance[u] + weigth;

            PQ.push(
                    make_pair(v, distance[v]));

            predecessor[v] = u;
        }
    }
}
...

return distance[p_destination];}

SKIP

使用优先级队列,您的工作量会增加很多。

您正在双重插入队列,因为您无法修改或删除。这是正常且必要的,因为你做不到。

但是当这些旧值从队列中出来时,您需要“跳过 while 循环的迭代”。

就像是:

if (PQ.top().second != distance[PQ.top().first]) continue;  // It's stale! SKIP!!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

std::priority_queue 与 std::set 的 Dijkstra 最短路径算法性能 的相关文章

  • 用于清理 openssl EVP_PKEY 私钥内存的 C 代码

    我开始学习 C C 中的 OpenSSL 编程 我遇到的一个问题是 如何安全地清除私钥的内存 例如 我可能有代码 EVP PKEY private key PEM read bio PrivateKey bio RSA r EVP PKEY
  • Linux中如何避免sleep调用因信号而中断?

    我在 Linux 中使用实时信号来通知串行端口中新数据的到达 不幸的是 这会导致睡眠呼叫在有信号时被中断 有人知道避免这种行为的方法吗 我尝试使用常规信号 SIGUSR1 但我不断得到相同的行为 来自 nanosleep 联机帮助页 nan
  • "/>

    Error 5 expected Css test css gt gt 我需要给吗 在这里 因为我的解决方案仍然无法正常工作 它开始给出一些其他错误 您需要添加一个等号 如下所示 Css test css gt gt 解释 块将整个语句或块
  • 字节序和大小为 1 的位域

    我认为字节顺序不应该影响大小最多为 1 个字节的结构 但这是我的小端机器上的代码 include
  • 多次客户端打印后,Arduino (Uno) 以太网客户端连接失败

    我正在使用带有以太网扩展板的 Arduino Uno 发送多次 HTTP 请求后 客户端 println 客户端连接时开始失败 故障时间似乎是随机的 并且循环中的序列读数可能在 1000 和 7000 之间变化 该错误与以太网发送缓冲区溢出
  • 可空可选参数

    我在 asp net mvc 应用程序中使用带有 edmx 文件和 POCO 的实体框架 4 首先 我有一个映射到数据库中的表的人员类 public class Person public Int32 ID get set public s
  • 将 0x1234 转换为 0x11223344

    如何高性能地将十六进制数0x1234扩展到0x11223344 unsigned int c 0x1234 b b c 0xff lt lt 4 c 0xf c 0xff0 lt lt 8 c 0xff00 lt lt 12 c 0xf00
  • 拖动用户控件,但将其保留在 WPF 中其父级的边界内

    我有一个用户控件 正在将其拖动到网格内 Z Index 设置得相当高 这样我就可以将其保持在其他孩子之上 拖动控件效果很好 但如果用户想要将控件移到网格之外 它会允许这样做 How do I keep it from leaving the
  • if constexpr 与 sfinae

    随着引入if constexpr in c 17 通过使用编译时 SFINAE 解决了一些问题c 14 c 11现在可以使用解决if constexpr 具有更简单的语法 例如 考虑以下编译时递归的基本示例 以生成打印可变数量参数的子例程
  • 给定 X 在三次贝塞尔曲线上求 Y?

    我需要一种方法 允许我在给定 x 坐标的情况下找到三次贝塞尔曲线上的 Y 坐标 我遇到过很多地方告诉我将其视为三次函数 然后尝试找到根 我理解这一点 然而 三次贝塞尔曲线的方程是 对于 x 坐标 X t 1 t 3 X0 3 1 t 2 t
  • C语言中的积分提升和平衡有什么区别?

    积分提升和平衡有什么区别 我们是否可以总结这两条规则 即在执行任何操作 逻辑运算符 除外 之前 任何类型都至少转换为 int 或 unsigned int 类型 如果任何操作数的类型为更大 则转换为更大的类型比整数 积分促销 是旧的C90术
  • Facebook C# SDK 从 V5 迁移到 V6

    我正在尝试从 SDK 的 V5 3 2 迁移到 V6 我有一个 ASP NET 4 0 Canvas 应用程序 我注意到现在不再有 facebook web dll 我以前使用过 并找到了以下信息 gt 删除 Facebook Web dl
  • 将渲染后效果应用于 XNA 中的 SpriteBatch

    在 XNA 框架中 有没有一种方法可以使用典型的 SpriteBatch 方法渲染 2D 场景 然后在渲染该帧后将效果应用于整个图像 例如 模糊 棕褐色甚至使整个事情看起来像旧电影胶片 带有颗粒 灰尘 线条等 是的 您要做的就是将渲染目标设
  • 关于使用 Botframework v4 更改为新 LUIS 密钥的问题

    我在 Azure 中下载了 C 模板 它会自动创建并设置 LUIS 应用程序 但现在 LUIS 达到 1000 次调用并且现已过期 我使用创建了一个新密钥本指南 https learn microsoft com en us azure c
  • C++ Microsoft:如何将 uuid/guid 与模板专业化相关联

    我想将 uuid guid 与模板专业化相关联 以下代码可用于将 uuid 与非模板接口 类 结构 关联 interface declspec uuid CECA446F 2BE6 4AAC A117 E395F27DF1F8 ITest
  • 关于捕获异常的良好实践

    我正在用 C 11 编写一个小程序 并且第一次真正使用异常 我有一个关于如何有效捕获异常的问题 经过一番谷歌搜索后我仍然没有答案 这是问题 通过 const 左值引用捕获异常还是通过 const 右值引用捕获异常 哪个更有效 或推荐 在代码
  • static_assert 有什么作用,你会用它做什么?

    你能举个例子吗static assert C 11 会优雅地解决手头的问题吗 我熟悉运行时assert 我应该选择什么时候static assert 超过常规assert 另外 在boost有一种东西叫做BOOST STATIC ASSER
  • 我可以以编程方式更改 Xamarin.Forms 中的 styles.xml 吗?

    我们有一个可自定义颜色的应用程序 这使得列表视图中所选项目的橙色 Android 默认值有时看起来很糟糕 我们想要更改列表视图所选项目的颜色 我知道如何在我们页面的后台代码 xaml cs 中执行此操作 并且我知道您可以在 styles x
  • 从文本文件中读取行并存储到数组中

    如何从文本文件中读取行并将其存储到数组中 例如 我有一个包含 45 行不同行的文本文件 我的尝试 int main int a 45 ifstream myfile enroll assg txt if myfile cout lt lt
  • 在使用 stop_token 等待条件变量_any 时是否需要拥有锁来请求停止?

    在等待条件变量时 更改谓词状态的线程必须拥有锁 因此在唤醒期间不会错过更新 根据文档 这是必要的 即使在使用原子变量时也是如此 不过我不确定是否request stop 已经正确处理了 那么问题是 这两个选项中哪一个是正确且符合标准的呢 j

随机推荐

  • GTK 在哪里找到与 gtk_image_new_from_icon_name() 一起使用的图标名称?

    GTK 可以通过 当前图标主题中的图标 的名称来构造图像 例如 usr bin env python import gtk wnd gtk Window img gtk Image img set from icon name go jum
  • 如何指定应在新克隆中检出哪个分支?

    在 Git 扩展中 用户可以在克隆存储库时指定哪个分支 可能不是master 应在生成的克隆中进行检查 我怎样才能在命令行上做到这一点 通常 答案就在手册页中 在git clone手册页 在这里 branch
  • 如何在 Spring JPA 中为quartz作业运行更新查询

    我在 spring 4 有一份quartz 工作 我正在使用 JPA hibernate 通过quartz 工作更新数据库值 但我得到了javax persistence TransactionRequiredException Execu
  • 升级 Android Gradle Plugin 7.1 后无法加载类 AndroidComponentsExtension

    我最近下载了Android Studio 大黄蜂 https developer android com studio releases bumblebee它询问我是否想要升级到 Android Gradle Plugin 7 1 0 该版
  • 以编程方式获取插件的 Jenkins 配置

    我正在尝试获取 并希望更改 Groovy 控制台内带有 Groovy 脚本的插件的 Jenkins 配置 我的具体示例是尝试更改publish over ssh插件的多个IP地址 通过命令行 编辑 xml 可以很容易地做到这一点 但是经过几
  • 使用 asyncio 创建最小的 HTTP 服务器

    虽然我熟悉 HTTP 服务器和事件循环 但在掌握 Python 的内部工作原理时遇到了一些困难asyncio https docs python org 3 library asyncio html 作为学习练习 我一直在尝试编写一个最小的
  • 如何将 jQuery .live() 转换为 .on() 并将事件绑定到此?

    我正在将已弃用的代码转换为 live API to on 参见jQuery 1 7 发行说明 http blog jquery com 2011 11 03 jquery 1 7 released 我附加了现场活动this在多个自定义 jQ
  • Android 设置超时时间的方法

    如果在特定时间段内服务器没有响应 是否有任何方法可以在 android 中设置超时 以下是我用于超时的代码 uri new URI url HttpGet method new HttpGet uri method addHeader Co
  • 您最喜欢用什么方法来检查 HTML COLOR 是否有效?

    我使用 C 和 ASP NET 4 WebControls 我的页面上有一个文本框 用户可以输入十六进制格式 ff0000 或 HTML 格式 红色 的 HTML 颜色 我最初的想法是 编写一个能够验证该用户输入的正则表达式太困难了 因此我
  • 如何通过 matplotlib 在矩形条上绘制温度(应力)?

    我尝试使用 matplotlib 库绘制梁的应力 我已经使用公式计算并绘制了它作为示例 如图 1 所示 您会看到绿色光束在元素 3 和元素 8 处具有更大的应力 因此如果我用彩虹渐变填充颜色 蓝色光束的整体颜色将相同 但绿色光束将具有不同的
  • 警报通知立即触发。安卓

    我正在开发一个提醒 它会在固定时间向用户发送通知 警报立刻响起 我尝试了大部分建议stackoverflow 但仍然有同样的问题 请帮我解决这个问题 服务器数据 user reminder id 75 name Morning Snacks
  • XSLT 文档功能 - 文件夹层次结构

    我正在使用 xslt 1 0 并尝试使用 XSLT 文档功能将样式表应用到文件夹层次结构 文件夹结构如下 但我似乎无法在网上找到任何关于如何执行此操作的可靠参考 a b c d e f 有没有一种方法可以通过文件夹 a 中的文件将样式表应用
  • 将二维数组转换为二维ArrayList?

    我有这段代码 int pattern new int 1 1 1 1 1 1 1 1 2 0 0 0 2 1 1 0 3 0 3 0 1 1 0 0 4 0 0 1 1 0 3 0 3 0 1 1 2 0 0 0 2 1 1 1 1 1 1
  • 从命令行运行垃圾收集器? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否可以从命令行运行 NET 垃圾收集器 例如不写代码 Edit 当被问到这个问题时 我的意思正是这里对
  • 正则表达式仅允许 1-20 范围内的数字

    我想让用户输入0 20范围内的数字 他们都可以输入01和1 这就是我到目前为止所拥有的 1 9 0 1 9 1 0 9 2 0 但它不起作用 问题是 优先级低于 and 所以你的模式意味着 1 9 or 0 1 9 or 1 0 9 or
  • 在项目之间复制源代码时防止eclipse自动导入包

    当我将源代码从一个项目复制到另一个项目时 是否可以防止 Eclipse 自动导入任何模块 我只想复制源代码 然后重命名所有特定的类 我实际上不想使用其他项目中的类 在首选项窗口中 菜单 Windows Preferences 在搜索字段 左
  • Retrofit 2.0 OnFailure - 原始响应

    我在用着retrofit调用网络服务和改造会引发失败 来自 Throwable 的消息给了我 java lang IllegalStateException 预期为 BEGIN OBJECT 但在第 1 行第 1 列路径 处为 STRING
  • 我应该在 SCRIPT 标签中包含 type="text/javascript" 吗?

    我通读了Crockford 的 JavaScript 最佳实践 http javascript crockford com code html 他说 无需使用语言或类型属性 决定 MIME 类型的是服务器 而不是脚本标记 但我从未见过有人省
  • 我可以在保留私钥的同时更改 Android 签名证书主题吗

    我已经开发了一个 Android 应用程序 我正在将其转让给另一个人以进一步开发 我了解到 如果新开发人员使用相同的密钥库 无缝升级过程将继续 Android在更新应用程序时如何验证证书 难道只是仅验证签名或者这样做比较整个证书以及主题名称
  • std::priority_queue 与 std::set 的 Dijkstra 最短路径算法性能

    我想了解这些容器在时间复杂度方面的主要区别 我尝试了 Dijkstra 算法的 3 种实现 如下所述 1 使用一个简单的数组作为队列 2 使用STLpriority queue 3 带有STL集 我测试过的图相当大 它包含超过 150000