DAG路径搜索优化性能提高百倍

news2024/11/17 21:17:47

问题描述:

从一个DAG图中给定的起点 begin_line 寻找一条路径到达给定的终点 end_line。
图的拓扑关系由 top 这个映射(map<int64, vector<int64>>)表示,每条边都有一个或多个邻接的后继。begin_line 和 end_line 都是边的id。
如果找到了这样的路径,将路径保存 vector<int64> path 结构中。如果路径有多条,只需找出任意一条即可。

参考的函数定义:

/*
 * begin_line: 起始边的ID。
 * end_Line: 目标边的ID。
 * top: 一个映射,键是节点的ID,值是一个包含邻接ID的列表。
 * path_r: 输出参数,用于返回找到的路径。
*/
bool GetPath(int64 begin_line, int64 end_line, const map<int64, vector<int64>>& top, vector<int64>& path_r);

初步的实现

使用广度优先遍历的方式寻找路径。

bool GetPath(int64 begin_line, int64 end_Line, const map<int64, vector<int64>>& top, vector<int64>& path_r) {
  struct LineNode {
    int64 line_id;
    vector<int64> path;
    set<int64> exists;
  };

  vector<int64> line_list;
  list<LineNode> visited;
  visited.push_back(LineNode());
  visited.back().line_id = begin_line;
  visited.back().path.push_back(begin_line);
  visited.back().exists.insert(begin_line);

  auto iter = visited.begin();
  while (iter != visited.end()) {
    LineNode& node = *iter;
    if (node.line_id == end_Line) {
      path_r = node.path;
      return true;
    } else {
      auto iter_top = top.find(node.line_id);
      if (iter_top != top.end()) {
        for (int64 next_id : iter_top->second) {
          if (node.exists.find(next_id) != node.exists.end()) {
            continue;
          }
          visited.push_back(LineNode());
          visited.back().line_id = next_id;
          visited.back().path = node.path;
          visited.back().exists = node.exists;
          visited.back().path.push_back(next_id);
          visited.back().exists.insert(next_id);
          //std::cout << next_id << endl;
        }
      }
    }
    ++iter;
  }
  return false;
}

存在的问题:运行很慢。

优化方案:

  1. 使用队列代替列表:在原始实现中,使用了 std::list 来存储待访问的节点。虽然 std::list 提供了高效的插入和删除操作,但对于广度优先搜索(BFS)而言,使用 std::queue 可能更为合适,因为它不需要频繁地移动元素。
  2. 减少内存分配:在原始实现中,每当遇到新的邻接顶点时都会创建一个新的 LineNode 实例。这会导致大量的动态内存分配和析构操作。我们可以尝试重用现有的 LineNode 实例来减少内存分配次数。
  3. 避免不必要的复制:在原始实现中,每次创建新节点时都会复制路径 path 和已访问顶点集合 exists。这可能导致不必要的内存复制开销。我们可以通过引用或指针来避免这种复制。

基于上述考虑,下面是一个经过优化的版本:

#include <iostream>
#include <queue>
#include <set>
#include <vector>
#include <map>
#include <memory>

struct LineNode {
    int64 line_id;
    std::vector<int64> path;
};

bool GetPath(int64 begin_line, int64 end_line, const std::map<int64, std::vector<int64>>& topo, 
    std::vector<int64>& path_r) {
    using NodePtr = std::unique_ptr<LineNode>;

    std::queue<NodePtr> que;  // 使用队列存储指向 LineNode 的智能指针
    std::set<int64> visited_lines;  // 存储已访问的顶点

    NodePtr start_node(new LineNode());
    start_node->line_id = begin_line;
    start_node->path.push_back(begin_line);

    que.push(std::move(start_node));  // 将起始节点放入队列
    visited_lines.insert(begin_line);

    while (!que.empty()) {
        NodePtr current = std::move(que.front());
        que.pop();

        if (current->line_id == end_line) {
            path_r = current->path;
            return true;
        }

        auto iter_topo = topo.find(current->line_id);
        if (iter_topo != topo.end()) {
            for (int64 next_id : iter_topo->second) {
                if (visited_lines.find(next_id) != visited_lines.end()) {
                    continue;
                }

                NodePtr next_node(new LineNode(*current));  // 深拷贝当前节点
                next_node->line_id = next_id;
                next_node->path.push_back(next_id);

                que.push(std::move(next_node));
                visited_lines.insert(next_id);
            }
        }
    }

    return false;
}

int main() {
    std::map<int64, std::vector<int64>> topo = {
        {1, {2, 3}},
        {2, {4}},
        {3, {5}},
        {4, {6}},
        {5, {6}},
        {6, {}}
    };

    std::vector<int64> path;
    bool found = getPath(1, 6, topo, path);

    if (found) {
        for (int64 id : path) {
            std::cout << id << " ";
        }
        std::cout << std::endl;
    } else {
        std::cout << "No path found." << std::endl;
    }

    return 0;
}

效果:

快到飞起!

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

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

相关文章

javax.imageio.IIOException: Not a JPEG file: starts with 0xff 0xd9

目录 问题描述&#xff1a; 解决思路&#xff1a; 问题出现的原因&#xff1a; 解决方法&#xff1a; 问题描述&#xff1a; 最近在用java做一个上传图像识别文字的功能&#xff0c;上传图像后报错。 接口返回&#xff1a; {"code": 500,"success":…

滚动懒加载升级版:添加滚动回收策略

在之前的1.0版本的基础上&#xff0c;添加滚动回收策略&#xff0c;保持页面只保留固定数量的数据&#xff0c;优化渲染 否则一直往数组里push内容&#xff0c;当数组长度过大&#xff0c;可能页面会崩溃&#xff08;本需求是日志列表&#xff0c;由于日志数据可能会非常庞大&…

C++入门基础知识41——【关于C++ 运算符——杂项运算符】

成长路上不孤单&#x1f60a;【14后&#xff0c;C爱好者&#xff0c;持续分享所学&#xff0c;如有需要欢迎收藏转发&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#xff01;&#xff01;&#xff01;&#xff01;&#xff…

URP custompasscustom render objects

https://dbbh666.blog.csdn.net/article/details/141296728?spm1001.2014.3001.5502 上一次 custom render pass的时候&#xff0c;直接是quad的渲染&#xff0c;如果想把任意对象绘制到FBO怎么写呢 参考这两个高手的文章&#xff0c;总结一下 https://www.bilibili.com/read…

换毛季猫咪化身掉毛怪,宠物浮毛如何清理?推荐用宠物空气净化器

我家现在有三只毛孩子&#xff0c;养宠的幸福是三倍&#xff0c;除毛的烦恼也是三倍。尤其还有两只是银渐层&#xff0c;掉毛量实在是太夸张了&#xff0c;衣服、地板、水杯家里到处都是。我也每天早晚都给它们梳毛&#xff0c;卫生也定期清理&#xff0c;可还是浮毛满天飞。 …

【前缀和】--- 初阶题目赏析

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; 算法Journey 了解完一维和二维前缀和模板之后&#xff0c;我们来看几道题目感受前缀和的算法原理以及使用场景。 &#x1f3e0; 寻找数组的中心下标 &am…

多张图片拼接在线制作难吗?学会这招让拼接变得很简单

你是否曾遇到过这样的困境&#xff1f;手机里的照片堆积如山&#xff0c;想要在社交平台上分享&#xff0c;却发现限制多多&#xff0c;根本没办法一次性分享完所有的精彩瞬间。这真是让人既兴奋又苦恼的事情啊&#xff01; 记得上次旅行回来&#xff0c;我拍了一大堆照片&…

精益生产管理咨询师OS:我需要时间!!!

最近一位企业的老板和我聊起管理企业的问题&#xff1a;之前听说精益生产管理不错&#xff0c;就试着在企业推行精益生产管理&#xff0c;结果精益培训搞了一个多月, 课上完了,可总是感觉精益并没有在企业落地,反倒感觉越来越越迷茫了。还抱怨说请精益生产管理咨询师花了很多钱…

AI智能对话绘画二合一系统源码 输入文字就可以快速生成高清图片 带源代码包以及搭建部署教程

系统概述 AI 智能对话绘画二合一系统源码是一款集智能对话与绘画功能于一体的先进系统。它融合了人工智能、计算机视觉等多项技术&#xff0c;能够实现自然语言处理与图像生成的高度协同。 该系统通过对大量文本和图像数据的学习与训练&#xff0c;具备了理解用户意图、生成相…

智游剪辑1.7.0 发布

最近又简单给桌面版升级了一下&#xff0c;一起来看看有啥新功能吧 支持实时输出 之前的文字类功能一般都需要等一会才能给出完整结果&#xff0c;现在它支持实时显示输出结果了&#xff0c;不仅输出更快了&#xff0c;而且还可以实时看到效果 字幕生成功能优化 旧版的字幕生…

vscode开发uniapp项目教程

一&#xff0c;在HB编辑器中用命令行创建uniapp项目&#xff08;vitevue3TS) npx degit dcloudio/uni-preset-vue#vite-ts 项目名称注意&#xff1a;搭梯子在创建或者连手机网络创建&#xff0c;按官方提示的下载模板也行。 在HB编辑器中安装vue3插件 二&#xff0c;在vscod…

抽烟检测算法引领公共场所健康管理的未来抽烟检测算法方案源码

在现代社会&#xff0c;吸烟对公共健康的影响越来越受到关注。为应对这一挑战&#xff0c;智能抽烟检测算法作为一种前沿技术&#xff0c;正逐渐成为公共场所健康管理的得力助手。这些算法通过先进的计算机视觉和深度学习技术&#xff0c;能够实时监控和识别吸烟行为&#xff0…

Linux基础1-基本指令5(more,less,head,tail, | ,find)

本章继续整理其他linux基本指令 一.本章重点 1.more和less命令查看大文本 2.head和tail命令查看小文本和日志 3.使用管道多次处理信息 4.find指令 二.more和less more命令和less命令常用来查看大文本&#xff0c;其中less可以使用上下键快速浏览文本 使用方式 more文件 …

若依ruoyi-vue部署在子域名下(做为子应用)

若依ruoyi-vue部署在子域名下&#xff08;做为子应用&#xff09; 特殊情况需要部署到子路径下&#xff08;做为子应用&#xff09; 文章目录 若依ruoyi-vue部署在子域名下&#xff08;做为子应用&#xff09;一、vue.config.js二、router/index.js三、Navbar.vue四、request.j…

通过查找真实IP bypass WAF

当已知某站存在漏洞时&#xff0c;Web 应用程序防火墙&#xff08;简称WAF&#xff09;是最大的阻碍。通常&#xff0c;这些网站都很老旧&#xff0c;维护得不是很好&#xff0c;因此在大多数情况下&#xff0c;将 WAF 放在它们之上会更容易。有一种方法可以绕过这一层保护&…

【软件文档】软件质量保证计划书(Word完整版)

1 概述 2 质量目标 3 项目基本情况 4 资源 4.1 人员 4.1.1 组织结构 4.1.2 职责 4.2 工具及设施 5 质量保证的主要工作 6 质量保证工作量估算 7 质量保证工作提交的产物 8 变更管理 9 评价标准 10 形成的记录 软件全套资料部分文档清单&#xff1a; 工作安排任务书&#xff0c;…

想了解前端开发神器MemFire Cloud,这一文就搞定

在如今这个快速变化的开发世界里&#xff0c;谁不想拥有一款能够极大提升效率的开发神器&#xff1f;如果你也是一个想在开发路上少走弯路的程序员&#xff0c;那你一定要了解一下 MemFire Cloud。这款专为“懒人开发者”准备的全能工具&#xff0c;凭借其便捷的操作和强大的功…

ESP32-C3在MQTT访问时出现“Last error code reported from esp-tls: 0x8001”和问题的分析(5)

接前一篇文章:ESP32-C3在MQTT访问时出现“Last error code reported from esp-tls: 0x8001”和问题的分析(4) 前几篇文章分析了笔者在调试测试MQTT时所遇到的“Last error code reported from esp-tls: 0x8001”的问题。实际上笔者在实际测试时发现,还有另外一种错误情况,…

关于Claude Artifacts的5条总结!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

简道云进销存的设计分析

​简道云-进销存应用是对标标准ERP的核心场景业务流、功能&#xff0c;开发的一款拥有自定义能力的“专业进销存”场景应用产品。 01功能表 简道云-进销存应用&#xff0c;主要是实现进销存业务中的4大工作流程“采购、销售、库存、财务”的场景设计&#xff0c;对应的&#x…