什么是深度/广度优先遍历(DFS/BFS)?
深度优先遍历简称DFS(Depth First Search),广度优先遍历简称BFS(Breadth First Search),它们是遍历图当中所有顶点的两种方式。
这两种遍历方式有什么不同呢?我们来举个栗子:
我们来到一个游乐场,游乐场里有11个景点。我们从景点0开始,要玩遍游乐场的所有景点,可以有什么样的游玩次序呢?
第一种:
一头扎到底的玩法。我们选择一条支路,尽可能不断地深入,如果遇到死路就往回退,回退过程中如果遇到没探索过的支路,就进入该支路继续深入。
像这样先深入探索,走到头再回退寻找其他出路的遍历方式,就叫做深度优先遍历(DFS)。
除了像深度优先遍历这样一头扎到底的玩法以外,我们还有
另一种玩法:
首先把起点相邻的几个景点玩遍,然后去玩距离起点稍远一些(隔一层)的景点,然后再去玩距离起点更远一些(隔两层)的景点......
像这样一层一层由内而外的遍历方式,就叫做广度优先遍历(BFS)。
这种方式看上去很像二叉树的层序遍历,其实,二叉树的层序遍历,本质上也可以被认为是广度优先遍历。
深度/广度优先遍历 的实现
DFS VS BFS
那么如何实现深度优先遍历和广度优先遍历算法呢?
实现深度优先遍历的关键在于【回溯】,
实现广度优先遍历的关键在于【重放】。
深度优先遍历DFS
首先说说深度优先遍历的实现过程。这里所说的回溯是什么意思呢?
回溯,顾名思义,就是自后向前,追溯曾经走过的路径。要想实现回溯,可以利用栈的先入后出特性,也可以采用递归的方式(因为递归本身就是基于方法调用栈来实现)。
演算方法:
首先将根节点放入stack中。
从stack中取出第一个节点,并检验它是否为目标。
重复步骤2。
如果不存在未检测过的直接子节点。
重复步骤4。
若stack为空,表示整张图都检查过了——亦即图中没有欲搜寻的目标。结束搜寻并回传“找不到目标”。
举个栗子:
树是图的一种特例(连通无环的图就是树),接下来我们来看看树用深度优先遍历该怎么遍历。
1、我们从根节点 1 开始遍历,它相邻的节点有 2,3,4,先遍历节点 2,再遍历 2 的子节点 5,然后再遍历 5 的子节点 9。