首页 > 代码库 > 算法7-9:有向图搜索算法

算法7-9:有向图搜索算法

深度优先算法


问题


给定一个有向图,判断其顶点能否到达另外一个顶点。


解决办法


使用深度优先算法,和无向图中的是一样的。


代码

import java.util.Stack;
 
/**
 * Created by caipeichao on 14-6-11.
 */
 
public class DigraphDFS {
    private int s;
    private boolean[] visited;
    private int[] edgeTo;
 
    public DigraphDFS(Digraph G, int s) {
        this.s = s;
        visited = new boolean[G.V()];
        edgeTo = new int[G.V()];
        dfs(G, s);
    }
 
    private void dfs(Digraph G, int s) {
        visited[s] = true;
        for (int v : G.adj(s)) {
            if (!visited[v]) {
                edgeTo[v] = s;
                dfs(G, v);
            }
        }
    }
 
    public boolean hasPathTo(int v) {
        return visited[v];
    }
 
    public Iterable<Integer> pathTo(int v) {
        if (!hasPathTo(v)) return null;
        Stack<Integer> result = new Stack<Integer>();
        while (v != s) {
            result.add(v);
            v = edgeTo[v];
        }
        return result;
    }
}


应用


深度优先搜索算法可以用在程序的控制流分析中,分析哪段代码不会被执行,分析代码中可能存在的死循环问题。


DFS还可以应用在垃圾回收中,比如Java的垃圾回收。



关于垃圾回收,比较常用的有mark-sweep算法,有兴趣的同学可以去了解一下。


DFS还可以用于路径查找、拓扑排序、回路检测,这里就不再赘述了。


宽度优先搜索


代码和无向图的代码是一模一样的,这里就不展示了。


下面我们动手去实现一个非常简易的网络爬虫。网络爬虫用的其实就是宽度优先算法。首先是在队列中增加一个URL,然后每次从队列中取出一个URL,获取URL对应的网页,分析网页中存在的其他URL,再放入队列。这样一个简单的网络爬虫就实现了。代码如下:

import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class WebSpider {
    public static void main(String[] argv) {
        // 初始化队列
        LinkedQueue<String> urls = new LinkedQueue<String>();
        Set<String> discovered = new LinkedHashSet<String>();
        urls.enqueue("http://www.baidu.com/");
 
        // 初始化正则匹配,用于匹配URL
        String regex = "http://[A-z0-9.\\-+_/%?=]+";
        Pattern pattern = Pattern.compile(regex);
 
        // 每次从队列中获取一个网页
        while (!urls.isEmpty()) {
            try {
                String url = urls.dequeue();
                StdOut.println(url);
                In in = new In(url);
                String html = in.readAll();
 
                // 找出网页中的URL
                Matcher matcher = pattern.matcher(html);
                while (matcher.find()) {
                    String u = matcher.group();
                    if (!discovered.contains(u)) {
                        discovered.add(u); // 注意:这句话不要忘记了
                        urls.enqueue(u);
                    }
                }
            } catch(Exception ex){
                StdOut.println("Error: " + ex.toString());
            }
        }
    }
}