图,树,遍历顺序 Graphs,Trees and Traversal Order

图,树,遍历顺序 Graphs,Trees and Traversal Order

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

图 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)

本文中,图中的边用虚线边,树的边用实线边,下面是一个有向图。
graph

树 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:后序的逆序。

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

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

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

但对于有环的有向图CFG,其实不存在拓扑排序,但是深度优先排序这种类似拓扑排序依然能够减少有环图的迭代次数,因为大多数节点的访问都先于其后继。

参考

  • [1] Algorithms for Finding Dominators in Directed Graphs
  • [2] 龙书
  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值