图,树,图的遍历顺序(Graphs,Trees and Traversal Oreder of Graphs)

图,树,图的遍历顺序(Graphs,Trees and Traversal Oreder of Graphs)

主要介绍在编译器中使用到的图、树和图的遍历顺序。

图 Graphs

在图论中,图是一种数学结构,用来表示一组对象,这些对象之间有一些成对的关系。对象可以包含任意信息,例如单个值、某段代码或公司员工的姓名,具体取决于图的用途。

这里我们尽可能简单地用一个字母标识每个对象,将图中对象成为顶点(vertices),对象间关系成为边(edges)。使用 G = ( V , E ) G = (V,E) G=(V,E) 描述顶点V 和边E 的集合,顶点V 的个数为 n = ∣ V ∣ n = |V| n=∣V∣,边的个数 m = ∣ E ∣ m = |E| m=∣E∣。

边用于描述顶点的移动,这种移动称为路径,边可以是有方向的,也可以是无方向的。也就是说,通过多个顶点到顶点的边,可能从顶点y到达顶点v。图中y到v的路径可以记为: y   ∗ → G   v _y \ \underrightarrow{*}_G\ {_v} y​  ∗​G​ v​ 。图可以有一个根节点r,表示图的起点,这时候图记为 G = ( V , E , r ) G=(V,E,r) G=(V,E,r)。

本文中,图中的边用虚线边,树的边用实线边,下面是一个有向图。
图,树,图的遍历顺序(Graphs,Trees and Traversal Oreder of Graphs)

树 Trees

树是图的子集,这意味着树由相同的元素组成,例如顶点、有向边、无向边和根。树中不能有任何循环路径,因此树中的顶点具有层次顺序。这意味着每个顶点都与树中的其他顶点有某种关系。下面介绍树T的一些关系。

  • Root:树顶部的顶点,记为r
  • 路径 Path:树中的路径是连接一个顶点到另一个顶点的顶点和边的序列,顶点y到顶点v的路径记为 y   ∗ → T   v _y \ \underrightarrow{*}_T\ {_v} y​  ∗​T​ v​ 。
  • 深度 Depth:一个顶点v的深是路径 r   ∗ → T   v _r \ \underrightarrow{*}_T\ {_v} r​  ∗​T​ v​上边的数目。
  • 父亲 Parent:如果在树上存在一个边 ( p , v ) (p,v) (p,v),则顶点p是顶点v的父亲。
  • 孩子 Child:如果在树上存在一个边 ( p , v ) (p,v) (p,v),则顶点v是顶点p的父亲。
  • 兄弟 Sibling:有相同父亲的顶点。
  • 祖先 Ancestor:如果a在路径 a   ∗ → T   v _a \ \underrightarrow{*}_T\ {_v} a​  ∗​T​ v​ (包括v)上,则顶点a是v的祖先。
  • 后代 Descendant:顶点a是顶点v的祖先,则va的后代,包括顶点自己。
  • 真祖先 Proper Ancestor:和祖先的一样,但不包括自己,真祖先a到顶点v的路径记为: a   + → T   v _a \ \underrightarrow{+}_T\ {_v} a​  +​T​ v​ 。
  • 真后代 Proper descendant:和后代一样,但不包括自己。
  • 子树 Subtree:顶点v是树中的一个顶点,有v和其后代组成的的树为T的子树,顶点v是该子树的根。
  • 单体 Singlenton:只有一个顶点的树。
  • 森林 Forest:森林就是一系列的树,这些树不互相连接。

遍历顺序 Traversal Order

遍历一个图或树,就是访问他们的每个节点。图和树的遍历顺序非常多,这里介绍一种叫做深度优先搜索 (DFS:Depth-First-Search)方法,并由此产生的四种遍历顺序。

深度优先搜索算法:沿着图或树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。

并由DFS产生4种遍历顺序:

  • 前序遍历 Pre-order:以DFS搜序一个顶点没有编号的图,每个定点在发现时进行编号,这个顺序就是前序遍历。
  • 后序遍历 Post-order:一个顶点所有出边到达的顶点都被访问过后,它所获得的编号。
  • 逆前序 Reverse pre-order:前序的逆序。
  • 逆后序 Reverse post-order:后序的逆序。

图,树,图的遍历顺序(Graphs,Trees and Traversal Oreder of Graphs)
这个图中,所有黑色线都是图的一部分,但是只有直线是图的DFS生成的树(DFST: Depth-Fist Spanning Tree)的一部分,红线是DFS的搜索路径。
图,树,图的遍历顺序(Graphs,Trees and Traversal Oreder of Graphs)
在龙书介绍了DFS的算法,以上面这个有向图为例。
图,树,图的遍历顺序(Graphs,Trees and Traversal Oreder of Graphs)
图,树,图的遍历顺序(Graphs,Trees and Traversal Oreder of Graphs)
对于逆后序(RPO),又称为深度优先排序(depth-first order)是编译器中做数据流迭代时候常选用的遍历顺序,它可以加快求解不动点的速度。

DAG的拓扑排序,就是任意一条边 n->m,节点 n 都先于节点 m 。

对于有向无环图(DAG),其实逆后序就是拓扑排序。如果一个有向图没有环的话,也就是一个DAG,已拓扑排序或者RPO顺序遍历只需要一次迭代便可以收敛(得到不动点),因为根据拓扑排序的定义可以知道,访问一个节点前它的前驱都已经访问过了。

但对于有环的有向图CFG,其实不存在拓扑排序,这时候已逆后序RPO顺序遍历,可以加速算法。

参考

  • [1] Algorithms for Finding Dominators in Directed Graphs
  • [2] 龙书
上一篇:line XX: 12364 Killed 报错


下一篇:《Inductive Representation Learning on Large Graphs》论文阅读(GraphSAGE)