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

本文深入探讨了无向图的深度优先搜索(DFS)和广度优先搜索(BFS)算法,详细解释了它们的工作原理,并通过实例展示了如何在图中遍历节点。了解这些算法对于图论和数据结构的学习至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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]; }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值