【数据结构-图】图介绍

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
img

  • 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老
  • 导航
    • 檀越剑指大厂系列:全面总结 java 核心技术点,如集合,jvm,并发编程 redis,kafka,Spring,微服务,Netty 等
    • 常用开发工具系列:罗列常用的开发工具,如 IDEA,Mac,Alfred,electerm,Git,typora,apifox 等
    • 数据库系列:详细总结了常用数据库 mysql 技术点,以及工作中遇到的 mysql 问题等
    • 懒人运维系列:总结好用的命令,解放双手不香吗?能用一个命令完成绝不用两个操作
    • 数据结构与算法系列:总结数据结构和算法,不同类型针对性训练,提升编程思维,剑指大厂

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨

博客目录

    • 一.图的概念
      • 1.概念
      • 2.有向 vs 无向
      • 3.度
      • 4.权
      • 5.路径
      • 6.环
      • 7.图的连通性
    • 二.DFS 和 BFS
      • 1.Java 表示
      • 2.DFS
      • 3.BFS
    • 三.拓扑排序
      • 1.什么是拓扑排序?
      • 2.BFS
      • 3.DFS
      • 4.Kahn
    • 四.习题
      • 1.图-相关题目

一.图的概念

1.概念

图是由顶点(vertex)和边(edge)组成的数据结构,例如

A
B
C
D

该图有四个顶点:A、B、C、D 以及四条有向边,有向图中,边是单向的

2.有向 vs 无向

如果是无向图,那么边是双向的,下面是一个无向图的例子

A
B
C
D

3.度

是指与该顶点相邻的边的数量

A
B
C
D
E
F

例如上图中

  • A、B、C、E、F 这几个顶点度数为 2
  • D 顶点度数为 4

有向图中,细分为入度出度,参见下图

A
B
C
D
E
F
  • A (2 out / 0 in)
  • B、C、E (1 out / 1 in)
  • D (2 out / 2 in)
  • F (0 out / 2 in)

4.权

边可以有权重,代表从源顶点到目标顶点的距离、费用、时间或其他度量。

北京
武汉
广州
上海
800km
1900km
1200km
1050km
700km

5.路径

路径被定义为从一个顶点到另一个顶点的一系列连续边,例如上图中【北京】到【上海】有多条路径

  • 北京 - 上海
  • 北京 - 武汉 - 上海

路径长度

  • 不考虑权重,长度就是边的数量
  • 考虑权重,一般就是权重累加

6.环

在有向图中,从一个顶点开始,可以通过若干条有向边返回到该顶点,那么就形成了一个环

A
B
C
D
E

7.图的连通性

如果两个顶点之间存在路径,则这两个顶点是连通的,所有顶点都连通,则该图被称之为连通图,若子图连通,则称为连通分量

A
B
C
D
E
F
G
H
I
J

二.DFS 和 BFS

比如说,下面的图

A
B
C
D

邻接矩阵可以表示为:

  A B C D
A 0 1 1 0
B 1 0 0 1
C 1 0 0 1
D 0 1 1 0

邻接表可以表示为:

A -> B -> C
B -> A -> D
C -> A -> D
D -> B -> C

有向图的例子

A
B
C
D
  A B C D
A 0 1 1 0
B 0 0 0 1
C 0 0 0 1
D 0 0 0 0
A - B - C
B - D
C - D
D - empty

1.Java 表示

顶点

public class Vertex {String name;List<Edge> edges;// 拓扑排序相关int inDegree;int status; // 状态 0-未访问 1-访问中 2-访问过,用在拓扑排序// dfs, bfs 相关boolean visited;// 求解最短距离相关private static final int INF = Integer.MAX_VALUE;int dist = INF;Vertex prev = null;
}

public class Edge {Vertex linked;int weight;public Edge(Vertex linked) {this(linked, 1);}public Edge(Vertex linked, int weight) {this.linked = linked;this.weight = weight;}
}

2.DFS

public class Dfs {public static void main(String[] args) {Vertex v1 = new Vertex("v1");Vertex v2 = new Vertex("v2");Vertex v3 = new Vertex("v3");Vertex v4 = new Vertex("v4");Vertex v5 = new Vertex("v5");Vertex v6 = new Vertex("v6");v1.edges = List.of(new Edge(v3), new Edge(v2), new Edge(v6));v2.edges = List.of(new Edge(v4));v3.edges = List.of(new Edge(v4), new Edge(v6));v4.edges = List.of(new Edge(v5));v5.edges = List.of();v6.edges = List.of(new Edge(v5));dfs1(v1);}private static void dfs2(Vertex v) {LinkedList<Vertex> stack = new LinkedList<>();stack.push(v);while (!stack.isEmpty()) {Vertex pop = stack.pop();pop.visited = true;System.out.println(pop.name);for (Edge edge : pop.edges) {if (!edge.linked.visited) {stack.push(edge.linked);}}}}private static void dfs1(Vertex v) {v.visited = true;System.out.println(v.name);for (Edge edge : v.edges) {if (!edge.linked.visited) {dfs(edge.linked);}}}
}

3.BFS

public class Bfs {public static void main(String[] args) {Vertex v1 = new Vertex("v1");Vertex v2 = new Vertex("v2");Vertex v3 = new Vertex("v3");Vertex v4 = new Vertex("v4");Vertex v5 = new Vertex("v5");Vertex v6 = new Vertex("v6");v1.edges = List.of(new Edge(v3), new Edge(v2), new Edge(v6));v2.edges = List.of(new Edge(v4));v3.edges = List.of(new Edge(v4), new Edge(v6));v4.edges = List.of(new Edge(v5));v5.edges = List.of();v6.edges = List.of(new Edge(v5));bfs(v1);}private static void bfs(Vertex v) {LinkedList<Vertex> queue = new LinkedList<>();v.visited = true;queue.offer(v);while (!queue.isEmpty()) {Vertex poll = queue.poll();System.out.println(poll.name);for (Edge edge : poll.edges) {if (!edge.linked.visited) {edge.linked.visited = true;queue.offer(edge.linked);}}}}
}

三.拓扑排序

1.什么是拓扑排序?

拓扑排序(Topological Sorting)是一种用于有向图(Directed Acyclic Graph,DAG)的节点排序算法。在拓扑排序中,图中的节点被安排成线性顺序,满足以下条件:

  1. 对于任意的有向边 (u, v),节点 u 在节点 v 之前。
  2. 图中不能包含环路(即,图必须是有向无环图,DAG)。

拓扑排序主要应用于描述一些任务或事件之间的依赖关系,其中每个节点代表一个任务或事件,有向边表示依赖关系。通过拓扑排序,你可以确定任务或事件的执行顺序,以确保没有依赖关系被破坏。

拓扑排序算法通常使用深度优先搜索(DFS)或广度优先搜索(BFS)来实现。算法的基本思想是从入度为 0 的节点开始,逐步移除这些节点及其出边,然后继续处理新的入度为 0 的节点,直到所有节点都被处理。

拓扑排序在许多领域有广泛的应用,包括编译器优化、任务调度、依赖分析、项目管理等。它是一种非常有用的算法,用于解决有向图中的依赖关系问题。

网页基础
Java Web
Java 基础
数据库
Spring框架
微服务框架
实战项目

2.BFS

public class TopologicalSort {public static void main(String[] args) {Vertex v1 = new Vertex("网页基础");Vertex v2 = new Vertex("Java基础");Vertex v3 = new Vertex("JavaWeb");Vertex v4 = new Vertex("Spring框架");Vertex v5 = new Vertex("微服务框架");Vertex v6 = new Vertex("数据库");Vertex v7 = new Vertex("实战项目");v1.edges = List.of(new Edge(v3)); // +1v2.edges = List.of(new Edge(v3)); // +1v3.edges = List.of(new Edge(v4));v6.edges = List.of(new Edge(v4));v4.edges = List.of(new Edge(v5));v5.edges = List.of(new Edge(v7));v7.edges = List.of();List<Vertex> graph = List.of(v1, v2, v3, v4, v5, v6, v7);// 1. 统计每个顶点的入度for (Vertex v : graph) {for (Edge edge : v.edges) {edge.linked.inDegree++;}}/*for (Vertex vertex : graph) {System.out.println(vertex.name + " " + vertex.inDegree);}*/// 2. 将入度为0的顶点加入队列LinkedList<Vertex> queue = new LinkedList<>();for (Vertex v : graph) {if (v.inDegree == 0) {queue.offer(v);}}// 3. 队列中不断移除顶点,每移除一个顶点,把它相邻顶点入度减1,若减到0则入队List<String> result = new ArrayList<>();while (!queue.isEmpty()) {Vertex poll = queue.poll();
//            System.out.println(poll.name);result.add(poll.name);for (Edge edge : poll.edges) {edge.linked.inDegree--;if (edge.linked.inDegree == 0) {queue.offer(edge.linked);}}}if (result.size() != graph.size()) {System.out.println("出现环");} else {for (String key : result) {System.out.println(key);}}}
}

3.DFS

public class TopologicalSortDFS {public static void main(String[] args) {Vertex v1 = new Vertex("网页基础");Vertex v2 = new Vertex("Java基础");Vertex v3 = new Vertex("JavaWeb");Vertex v4 = new Vertex("Spring框架");Vertex v5 = new Vertex("微服务框架");Vertex v6 = new Vertex("数据库");Vertex v7 = new Vertex("实战项目");v1.edges = List.of(new Edge(v3));v2.edges = List.of(new Edge(v3));v3.edges = List.of(new Edge(v4));v6.edges = List.of(new Edge(v4));v4.edges = List.of(new Edge(v5));v5.edges = List.of(new Edge(v7));v7.edges = List.of();List<Vertex> graph = List.of(v1, v2, v3, v4, v5, v6, v7);LinkedList<String> result = new LinkedList<>();for (Vertex v : graph) {if(v.status==0) {dfs(v, result);}}System.out.println(result);}private static void dfs(Vertex v, LinkedList<String> result) {if (v.status == 2) {return;}if (v.status == 1) {throw new RuntimeException("发现环");}v.status = 1;for (Edge edge : v.edges) {dfs(edge.linked, result);}v.status = 2;result.push(v.name);}
}

4.Kahn

是的,Kahn 算法是一种使用广度优先搜索(BFS)的拓扑排序算法。该算法是由 Arthur Kahn 于 1962 年提出的,用于对有向无环图(DAG)进行拓扑排序。

Kahn 算法的基本思想是不断找到入度为 0 的节点,然后从图中移除这些节点及其出边,直到所有节点都被处理。这个过程与广度优先搜索类似,因此它使用了 BFS 的思想。

Kahn 算法的主要步骤包括:

  1. 初始化一个队列,将所有入度为 0 的节点加入队列。
  2. 从队列中取出一个节点,将其加入拓扑排序的结果中,并移除与该节点关联的出边,相应地更新相关节点的入度。
  3. 重复步骤 2,直到队列为空。

Kahn 算法的时间复杂度为 O(V + E),其中 V 是图中的节点数,E 是图中的边数。它是一种有效的拓扑排序算法,用于处理有向无环图中的依赖关系。

四.习题

1.图-相关题目

题目编号题目标题算法思想
547省份数量DFS、BFS、并查集
797所有可能路径DFS、BFS
1584连接所有点的最小费用最小生成树
743网络延迟时间单源最短路径
787K 站中转内最便宜的航班单源最短路径
207课程表拓扑排序
210课程表 II拓扑排序

觉得有用的话点个赞 👍🏻 呗。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

img

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

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

相关文章

高数:第二章:一元函数微分学

文章目录 一、导数与微分1.导数的概念(1)导数的定义(2)左右导数(3)定理&#xff1a;可导与左右导数的关系(4)可导三要素(5)用导数定义判断可导性 2.微分的概念(1)微分的定义(2)微分与可导的关系 3.导数与微分的几何意义(1)导数 f ′ ( x 0 ) f(x_0) f′(x0​)的几何意义&#x…

1.6.C++项目:仿mudou库实现并发服务器之channel模块的设计

项目完整版在&#xff1a; 文章目录 一、channel模块&#xff1a;事件管理Channel类实现二、提供的功能三、实现思想&#xff08;一&#xff09;功能&#xff08;二&#xff09;意义&#xff08;三&#xff09;功能设计 四、代码&#xff08;一&#xff09;框架&#xff08;二…

python监控ES索引数量变化

文章目录 1, datafram根据相同的key聚合2, 数据合并&#xff1a;获取采集10,20,30分钟es索引数据脚本测试验证 1, datafram根据相同的key聚合 # 创建df1 > json {key:A, value:1 } {key:B, value:2 } data1 {key: [A, B], value: [1, 2]} df1 pd.DataFrame(data1)# 创建d…

【QT开发(6)】0926-QT 中加入 fastDDS 通信库的程序使用说明

在智能驾驶中&#xff0c;DDS有可能被广泛使用&#xff0c;因此推出这篇说明教程。 1、基于【QT开发&#xff08;5&#xff09;】教程的项目文档进行开发 2、安装DDS 查看《【eProsima Fast DDS&#xff08;1&#xff09;】安装eProsima Fast DDS》 至少安装: foonathan_m…

Sentinel学习(2)——sentinel的使用,引入依赖和配置 对消费者进行流控 对生产者进行熔断降级

前言 Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。 本篇博客介绍sentinel的使用&#x…

Source Insight 工具栏图标功能介绍

这篇文章并不介绍 Source Insight 的具体使用方法&#xff0c;这类教程网上有很多&#xff0c;这里只分析 Souce Insight 工具栏图标的功能。 文章目录 Source Insight 简介Souce Insight 工具栏文件操作新建&#xff08;CtrlN&#xff09;打开&#xff08;CtrlO&#xff09;保…

35 LRU缓存

LRU缓存 题解1 双map&#xff08;差2个testcases&#xff09;题解2 哈希表双向链表&#xff08;参考&#xff09;题解3 STL:listunordered_map 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正…

无人直播间

失败&#xff01;&#xff01; 采用 ffmpeg 技术进行推流 推流代码&#xff1a; 【需要将rtmp替换为你的推流地址】 ffmpeg -re -stream_loop -1 -i "rain.mp4" -c copy -f flv ""推流地址获取 以哔哩哔哩为例 点击下方链接 开播设置 - 个人中心 - …

CCF CSP认证 历年题目自练Day17

CCF CSP认证 历年题目自练Day17 题目一 试题编号&#xff1a; 201803-1 试题名称&#xff1a; 跳一跳 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 256.0MB 问题描述&#xff1a; 问题描述   近来&#xff0c;跳一跳这款小游戏风靡全国&#xff0c;受到不少玩家的喜爱…

小黑子的java项目开发理解

小黑子的理解 一、基于Maven模板构建的三种常见Java项目——基于maven二、通常的java目录结构utils层 工具包model层&#xff08;pojo层&#xff09;exceptions层 报错包dao层&#xff08;mapper层&#xff09;[impl包—查询数据库]service层 定义接口 [impl—实现事务]control…

Backblaze发布2023中期SSD故障数据质量报告

作为一家在2021年在美国纳斯达克上市的云端备份公司&#xff0c;Backblaze一直保持着对外定期发布HDD和SSD的故障率稳定性质量报告&#xff0c;给大家提供了一份真实应用场景下的稳定性分析参考数据。 本文我们主要看下Backblaze最新发布的2023中期SSD相关故障稳定性数据报告。…

施耐德电气:勾勒未来工业愿景,赋能中国市场

9月19日&#xff0c;第23届中国国际工业博览会&#xff08;简称“工博会”&#xff09;在上海隆重召开。作为全球能源管理和自动化领域的数字化转型专家&#xff0c;施耐德电气在工博会现场全方位展现了自身对未来工业的全新视野与深刻见解&#xff0c;不仅展示了其贯通企业设计…

ubuntu 18.04安装libjasper-dev 亲测可行

情况&#xff1a; ubuntu 18.04 LTS安装OpenCV 3.4.16之前&#xff0c;需要安装几个依赖项&#xff1a; sudo apt-get install build-essential sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev sudo apt-get instal…

计算机网络 - 应用层

计算机网络 - 应用层 计算机网络 - 应用层 域名系统文件传送协议动态主机配置协议远程登录协议电子邮件协议 1. SMTP2. POP33. IMAP 常用端口Web 页面请求过程 1. DHCP 配置主机信息2. ARP 解析 MAC 地址3. DNS 解析域名4. HTTP 请求页面 域名系统 DNS 是一个分布式数据库&a…

python -m pip install --upgrade pip失败

显示这样的报错&#xff1a; You are using pip version 9.0.1, however version 23.2.1 is available. You should consider upgrading via the python -m pip install --upgrade pip command. 换源安装 python -m pip install --upgrade pip -i https://pypi.douban.com/s…

基于SpringBoot的服装生产管理系统的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 登录界面的实现 系统主界面的实现 用户管理模块的实现 人事安排管理模块的实现 工资管理模块的实现 考勤管理模块的实现 样板管理模块的实现 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 本协力服装厂服装生…

TensorFlow-Federated简介与安装

1、简介 TensorFlow Federated&#xff08;TFF&#xff09;是一个用于机器学习和其他分布式数据计算的开源框架。TFF 的开发旨在促进联邦学习 &#xff08;FL&#xff09;的开放研究和实验。联邦学习是一种机器学习方法&#xff0c;其中一个共享的全局模型在许多参与的客户之间…

【GDB】用 python 扩展 gdb

用 python 扩展 GDB .gdbinit 文件中实现自定义命令 mv 代码如下 define mvif $argc 2delete $arg0# 注意新创建的断点编号和被删除断点的编号不同break $arg1elseprint "输入参数数目不对&#xff0c;help mv 以获得用法"end end# (gdb) help mv 会输出以下帮助文…

centos 6使用yum安装软件

1. 执行以下命令&#xff0c;查看当前操作系统 CentOS 版本。 cat /etc/centos-release返回结果如下图所示&#xff0c;则说明当前操作系统版本为 CentOS 6.9。 2. 执行以下命令&#xff0c;编辑 CentOS-Base.repo 和CentOS-Epel.repo文件。 vim /etc/yum.repos.d/CentOS-Bas…

Scrapy-应对反爬虫机制

参考自https://blog.csdn.net/y472360651/article/details/130002898 记得把BanSpider改成自己的项目名&#xff0c;还有一个细节要改一下&#xff0c;把代码user换成user_agent 禁止Cookie 在Scrapy项目中的settings文件&#xff0c;可以发现文件中有以下代码: COOKIES_ENA…