图
一种非线性的数据结构,它表明了物件与物件之间“多对多”的一种复杂关系。
图包含了两个基本元素:顶点(vertex,简称V)和边(edge,简称E)。V 是节点的有限非空集合(在图结构中不允许没有顶点),E是节点的二元组集合,节点二元组称为边。V(G) 和 E(G) 分别称为图G的节点集(顶点集)与边集,也可用 G=(V, E) 表示图。
分类
简单图
在一个图中,若不存在顶点到其自身的边,且同一条边不重复出现,则称这样的图为简单图。
如下所示的两个图就不属于简单图(属于多重图):
多重图
在一个图中,某两节点之间的边数多于一条,且允许顶点通过一条边与自身关联,则称该图为多重图。
无向图
若顶点 Vi 到 Vj 之间的边没有方向,则称这条边为无向边(Edge),用无序偶对 (Vi, Vj) 来表示。如果图中任意两个顶点之间的边都是无向边,则称该图为无向图(Undirected Graphs)。
顶点集:V1 = { A, B, C, D }
边集:E1 = { (A, B), (B, C), (A, C), (A, D) }
有向图
若从顶点 Vi 到 Vj 的边有方向,则称这条边为有向边,也称为弧(Arc)。一般采用尖括号括起来表示,例如<Vi , Vj>。前者 Vi 称为弧尾(Tail),后者 Vj 称为弧头(Head)。如果图中任意两个顶点之间的边都是有向边,则称该图为有向图(Directed graphs)。
顶点集:V2 = { A, B, C, D }
弧集:E2 = {<B, A>, <A, D>, <A, C>, <B, C>}
无向完全图
在一个具有 n 个顶点的无向图中,倘若每个顶点与其他 n-1 个顶点之间都有边相连,则会有 n(n-1)/2 条边,这是具有 n 个顶点的无向图可能的最大边数。一个具有 n(n-1)/2 条边的 n 个顶点的无向图被称为无向完全图。
在无向图中,如果任意两个顶点之间都存在边,则称该图为 无向完全图。
有向完全图
在一个具有 n 顶点的有向图中,最多可能有 n(n-1) 条弧,具有 n(n-1) 条弧的 n 个顶点的有向图称为有向完全图。
在有向图中,如果任意两个顶点之间都存在 方向互为相反 的两条弧,
则称该图为 有向完全图。
有权图(网)
如果图的边有各自的权重,得到的图是有权图。
弧边上有权值,带权值的图称为网。
无权图
如果图的边没有权重,或者权重都一样(即没有区分),被称为无权图。
基本术语
邻接
若(V1,V2)是 E(G) 中的一条边,则称顶点 V1 和 V2 是相邻接(Adjacent)的顶点,称边(V1,V2)是依附于顶点 V1 和 V2 的边。
路径
顶点 Vi 到顶点 Vj 之间的连线称为路径(Path)。
简单路径
在一条路径中,若除了第一个顶点和最后一个顶点外,其余顶点各不相同,则称此路径为简单路径。
回路(环)
若一条路径的起点和终点相同( 即 Vi = Vj ),则称此路径为回路或者环。
一个拥有 n 个节点的图,若 |E| > n-1,则一定存在回路。(因为拥有 n 个节点的树,必有 n-1 条边)
简单回路(简单环)
在一个图的序列中除了第一个顶点与最后一个顶点之外,其他顶点不重复出现的回路 称为简单回路或者简单环。
顶点的度、入度、出度
顶点的度是指依附于某顶点 Vi 的边数,通常记为 TD(Vi);
顶点的入度(InDegree)是指以 Vi 为终点的弧的数目,记为 ID(Vi);
顶点的出度(OutDegree)是指以 Vi 为始点的弧的数目,记为 OD(Vi);
于是,在一个有向图中,有:TD(Vi) = ID(Vi) + OD(Vi)。
连通
若从顶点 Vi 到顶点 Vj( i ≠ j )有路径,则 Vi 和 Vj 是连通的。
连通图
在无向图中,若任意两个顶点 Vi 和 Vj 都是连通的,则称这样的无向图为连通图。
强连通图
在有向图中,若任意一对顶点 Vi 和 Vj( i ≠ j )均有 从 Vi 到 Vj 和 从 Vj 到 Vi 的 有向路径(不用在意方向),则称该有向图为强连通图。
一个连通图最多有 n(n-1)/2 条边;一个强连通图最多有 n(n-1) 条边,最少有 n 条边。
子图
连通分量
强连通分量
生成树
生成森林
稀疏图、稠密图
存储
邻接矩阵(Adjacency Matrex)
使用两个数组来表示图,其中一个是一维数组,用来保存图中的各个顶点信息;另一个是二维数组(称为邻接矩阵),用来存储图中的边或弧的信息。
在邻接矩阵中,使用 0 表示两个顶点之间不相连,使用 1 表示两个顶点之间相连。
邻接表(Adjacency Lists)
一种顺序分配和链式分配相结合的存储结构。它包括两个部分:一部分是数组,另一部分是链表。数组用来存放每条单链表的表头,由数组的特性可知,定位每条单链表的时间都是O(1)。
遍历
深度优先搜索(Depth-first Search, DFS)
1)从一个选定的点出发;
2)访问与 当前选定的点 直接相连且未被访问过的点,标记为“已访问”,重复 1),若与当前节点相邻的节点均已被访问,则 3);
3)从当前点退回其“来处”的点,判断是否存在与这个点直接相连且未被访问的点,若存在则选定并 2),若不存在则 3)。直到没有未被访问的点为止。
广度优先搜索(Breadth-First Search, BFS)
1)入队一个节点;
2)入队与该节点相邻的且未被访问过的节点,然后出队该节点;
3)重复 2),直到所有的节点均被访问。