您的位置:首页 > 其它

无向图的Depth-first search和Breadth-first Search

2018-03-31 14:23 435 查看
1. Depth-first search和Breadth-first search有什么用?
从它们的名字中可以看出,这两者都是图的搜索算法。不同于树的搜索,图搜索的基本思路是遍历每一个vertex,直到找到我们想要的结果。这两个算法实际上都是遍历。前面我们建立起了图结构,我们可以直接知道每个vertex相邻近的vertex有哪些,但是不能直接知道任意两个vertex之间是什么关系(比如它们之间的路径啊,是不是相连啊等等)。基于Depth-first search和Breadth-first search算法,我们可以高效地解决这一问题。

2. Depth-first search的应用一:查找路径。
给定一个源头vertex(假设叫s),和任意一个vertex,他们之间的连接路径是怎样的?为了解决这一问题,我们可以用Depth-first search算法。思路如下:首先新建两个数组,一个boolean类型,叫marked,用来记录vertex是不是被检验过(为了避免重复);一个int类型,叫edgeTo,用于记录某vertex上面连接着啥玩意儿。在遍历与s相关vertex的同时(即Depth-first search),我们顺便操作一下这两个数组。这样结束的时候,所有路径信息都被记录在edgeTo数组里面,我们可以从非常方便的查找某vertex到s的路径信息。代码如下:
public class DepthFirstPath{
private boolean[] marked;
//edgeTo数组,用于记录路径信息。
private int[] edgeTo;
private final int s;

public DepthFirstPath(Graph G, int s)
{
this.s = s;
//初始化marked以及edgeTo数组,长度就是G图内vertex的个数。
marked = new boolean[G.V()];
edgeTo = new int[G.V()];
dfs(G, s);
}

private void dfs(Graph G, int v)
{
marked[v] = true;
for(int w : G.adj(v))
if(!marked[w])
{
//这个便是dfs的顺便操作,在遍历相关vertex的同时,
//顺便操作了edgeTo数组。
edgeTo[w] = v;
dfs(w);
}
}

public boolean hasPath(int v)
//未被标记(marked值为false),说明该vertex跟s不相连,自然没有path。
{ return marked[v]; }

public Iterable path(int v)
{
if(!hasPath(v)) return null;
Stack<Integer> path = new Stack<>();
for(int x = v; x != s; x = edgeTo[x])
//路径信息提取出来,保存到stack里面。
path.push(x);
path.push(s);
return path;
}
}
3. Breadth-first search的应用一:查找路径。
Breadth-first search也是一种遍历所有元素的算法。从它的名字中就可以看出,这种算法是讲究宽度,而不是深度。Depth-first search是沿某一支不断深入下去,到头了就再回到上一节点再往下找。而Breadth-first search是很多支一起,一层层的往下进展的。当然也可以顺便操作edgeTo数组,记录路径信息。public class BreadthFirstPaths
{
private int[] edgeTo;
private boolean[] marked[];
private int s;

public BreadthFirstPaths(Graph G, int s)
{
maeked = new boolean[G.V()];
edgeTo = new int[G.V()];
this.s = s;
bfs(s);
}

private void bsf(Graph G, int s)
{
marked[s] = true;
Queue<Integer> queue = new Queue<>();
queue.enqueue(s);
while(!queue.isEmpty())
{
int v = queue.dequeue();
for(int w : G.adj())
if(!marked[w])
{
queue.enqueue(w);
edgeTo[w] = v;
marked[w] = true;
}
}
}

public boolean hasPathTo(int v)
{ return marked[v]; }

public Iterable<Integer> pathTo(int v)
{
if(!hasPathTo(v)) return null;
Stack<Integer> path = new Stack<>();
for(int x = v; x != s; x = edgeTo[v])
path.push(x);
path.push(s);
return path;
}
}                                                
4. Depth-first search的应用二:相连的vertex。

任意给出一些vertex,如何判断它们是否相连?Depth-first search算法可以以解决这个问题,代码如下:public class CC
{
//ID数组代替edgeTo数组,相连接的vertex的ID值一致。
private int[] ID;
private boolean[] marked;
private int count;

public CC(Graph G)
{
ID = new int[G.V()];
marked = new boolean[G.V()];
for(int s = 0; s < G.V(); s++)
if(!marked[s])
{
dfs(G, s);
count++;
}
}

private void dfs(Graph G, int v)
{
marked[v] = true;
ID[v] = count;
for(int w : G.adj[v])
if(!marked[w])
{
dfs(w);
}
}

//判断两个vertex是否相连,就是看它们的ID是否一致。
public boolean connected(int v, int w)
{ return ID[v] == ID[w]; }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: