重回algo。
广度优先算法(BFS)。这个算法会用到队列的数据结构,简单说就是先进队列的结点最后会先出来,后进的后出。队列里最开始只有初始结点,让结点出队,然后分析每个这个结点能够连到的结点,如果目标结点没有被探索过(这里需要一个标记),标记它为已探索,然后让他入队,之后对每个入队的结点都对相同的处理。直到队列变为空队列,就意味着所有能够搜到的结点都搜完了。
这个算法是O(m+n)的。并且如果在做这个算法的时候多加一个标记,就可以顺便用来算其他所有结点相比于初始结点的最小路径。简单说就是初始结点的标记为0,那么从初始结点搜到的结点标记就为1,每搜到的新结点标记相比头结点加1。
当然还有深度优先算法(DFS)。深度有限算法是一个递归算法。它把所有结点分成两种状态:已完结和未完结。从初始结点出发搜下一个点,如果没有点可搜,标记该点为已完结并返回它的头结点,如果有点可搜,那么如果是已发现的就无视它,如果未发现,就对该点递归该算法。
同样它也是O(m+n)的。这个算法可以用来给有向图做拓扑排序。
拓扑排序就是把有向图的结点做成人体蜈蚣形状的(喂)。一个显而易见的思路就是找一个没有出边的结点,如果找不到就说明有向图有内循环,做不了拓扑排序,能找到的话,就删掉这个结点和与它相连的边,然后对剩余的有向图递归该算法。
不过实际上也很显然,在DFS的时候顺便加一个标记就可以顺手解决拓扑排序问题了。只需要把结点的完结顺序记录下来,然后一字排开就好了。
DFS还有一个应用就是寻找 strongly connected components (SCC),SCC就是一堆结点的集合,在这集合里面每个结点之间都能互通。一般来说可以把一个巨型图拆解为不同的SCC的集合。 寻找SCC的kosaraju算法基本流程就是把有向图的方向倒过来,对这个反向图做一次DFS,初始点可以随机的,把结点的完结顺序纪录下来。之后对正向图再做一次DFS,不过这里初始点就不能乱选了,要选之前那次DFS中最晚完结的点,以它开始做DFS,当它结束时,此时已完结的结点集合就构成了一个SCC。之后找到新的(此次DFS还没完结的)最晚完结的点,继续此次DFS,后面的流程类似,到最后所有点都完结的时候就得到了多个SCC了。
kosaraju算法的证明吧。。。抱歉我又没看懂。。。这里面SCC之间临界结点的部分是比较tricky的,我听的云里雾里。不过很显然它也是O(m+n)的。后面光头哥讲了一个SCC的直接应用,就是互联网网页之间的有向图关系,还蛮有趣的。