C++ 有向图算法

news2024/11/15 8:25:53
概念

Breadth-First Search (BFS)

目的: 主要用于遍历或搜索图中的所有顶点。
特点: 从根节点开始,先访问所有与之相邻的节点,然后再一层一层地深入。
应用: 可以用来寻找两节点间的最短路径(当边的权重相等时),检测图中是否存在环路,以及层次遍历二叉树等。
数据结构: 使用队列来存储待访问的节点。
Depth-First Search (DFS):
目的: 同样用于遍历或搜索图中的所有顶点。
特点: 从根节点开始,尽可能深地搜索树的分支。
应用: 用于解决连通性问题,如检测环路、拓扑排序、迷宫求解等。
数据结构: 使用栈(可以是递归栈)来存储待访问的节点。

Dijkstra算法

目的: 用于找到图中一个节点到其他所有节点的最短路径。
特点: 要求图中没有负权边,并且是从一个源节点开始计算最短路径。
应用: 寻找两点之间的最短路径,广泛应用于路由算法。
数据结构: 使用优先队列(最小堆)来存储待处理的节点。

Kruskal算法

目的: 用于找到图的最小生成树(Minimum Spanning Tree, MST)。
特点: 是一种贪心算法,适用于边稀疏的图。
应用: 在网络设计中用于构建成本最低的网络连接。
数据结构: 使用并查集(Union-Find)来维护生成树的形成过程。

需要注意的是,Kruskal算法通常不直接用于有向图,因为它主要用于无向图中的最小生成树问题。对于有向图,我们通常考虑的是最短路径问题,而不是生成树问题

用法

#include "../src/algo/bfs.h"
#include "../src/algo/dfs.h"
#include "../src/algo/dijkstra.h"
#include "../src/algo/kruskal.h"

#include <gtest/gtest.h>

#include <chrono>
#include <memory>
#include <vector>

class GraphTest : public ::testing::Test
{
protected:
};


TEST_F(GraphTest, BFSTest)
{
  Graph graph{ false, false };
  graph.addEdges('a', { 'b' });
  graph.addEdges('b', { 'a', 'c' });
  graph.addEdges('c', { 'b', 'd', 'e' });
  graph.addEdges('d', { 'c', 'e' });
  graph.addEdges('e', { 'c', 'd' });

  auto begin = std::chrono::high_resolution_clock::now();
  BFS bfs{ graph };
//  DFS dfs{ graph };
  bfs.traverseGraph();
  auto end = std::chrono::high_resolution_clock::now();
  auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - begin);
  std::cout << "BFSTest : time in microseconds : " << elapsed.count() << std::endl;

  // 节点遍历
  const auto& nodes = graph.getNodes();
}


TEST_F(GraphTest, DijkstraTest)
{
  Graph graph{ true, true };
  graph.addEdgesWeighted('a', { { 'd', 3 }, { 'h', 5 } });
  graph.addEdgesWeighted('b', { { 'c', 4 }, { 'i', 1 } });
  graph.addEdgesWeighted('c', { { 'a', 4 }, { 'l', 5 } });
  graph.addEdgesWeighted('d', { { 'b', 2 }, { 'e', 1 }, { 'f', 8 } });
  graph.addEdgesWeighted('e', { { 'c', 5 }, { 'j', 7 } });
  graph.addEdgesWeighted('f', { { 'e', 2 }, { 'h', 2 }, { 'i', 7 }, { 'k', 10 } });
  graph.addEdgesWeighted('g', { { 'e', 3 } });
  graph.addEdgesWeighted('h', { { 'g', 6 }, { 'l', 4 }});
  graph.addEdgesWeighted('i', { { 'k', 6 } });
  graph.addEdgesWeighted('j', { { 'c', 8 } });
  graph.addEdgesWeighted('k', { { 'g', 3 }, { 'j', 5 } });
  graph.addEdgesWeighted('l', { { 'g', 2 }, { 'e', 5 }, {'f', 12 } });

  char src = 'a';
  char dst = 'b';
  Dijkstra dijkstra{ graph };
  auto begin = std::chrono::high_resolution_clock::now();
  dijkstra.traverseGraph(src);
  auto end = std::chrono::high_resolution_clock::now();
  auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - begin);
  std::cout << "DijkstraTest : time in microseconds : " << elapsed.count() << std::endl;

  // 最短路径
  const auto nodesList = std::make_unique<std::list<char>>();
  nodesList->push_front(dst);
  dijkstra.traverseGraph(src);
  const std::map<char, route>& routes = dijkstra.getRoutes();

  std::optional<char> predecessor;
  predecessor = routes.at(dst).predecessor;
  while (predecessor != std::nullopt) {
    nodesList->push_front(predecessor.value());
    predecessor = routes.at(predecessor.value()).predecessor;
  }
  auto shortPaths = std::make_unique<std::vector<char>>(nodesList->begin(), nodesList->end());
}

TEST_F(GraphTest, KruskalTest)
{
  Graph graph{ false, true };
  graph.addEdgesWeighted('a', { { 'b', 3 }, { 'f', 2 } });
  graph.addEdgesWeighted('b', { { 'c', 17 }, { 'd', 16 } });
  graph.addEdgesWeighted('c', { { 'd', 8 }, { 'i', 18 } });
  graph.addEdgesWeighted('d', { { 'e', 11 }, { 'i', 4 } });
  graph.addEdgesWeighted('e', { { 'f', 1 }, { 'g', 6 }, { 'h', 5 }, { 'i', 10 } });
  graph.addEdgesWeighted('f', { { 'g', 7 } });
  graph.addEdgesWeighted('g', { { 'h', 15 } });
  graph.addEdgesWeighted('h', { { 'i', 12 }, { 'j', 13 } });
  graph.addEdgesWeighted('i', { { 'j', 9 } });

  auto begin = std::chrono::high_resolution_clock::now();
  Kruskal kruskal{ graph };
  std::unique_ptr<std::vector<Edge>> edges = kruskal.makeMinSpanningTree();
  auto end = std::chrono::high_resolution_clock::now();
  auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - begin);
  std::cout << "KruskalTest : time in microseconds : " << elapsed.count() << std::endl;

  // 最小生成树,边的权值之和最低的子图
  auto edgesTuple  = std::make_unique<std::vector<std::tuple<char, char>>>();
  for (const Edge& edge : *edges) {
    edgesTuple->push_back(std::tuple<char, char>{ edge.src, edge.dst });
  }
}
参考

C++ 有向图拓扑排序算法_有向图排序c++-CSDN博客

https://github.com/Przemyslawmd/Graphs


创作不易,小小的支持一下吧!

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

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

相关文章

笔记:应用Visual Studio Profiler分析CPU使用情况

一、目的&#xff1a;应用Visual Studio Profiler分析CPU使用情况 使用 Visual Studio Profiler 分析 CPU 使用情况可以帮助你识别性能瓶颈&#xff0c;优化代码&#xff0c;提高应用程序的响应速度。 二、实现 以下是如何使用 Visual Studio Profiler 分析 CPU 使用情况的详…

前端问答:如何判断变量是否为数组?

在JavaScript的世界里&#xff0c;判断一个变量的类型是开发者日常工作中不可或缺的一部分&#xff0c;尤其是在处理数组这种关键数据结构时。数组作为一种广泛应用于各种操作的数据结构&#xff0c;无论是简单的数据存储还是复杂的算法实现&#xff0c;都发挥着重要作用。然而…

力扣刷题--762. 二进制表示中质数个计算置位【简单】

题目描述&#x1f357; 给你两个整数 left 和 right &#xff0c;在闭区间 [left, right] 范围内&#xff0c;统计并返回 计算置位位数为质数 的整数个数。 计算置位位数 就是二进制表示中 1 的个数。 例如&#xff0c; 21 的二进制表示 10101 有 3 个计算置位。 示例 1&am…

【JPCS独立出版】2024电驱系统与控制工程国际学术研讨会(EDSCE 2024,10月18-20)

2024电驱系统与控制工程国际学术研讨会&#xff08;EDSCE 2024&#xff09;将于2024年10月18-20日在中国本溪隆重举行。 本次会议将集中讨论电驱系统与控制工程的最新研究成果&#xff0c;旨在建立一个高水平的学术交流平台&#xff0c;以便领域内的专家学者、工程师和技术研发…

【单片机原理及应用】实验: 8位数码显示器

目录 一、实验目的 二、实验内容 三、实验步骤 四、记录与处理 五、思考 六、成果文件提取链接 一、实验目的 学习8位数码管串行扩展原理&#xff0c;掌握74HC595与动态显示编程方法。 二、实验内容 【参照图表】 &#xff08;1&#xff09;创建一个包含80C51固件&#x…

如何选择适合企业的财税自动化解决方案

财税自动化解决方案是现代企业提升财务管理效率、降低运营成本的关键工具。然而&#xff0c;市场上的财税自动化产品琳琅满目&#xff0c;功能各异&#xff0c;企业在选择时常常感到困惑。本文金智维将从中小型的需求出发&#xff0c;帮助企业了解如何选择适合自身的财税自动化…

ASP.NET Core6.0-wwwroot文件夹无法访问解决方法

默认情况下&#xff0c;ASP.NET Core项目中的wwwroot文件夹被视为Web根文件夹。静态文件可以存储在Web根目录下的任何文件夹中&#xff0c;并可以使用该根目录的相对路径进行访问。在ASP.NET应用程序中&#xff0c;可以从应用程序的根文件夹或其下的任何其他文件夹提供静态文件…

数据分析学习之numpy

引言 好久没写帖子了&#xff0c;确实变懒了&#xff0c;在这一个月里学习了爬虫&#xff0c;还有seleium自动化技术初步以及数据分析中的numpy&#xff0c;下一步就要学习pandas,但是欠了太多帖子没写&#xff0c;所以现在来补一下&#xff0c;现在来的是numpy的学习&#xff…

Java面试宝典-java基础07

Java面试宝典-java基础07 61、什么是 java 序列化&#xff1f;什么情况下需要序列化&#xff1f;62、序列化使用场景有哪些&#xff1f;63、使用序列化和反序列化的注意事项64、为什么要使用克隆&#xff1f;如何实现对象克隆&#xff1f;深拷贝和浅拷贝区别是什么&#xff1f;…

计算机网络概述(分组延时、丢失和吞吐量)

目录 分组丢失和延时是怎样发生的&#xff1f; 四种分组延时 节点延时 排队延迟 分组丢失 吞吐量 吞吐量&#xff1a;互联网场景 分组丢失和延时是怎样发生的&#xff1f; 在路由器缓冲区的分组队列 分组到达链路的速率超过了链路输出的能力分组等待排队到队头、被传输…

Ethernet 测试系列(1)-- 物理层测试::IOP Test::Link-up time

车载以太网物理层IOP测试&#xff0c;即互操作性测试&#xff08;Interop- erability Tests&#xff09;&#xff0c;用于验证车载以太网PHY&#xff08;通常也称为收发器&#xff09;的可靠性和检查PHY能否在给定的有限时间内建立稳定的链路;还用于车载以太网PHY的诊断&#x…

ARCGIS 纸质小班XY坐标转电子要素面(2)

本章用于说明未知坐标系情况下如何正确将XY转要素面 背景说明 现有资料&#xff1a;清除大概位置&#xff0c;纸质小班图&#xff0c;图上有横纵坐标&#xff0c;并已知小班XY拐点坐标&#xff0c;但未知坐标系。需要上图 具体操作 大部分操作同这边文章ARCGIS 纸质小班XY…

Vue.js 模板语法详解:插值表达式与指令使用指南

Vue.js 模板语法详解&#xff1a;插值表达式与指令使用指南 引言 简要介绍主题&#xff1a; Vue.js 是一个现代化的 JavaScript 框架&#xff0c;用于构建用户界面。Vue 的模板语法提供了直观且功能强大的工具&#xff0c;用于将数据与 DOM 绑定。本文将深入探讨 Vue.js 的两个…

AI游戏革命!谷歌推出GameNGen,实时生成游戏画面,每秒20帧实时模拟

未来&#xff0c; AI会取代传统游戏引擎吗&#xff1f; 谷歌的研究人员发表论文称&#xff0c;他们创建了一个名为GameNGen的AI神经网络&#xff0c;直接用AI生成了整个《Doom》游戏&#xff01; 最令人惊讶的是&#xff0c;他们并没有使用传统的游戏引擎&#xff0c;而是在单…

基于单片机的浴室防雾镜系统设计

1系统方案设计 浴室防雾镜是一种特殊的镜子&#xff0c;在浴室中使用时不会起雾&#xff0c;通过对其需要展开分析&#xff0c;本设计基于51单片机设计的浴室防雾镜的系统架构如图2.1所示&#xff0c;采用了DS18B20温度传感器和人体红外感应红外传感器进行智能控制&#xff0c…

通过住宅代理捕获网站快照:技术解析与未来展望

引言 什么是网站快照&#xff1f;为什么需要网站快照&#xff1f; 网站快照的工作原理是什么&#xff1f; 如何捕获网站快照&#xff1f; 网站快照未来的发展趋势 总结 引言 在当今快速发展的数字时代&#xff0c;网站快照作为一种关键的网页记录技术&#xff0c;扮演着越…

Springboot3整合ELK实现日志可视化

一、环境准备 Elasticsearch、Logstash、Kibana,组合起来可以搭建线上日志系统 ELK中各个服务的作用 Elasticsearch:用于存储收集到的日志信息&#xff1b; Logstash:用于收集日志&#xff0c;SpringBoot应用整合了Logstash以后会把日志发送给Logstash,Logstash再把日志转发…

【Android】UI拓展之滑动菜单、悬浮按钮、CoordinatorLayout布局等

文章目录 一、滑动菜单1. 添加依赖2. 侧滑菜单内容2.1 headerLayout样式2.2 menu样式 3. 主界面添加4. 关联actionbar与滑动菜单 二、悬浮按钮FloatingActionButton 三、可交互提示Snackbar 四、能协调子视图的布局CoordinatorLayout 五、卡片式布局CardView 一、滑动菜单 Draw…

微信小程序服务器费用一年多少?微信小程序开发

在互联网时代&#xff0c;微信小程序已成为众多企业和个人拓展业务、提升服务品质的有力工具。然而对于许多准备涉足小程序领域的朋友来说【开发一个小程序大概需要多少钱】以及【微信小程序服务器费用一年需要多少】是首要关注的问题&#xff0c;今天飞飞将和你们分享小程序服…

【LoRa】SetLoRaSymbNumTimeout寄存器

目录 1 前言2 实验验证疑问2.1 SetRx的timeout模式和SetLoRaSymbNumTimeout2.1.1 实验12.1.2 实验22.1.3 结论 2.2 SetRx的single与continuous模式和SetLoRaSymbNumTimeout2.2.1 实验12.2.2 实验22.2.3 实验3 3 小结 1 前言 本章节介绍LoRa芯片的寄存器SetLoRaSymbNumTimeout&…