图的BFS和DFS

栏目: 数据库 · 发布时间: 5年前

内容简介:图的遍历对于图这类题目来说非常重要,但是图的实现又非常的难。在这里我介绍下图的广度优先遍历和深度优先遍历,讲一下其中的算法思想。邻接矩阵表示:图的邻接矩阵存储结构定义如下:

图的遍历对于图这类题目来说非常重要,但是图的实现又非常的难。在这里我介绍下图的广度优先遍历和深度优先遍历,讲一下其中的算法思想。

1.图的存储结构

邻接矩阵表示:

图的BFS和DFS

图的邻接矩阵存储结构定义如下:

int n;
    boolean[][] a;
    Node(int n){
        this.n=n;
        a = new boolean[n][n];
    }
    void addEdge(int i, int j) {
        a[i][j] = true;
    }
    void removeEdge(int i, int j) {
        a[i][j] = false;
    }
    boolean hasEdge(int i, int j) {
        return a[i][j];
    }
复制代码

邻接矩阵表示法的时间复杂度为O(n^2),空间复杂度也是O(n^2)。n代表图中顶点的个数。

邻接表表示:

图的BFS和DFS

图的邻接表存储结构定义如下:

//顶点的数量
    private int V;
    //邻接表-数组类型的链表
    private LinkedList<Integer> adj[];

    //构造一个图
    DepthFirstSearch(int  v){
        V = v;
        //数组链表
        adj = new LinkedList[v];
        for (int i = 0; i < v; i++) {
            adj[i]=new LinkedList();
        }
    }

    //加入与顶点v相连的边v-w
    void addEdge(int v,int w){
        adj[v].add(w);
    }
复制代码

时间复杂度为:O(V + E)其中V是图中顶点的数量,E是图中边的数量 。

还是看以前的书比较有亲和感!

2.广度优先遍历(Breadth-First-Search,BFS)

广度优先遍历类似与二叉树的层序遍历。它是一种分层的查找过程,每向前走一步能访问一批顶点,不像深度优先遍历那样有往回退的情况,因此它不是一个递归的算法。 为了实现逐层的访问,算法必须借助一个辅助队列,以记忆正在访问顶点的下一层顶点。

package com.zhoujian.solutions.dataStructure.graph;
import java.util.*;
/**
 * @author zhoujian123@hotmail.com 2018/4/26 10:28
 * 图的广度优先遍历----借助队列
 * 广度优先遍历类似于二叉树的层序遍历
 * 图是用邻接表来存储(对于稀疏图来说,邻接表比较合适)
 * 时间复杂度:O(V+E),其中V是图中顶点的数量,E是图中边的数量
 */
public class BreadthFirstSerch {
    private int V; //顶点
    private LinkedList<Integer> adj[]; //领接表
    //构造器,利用链表。v是顶点的个数
    BreadthFirstSerch(int v){
        V=v;
        adj = new LinkedList[v];
        for (int i = 0; i <v; i++) {
            adj[i]=new LinkedList();
        }
    }
    //加入一条边到图中
    void addEdge(int v,int w){
        adj[v].add(w);
    }
    //从给定的顶点开始遍历
    void BFS(int s){
        //默认将所有的顶点设置为未被访问(false)
        boolean visited[] = new boolean[V];
        //创建一个队列
        LinkedList<Integer> queue = new LinkedList<Integer>();
        //把当前顶点设置为已访问并且入队
        visited[s] = true;
        queue.add(s);
        while (queue.size()!=0){
            //出队并打印出来
            s=queue.poll();
            System.out.println(s+"");
            //获取与s相关联的全部的顶点,如果邻接的点未被访问,则设置为已被访问且入队
            //i是一种list列表的迭代器,用于存储相邻节点的列表
            ListIterator<Integer> i = adj[s].listIterator();
            while (i.hasNext()){
                int n = i.next();
                if (!visited[n]){
                    visited[n]=true;
                    queue.add(n);
                }
            }
        }
    }

    public static void main(String[] args) {
        BreadthFirstSerch g = new BreadthFirstSerch(4);
        g.addEdge(0,1);
        g.addEdge(0,2);
        g.addEdge(1,2);
        g.addEdge(2,0);
        g.addEdge(2,3);
        g.addEdge(3,3);
        //这个函数只能从指定顶点开始遍历。要是打印所有顶点,可以需要修改BFS函数,逐个从所有节点开始遍历
        System.out.println("广度优先遍历从0开始遍历");
        g.BFS(0);
        System.out.println("广度优先遍历从1开始遍历");
        g.BFS(1);
        System.out.println("广度优先遍历从2开始遍历");
        g.BFS(2);
        System.out.println("广度优先遍历从3开始遍历");
        g.BFS(3);
    }

}

复制代码
图的BFS和DFS

3.深度优先遍历(Depath-First-Search,DFS)

深度优先遍历类似于树的先序遍历。DFS算法是一个递归的算法,需要借助一个递归的工作栈,故它的空间复杂度为O(V)。总的时间复杂度为O(V+E)。

package com.zhoujian.solutions.dataStructure.graph;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
/**
 * @author zhoujian123@hotmail.com 2018/4/25 21:19
 * 图的深度优先遍历:需要借助栈
 * 深度优先遍历类似于二叉树的先序遍历
 * 使用邻接表表示
 * 时间复杂度:当以领接表表示时,查找所有顶点的邻接点所需为O(V),然后每条边至少访问一次所需时间为O(E),
 * 总的时间复杂度为O(V+E)
 *
 */
public class DepthFirstSearch {

    //顶点的数量
    private int V;
    //邻接表-数组类型的链表
    private LinkedList<Integer> adj[];

    //构造一个图
    DepthFirstSearch(int  v){
        V = v;
        //数组链表
        adj = new LinkedList[v];
        for (int i = 0; i < v; i++) {
            adj[i]=new LinkedList();
        }
    }

    //加入与顶点v相连的边v-w
    void addEdge(int v,int w){
        adj[v].add(w);
    }
    /**
     * 从顶点v开始深度遍历
     * @param v 顶点v
     * @param visited 访问标识符
     */
    void DFSUtil(int v,boolean visited[]){

        //把当前节点设置为被访问并打印出来
        visited[v]=true;
        System.out.println(v+" ");

        ListIterator<Integer> i = adj[v].listIterator();
        while (i.hasNext()){
            //返回与v相邻的节点
            Integer n = i.next();
            if (!visited[n]){
                DFSUtil(n,visited);
            }
        }

    }

    void DFS(int v){
        //初始化所有顶点并默认为false(数组)
        boolean[] visited = new boolean[V];
        DFSUtil(v,visited);
    }

    public static void main(String[] args) {
        DepthFirstSearch g = new DepthFirstSearch(4);
        g.addEdge(0,1);
        g.addEdge(0,2);
        g.addEdge(1,2);
        g.addEdge(2,0);
        g.addEdge(2,3);
        g.addEdge(3,3);
        System.out.println("深度优先遍历从顶点2开始");
        g.DFS(2);
    }
}
复制代码
图的BFS和DFS

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

jQuery实战(第2版)

jQuery实战(第2版)

[美]Bear Bibeault、[美]Yehuda Katz / 三生石上 / 人民邮电出版社 / 2012-3 / 69.00元

jQuery 是目前最受欢迎的JavaScript/Ajax 库之一,能用最少的代码实现最多的功能。本书全面介绍jQuery 知识,展示如何遍历HTML 文档、处理事件、执行动画、给网页添加Ajax 以及jQuery UI 。书中紧紧地围绕“用实际的示例来解释每一个新概念”这一宗旨,生动描述了jQuery 如何与其他工具和框架交互以及如何生成jQuery 插件。 本书适合各层次Web 开发人......一起来看看 《jQuery实战(第2版)》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具