图是一种非线性表数据结构。
图中的元素我们就叫作顶点(vertex)。
一个顶点可以与任意其他顶点建立连接关系,这种建立的关系叫作边(edge)。
跟顶点相连接的边的条数,叫作顶点的度(degree)。
无向图
边没有方向的图就叫作“无向图”。
有向图
边有方向的图叫作“有向图”。
有向图中,把度分为入度(In-degree)和出度(Out-degree)。
顶点的入度,表示有多少条边指向这个顶点;
顶点的出度,表示有多少条边是以这个顶点为起点指向其他顶点。
带权图
带权图中,每条边都有一个权重 (weight),可以通过这个权重来表示 QQ 好友间的亲密度。
存储方法
邻接矩阵 Adjacency Matrix
邻接矩阵的底层依赖一个二维数组,
- 无向图
如果顶点 i 与顶点 j 之间有边,我们就 将 A[i][j] 和 A[j][i] 标记为 1; - 有向图
如果顶点 i 到顶点 j 之间,有一条箭头从顶点 i 指向顶点 j 的边,就将 A[i][j] 标记为 1;
如果有一条箭头从顶点 j 指向顶点 i 的 边,就将 A[j][i] 标记为 1; - 带权图,数组中就存储相应的权重。
优点: 简单、直观、获取关系时高效、运算方便
缺点: 浪费空间
首先,无向图中,如果 A[i][j] 等于 1,那 A[j][i] 也肯定等于 1,对角线上下两部分相等,浪费一半空间;
其次,存储的矩阵大都是稀疏矩阵,比如微信有好几亿的用户,对应到图上就是好几亿的顶点。但矩阵中绝大部分都是0。
邻接表 Adjacency List
结构类似于散列表,每个顶点对应一条链表,链表中存储的是与这个顶点相连接的其他顶点。
对于无向图类似,不过每个顶点的链表中存储的,是跟这个顶点有边相连的顶点。
这种方法节省空间,但是使用起来就比较耗时间。
若想判断是否存在一条从顶点 2 到顶点 4 的边,就要遍历 顶点 2 对应的那条链表,看链表中是否存在顶点 4。
可以将链表改成红黑树或跳表,以增加查找速度。
逆邻接表
以微博关注为例,
使用邻接表查找某个用户关注了哪些用户容易(某个顶点指向哪些其他顶点),
但是如果想知道某个用户都被哪些用户关注了,也就是用户的粉丝列表,是非常困难的。
这时,需要一个逆邻接表,来存储指向这个顶点的顶点。
本文是极客时间王争 数据结构与算法 课程的笔记,推荐此课,喜欢可以购买课程。