图论算法(3):图的基本表示(邻接矩阵、邻接表、邻接矩阵与邻接表的对比)

本文详细介绍了图的两种基本表示方法——邻接矩阵和邻接表,包括它们的概念、优缺点以及Java实现。针对无向图,邻接矩阵是对称的,而邻接表在空间复杂度和查找相邻节点上更优。通过具体示例和代码展示,阐述了邻接表如何使用红黑树或哈希表提高效率。最后,鉴于空间复杂度考虑,选择了邻接表作为图的首选表示方式。
摘要由CSDN通过智能技术生成

本章节内容使用 java 实现,Github 代码仓:https://github.com/ZhekaiLi/Code/tree/main/Graph/src

查看文章内的图片可能需要科学上网! 因为使用了github管理图片,因此如果出现无法加载的情况请翻墙

【参考资料】imooc 波波老师:玩转算法系列–图论精讲 面试升职必备(Java版)

【往期博客链接】
图论算法(1、2):图的分类、图的基本概念(无向图与有向图、无权图、无环图、完全图、二分图;简单图、连通分量、图的生成树、子图与母图)
图论算法(3):图的基本表示(邻接矩阵、邻接表、邻接矩阵与邻接表的对比)
图论算法(4):图的深度优先遍历 DFS
图论算法(5):图的广度优先遍历 BFS
图论算法(6):LeetCode 图论算法练习(785.判断二分图、695.岛屿的最大面积、Floodfill 算法、并查集)

3. 图的基本表示

3.1 邻接矩阵

G = ( V , E ) G = (V, E) G=(V,E)邻接矩阵(adjacency matrix) C C C 是如下定义的:
C = ( c i j ) n × n ∈ { 0 , 1 } n × n c i j = { 1 ,      ( i , j ) ∈ E 0 ,      ( i , j ) ∉ E \begin{aligned} C&=(c_{ij})_{n\times n}\in\{0,1\}^{n\times n}\\ c_{ij}&=\begin{cases} 1,\;\;(i,j)\in E\\ 0,\;\;(i,j)\notin E \end{cases} \end{aligned} Ccij=(cij)n×n{0,1}n×n={1,(i,j)E0,(i,j)/E


示例:有向图及其邻接矩阵

而对于无向图来说,其邻接矩阵是对称的( c i j = c j i c_{ij}=c_{ji} cij=cji

可以用下图中央这样的两列数据来表示一个无向图,然后将其翻译为邻接矩阵



java 实现:AdjMatrix.java

3.2 邻接表

为什么要引入邻接表?(邻接矩阵的复杂度)



邻接矩阵的的建图时间复杂度 O ( E ) O(E) O(E)(遍历每条边),以及判断两点是否相邻的时间复杂度 O ( 1 ) O(1) O(1) 没有提升空间,但其空间复杂度以及求相邻节点的时间复杂度较大

尤其是例如对于一个有3000个节点的树(无向图),它只有2999条边,即使是乘2也只有6000不到组数据,但是其对应的邻接矩阵的空间复杂度却是 O ( 300 0 2 ) O(3000^2) O(30002)近千倍的差距!

邻接表的定义

图的邻接表(adjacency list) 是所有节点的邻接表的集合
各节点的邻接表由其:

  1. 邻边(无向图)
  2. 出弧(有向图)

组成,并用一个单向链表列出,链表中每个单元对应于一条邻边/出弧,此外还可以包含弧上的权等作为数据域。

邻接表的表示

对于有向图 G = ( V , E ) G = (V, E) G=(V,E),一般用 A ( i ) A(i) A(i) 表示节点 i i i 的邻接表,即节点 i i i 的所有出弧构成的集合或链表

对于无向图 A ( i ) A(i) A(i) 则表示节点 i i i 邻边的集合

图的整个邻接表还可以用一个指针数组表示。例如:(下图中第一个指针数组表示, 1 → 2 1\to2 12 的权重为8, 1 → 3 1\to3 13 的权重为9)



java 实现:AdjList.java

邻接表的复杂度



相较于邻接矩阵的复杂度,邻接表在空间复杂度、求相邻节点的时间复杂度这两方面有明显优势,但其建图的时间复杂度、判断两点是否相邻的时间复杂度较大

降低这两个复杂度的关键在于实现快速查看重复边/ 快速判断两点是否相邻,因此我们可以使用哈希表 O ( 1 ) O(1) O(1) 或红黑树 O ( log ⁡ V ) O(\log V) O(logV) 代替链表(在 java 中分别对应 HashSet, TreeSet, LinkedList)

java 实现:Graph.java(使用红黑树)

3.3 比较:矩阵 vs 两种表



因此我门最终选用邻接表(TreeSet) 作为图的表达形式(当然也可以使用HashSet)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江湖留名

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值