最近复习 FBRetainCycleDetector
源码的时候,需要的图的查询方法,深度优先搜索,这里记录下,便于系统复习。
这里仅仅为分析FBRetainCycleDetector
实现原理,采用深度优先搜索DFS
图
图由顶点(vertex)
和边(edge)
组成,通常表示为 G = (V, E)
- G表示一个图,V是顶点集,E是边集
- 顶点集V有穷且非空
- 任意两个顶点之间都可以用边来表示它们之间的关系,边集E可以是空的
有向图
-
有向图的边是有明确方向的
-
有向无环图(
Directed Acyclic Graph
,简称DAG
) -
如果一个有向图,从任意顶点出发无法经过若干条边回到该顶点,那么它就是一个
有向无环图
图的实现方式
邻接矩阵(Adjacency Matrix)
邻接矩阵的存储方式
- 一维数组存放顶点信息
- 二维数组存放边信息
邻接矩阵比较适合稠密图,不然会比较浪费内存
邻接表(Adjacency List)
使用链表存储
图的知识有很多,包括有向图
无向图
混合图
,对于Object-C
的对象引用,A->B->C
我们可以作为有向图
来处理。
遍历
广度优先搜索 BFS
BFS 相当于一个层级遍历,一层一层遍历,然后寻找路线最短的一条线。
相当于二叉树中的层序遍历,需要缓存各个层级,然后找到深度最低的那一条。
左侧为无序图时的遍历,右侧为有序图时的遍历。由于需要检索层级每个节点,所以做了很多无关运算。
优点是能够找到一个最优解
,而且速度快,但是需要存储各个节点信息,占用内存大。
深度优先搜索 DFS
DFS
则只会查找一条线路,当线路无法到达时,就原路返回,尝试其他分支。
二叉树的前序遍历就是一种。
优点不用遍历每个层级,找到之后就不会再遍历。找到的或许不是最优解,但是占用的内存较少,不用存储产生的所有节点。由于需要栈结构进行出栈入栈
,所以往往要比广度优先搜索 BFS
慢一些,但不是绝对。
可以查看这篇文章看流程 https://www.jianshu.com/p/bff70b786bb6
FBRetainCycleDetector的应用
那么我们通过找到A
对象的strong
引用的成员B
,然后进行深度优先搜索
,如果能够找到B
到达A
的强引用路线,则认为是有循环引用关系。
FBRetainCycleDetector
默认的搜索深度是10
,也一般能处理大部分的循环引用问题了。