在有向图中,边是单向的:每条边所连接的两个顶点都是一个有序对,它们的邻接性是单向的。许多应用(网络、任务调度条件或是电话的图)都是天然的有向图。
应用 | 顶点 | 边 |
食物链 | 物种 | 捕食关系 |
互联网连接 | 网页 | 超链接 |
程序 | 模块 | 外部引用 |
手机 | 电话 | 呼叫 |
学术研究 | 论文 | 引用 |
金融 | 股票 | 交易 |
网络 | 计算机 | 网络连接 |
4.2.1术语
虽然有向图的定义和无向图几乎相同,但本节为了说明边的方向性而产生细小文字差异所代表的的结构特性正是本节的重点。
定义:
一幅有方向性的图(或是有向图)是由一组顶点和一组有方向的边组成的,每条有方向的边连接着有序的一对顶点。
在一幅有向图中,一个顶点的出度为由该顶点指出的边的总数;一个顶点的入度为指向该顶点的边的总数。一条有向边的第一个顶点称为它的头,第二个顶点则被称为它的尾。一幅有向图中的两个顶点的关系可能有4种:没有边相连;存在从v到w的边相连v--->w; 存在从w-->v的边;既存在v->w也存在w->v, 即双向的连接。
定义: 在一幅有向图中,有向路径由一系列顶点组成,对于其中的每个顶点都存在一条有向边从它指向序列中的下一个顶点。有向环为一条至少含有一条边且起点和终点相同的有向路径。简单有向环是一条不含有重复的顶点和边的环。路径或者环的长度即为其中所包含的边数。
当存在从v到w的路径时,称顶点w能够从顶点v到达。每个顶点都能够达到它自己。
4.2.2 有向图的数据类型
在使用邻接表表示无向图时,如果v在w链表中,那么w必然也在v的链表中,但是在有向图中这种对称性是不存在的。这个区别在有向图的处理中影响深远。
4.2.2.1 有向图的表示
我们使用邻接表来表示有向图,其中边v->w表示顶点v所对应的的邻接链表中包含一个w顶点。
4.2.2.2 输入格式
由输入流读取有向图的构造函数的代码与Graph类中相应构造函数相同,但是边都是有向的。
4.2.3 有向图中的可达性
对于无向图中的DepthFirstSearch ,它解决了单点连通性的问题,使得用例可以判断其他顶点和给定顶点的起点是否连通。使用完全代码将其中的Graph替换为Digraph,解决一下问题
- 单点可达性:给定一幅有向图和一个起点s, 回答“是否妇女在一条从s到达给定顶点v的有向路径”
在添加一个或接受多个顶点的构造函数之后,这份API可以解决一个更加一般的问题。
- 多点可达性:给定一幅有向图和顶点的集合,回答“是否存在一条从集合中的任意顶点到达给定顶点v的有向路径?”等类似问题。
注意:无论是有向图还是无向图,在使用特定的搜索算法(深度优先搜索算法和广度优先搜索算法),在定义的时候,先将给定的起点点与相连通的结点遍历一遍,然后对于可遍历到的图结点要标上符号,然后在main函数中,用于判断给定结点在符号数组中是否可达。
4.2.3.1 标记-清除的垃圾收集
多点可达性的一个重要的实际应用是在典型的内存管理系统中,包括许多java的实现。
在一幅有向图中,一个顶点表示一个对象,一条边则表示一个对象对另一个对象的引用。这个模型很好地表现了运行中的java程序的内存使用状况。在程序执行的任何时候都有某些对象是可以被直接访问的,而不能通过这些对象访问到的所有对象都应该被回收以便释放内存。标记-清除的垃圾回收策略会为每个对象保留一个位做垃圾收集之用。它会周期性地运行与一个类似于DirectedDFS的有向图可达性算法来标记所有可以被访问到的对象,然后清理所有对象,回收没有被标记的对象,以腾出内存供信的对象使用。
4.2.3.2 有向图的寻路
4.2.4 环和有向无环图
在有向图中确定有向环的存在
4.2.4.1 调度问题
一种应广泛的模型是给定一组任务并安排它们的执行顺序,限制条件是这些任务的执行方法和起始时间。限制条件还可能包括任务的时耗以及消耗的其他资源。最重要的一种限制条件叫做优先级限制,它指明了哪些任务必须在哪些任务之前完成。不同的限制条件会产生不同类型不同难度的调度问题。在有向图中,优先级限制下的调度问题等价于下面这个基本问题。
- 拓扑排序。给定一幅有向图,将所有的顶点排序,使得所有的有向边均从排在前面的元素指向排在后面的元素。
4.2.4.2 有向图中的环
有向环检测:一如果给定有向图中包含环,按照路径的方向从某个顶点并返回自己来找到环上的所有顶点。在任务调度和其他许多实际问题中不允许出现有向环,因此不含有环的有向图就变得很特殊。
定义:如果有向无环图(DAG)就是一幅不含有环的有向图。
解决有向图检测的问题可以回答下面这个问题:一幅有向图是有向无环图吗??基于深度优先搜索来解决这个问题并不困难,因为有系统维护的递归调用的栈表示的正是“当前”正在遍历的有向路径。一旦我们找到了一条边v->w 且w已经存在于栈中,就找到了一个环,因为栈表示的是一条由w到v的有向路径,而v->w正好补全了这个环。同时,没有找到这样的边,那就意味着这幅有向图是无环的。
·
4.2.4.3 顶点的深度优先次序和拓扑排序
优先级限制下的调度问题等价于计算有向无环图的所有顶点的拓扑排序。
命题E:当且仅当一幅有向图是无环图时它才能进行拓扑排序。
证明:如果一幅有向图含有一个环,它就不可能是拓扑有序的。与此相反,我们将要学习的算法能够计算任意有向无环图的拓扑顺序。
根据算法有向图中基于深度优先搜索的顶点排序。它的基本思想是深度优先搜索正好只会访问每个顶点一次,如果将dfs() 的参数顶点保存在一个数据结构中,遍历这个数据结构实际上就能访问图中的所有顶点,遍历的顺序取决于这个数据结构的性质
4.2.5 有向图只能怪的强连通性
在前文中,我们仔细区别了有向图中的可达性和无向图中的连通性。无向图中,如果两结点之间有路径,则两结点之间是相互连通的。无向图中,必须是从v--> w , 而且是w-->v的才能算是连通的。
定义:如果两个顶点v和w是互相可达的,则称他们为强连通的,也就是说,既存在一条从v到w的有向路径,也存在一条从w到v的有向路径。如果一幅有向图中的任意两个顶点都是强连通的,则称这幅有向图也是强连通的。
一条普通的有向环可能含有重复的顶点就很容知道,两个顶点是强连通的当且仅当它们都在一个普通的有向环中。
4.2.5.1 强连通分量
和无向图中的连通性一样,有向图中的强连通性也是一种顶点之间平等关系,因为它有着以下关系:自反性,对称性,传递性。
强连通性将所有顶点分为了一些平等的部分,每个部分都是由相互均为强连通的顶点的最大子集组成的。我们将这些子集称为强连通分量,一个含有V个顶点的有向无环图含有V个强连通分量。强连通分量的定义是基于顶点的而非边的,有些边连接的两个顶点逗仔同一强连通分量中,而有些边连接的两个顶点则在不同的连通分量中。在有向图中识别强连通分量对于有向图处理也是非常重要的。
4.2.5.2 应用举例
理解有向图时,强连通性是一种非常重要的抽象,它突出了相互关联的几组顶点(强连通分量)
4.2.5.3 Kosaraju 算法
计算无向图中的连通分量只是深度优先搜索的一个简单应用。