深度优先算法
问题
给定一个有向图,推断其顶点是否能到达另外一个顶点。
解决的方法
使用深度优先算法。和无向图中的是一样的。
代码
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());
}
}
}
}