剑指Offer–图的操作

前言

  企业笔试过程中会涉及到数据结构的方方面面,现将有关图的深度优先搜索与广度优先搜索进行整理归纳,方便日后查阅。

  在已做过的笔试题目中,可用DFS解决的题目有:

  1. 地牢逃脱”–网易
  2. 遍历最短路径长度”–携程
  3. 小青蛙走迷宫”–滴滴

  三道题目都是DFS的经典应用,主要采用递归+回溯的方式。

  下面主要讲解一下DFS与BFS的具体实现。

深度优先搜索(DFS) && 广度优先搜索(BFS)

package cn.edu.ujn.graph;
import java.util.ArrayList;
import java.util.LinkedList;
/**
 * @description 邻接矩阵模型类
 * @author SHQ
 * @time 2016.09.12
 */
public class DFS_BFS {
    private ArrayList<Object> vertexList;// 存储点的链表
    private int[][] edges;       // 邻接矩阵,用来存储边
    private int numOfEdges;      // 边的数目
    boolean[] isVisited;         // 遍历标志位

    public DFS_BFS(int n) {
        //初始化矩阵,二维数组,和边的数目
        edges = new int[n][n];
        vertexList = new ArrayList<Object>(n);
        numOfEdges = 0;
        // 将所有节点访问标志位均置为未访问
        isVisited = new boolean[n];
        for(int i = 0; i < n; i++){
            isVisited[i] = false;
        }
    }

    // 得到结点的个数
    public int getNumOfVertex() {
        return vertexList.size();
    }

    // 得到边的数目
    public int getNumOfEdges() {
        return numOfEdges;
    }

    // 返回结点i的数据
    public Object getValueByIndex(int i) {
        return vertexList.get(i);
    }

    // 返回v1,v2的权值
    public int getWeight(int v1,int v2) {
        return edges[v1][v2];
    }

    //插入结点
    public void insertVertex(Object vertex) {
        vertexList.add(vertexList.size(),vertex);
    }

    //插入结点
    public void insertEdge(int v1,int v2,int weight) {
        edges[v1][v2]=weight;
        numOfEdges++;
    }

    //删除结点
    public void deleteEdge(int v1,int v2) {
        edges[v1][v2] = 0;
        numOfEdges--;
    }

    // 得到第一个邻接结点的下标
    public int getFirstNeighbor(int index) {
        for(int j = 0; j < vertexList.size(); j++) {
            if (edges[index][j] > 0) {
                return j;
            }
        }
        return -1;
    }

    // 根据前一个邻接结点的下标来取得下一个邻接结点
    public int getNextNeighbor(int v1, int v2) {
        for (int j = v2+1; j < vertexList.size(); j++) {
            if (edges[v1][j]>0) {
                return j;
            }
        }
        return -1;
}
    // 私有函数,深度优先遍历
    private void depthFirstSearch(boolean[] isVisited,int  i) {
        // 首先访问该结点,在控制台打印出来
        System.out.print(getValueByIndex(i) + "  ");
        // 置该结点为已访问
        isVisited[i] = true;

        int w = getFirstNeighbor(i);
        while (w != -1) {
            if (!isVisited[w]) {
                depthFirstSearch(isVisited,w);
            }
            w = getNextNeighbor(i, w);
        }
    }

    // 对外公开函数,深度优先遍历,与其同名私有函数属于方法重载
    public void depthFirstSearch() {
        for(int i = 0; i < getNumOfVertex(); i++) {
            //因为对于非连通图来说,并不是通过一个结点就一定可以遍历所有结点的。
            if (!isVisited[i]) {
                depthFirstSearch(isVisited,i);
            }
        }
}
    /**
     * 私有函数,广度优先遍历
     * 遍历步骤:
     *  1.访问初始结点v并标记结点v为已访问。
     *  2.结点v入队列
     *  3.当队列非空时,继续执行,否则算法结束。
     *  4.出队列,取得队头结点u。
     *  5.查找结点u的第一个邻接结点w。
     *  6.若结点u的邻接结点w不存在,则转到步骤3;否则循环执行以下三个步骤:
     *      1)若结点w尚未被访问,则访问结点w并标记为已访问。
     *      2)结点w入队列
     *      3)查找结点u的继w邻接结点后的下一个邻接结点w,转到步骤6。
     * @param isVisited
     * @param i
     */
    private void broadFirstSearch(boolean[] isVisited, int i) {
        int u, w;
        // 借助辅助队列,记录访问顺序
        LinkedList<Object> queue = new LinkedList<Object>();
        // 访问结点i
        System.out.print(getValueByIndex(i) + "  ");
        isVisited[i] = true;
        // 结点入队列
        queue.addLast(i);
        while (!queue.isEmpty()) {
            u = ((Integer)queue.removeFirst()).intValue();
            w = getFirstNeighbor(u);
            while(w != -1) {
                if(!isVisited[w]) {
                        //访问该结点
                        System.out.print(getValueByIndex(w)+"  ");
                        //标记已被访问
                        isVisited[w] = true;
                        //入队列
                        queue.addLast(w);
                }
                //寻找下一个邻接结点
                w = getNextNeighbor(u, w);
            }
        }
    }

    //对外公开函数,广度优先遍历
    public void broadFirstSearch() {
        for(int i = 0; i < getNumOfVertex(); i++) {
            if(!isVisited[i]) {
                broadFirstSearch(isVisited, i);
            }
        }
    }
}

Main.java

package cn.edu.ujn.graph;

public class Main {
    public static void main(String args[]) {
        int n = 8, e = 9;   // 分别代表结点个数和边的数目
        String labels[]={"1","2","3","4","5","6","7","8"};  // 结点的标识
        DFS_BFS graph = new DFS_BFS(n);
        for(String label : labels) {
            graph.insertVertex(label);  // 插入结点
        }
        //插入九条边
        graph.insertEdge(0, 1, 1);
        graph.insertEdge(0, 2, 1);
        graph.insertEdge(1, 3, 1);
        graph.insertEdge(1, 4, 1);
        graph.insertEdge(3, 7, 1);
        graph.insertEdge(4, 7, 1);
        graph.insertEdge(2, 5, 1);
        graph.insertEdge(2, 6, 1);
        graph.insertEdge(5, 6, 1);
        graph.insertEdge(1, 0, 1);
        graph.insertEdge(2, 0, 1);
        graph.insertEdge(3, 1, 1);
        graph.insertEdge(4, 1, 1);
        graph.insertEdge(7, 3, 1);
        graph.insertEdge(7, 4, 1);
        graph.insertEdge(6, 2, 1);
        graph.insertEdge(5, 2, 1);
        graph.insertEdge(6, 5, 1);

/*        System.out.println("深度优先搜索序列为:");
        graph.depthFirstSearch();
        System.out.println();*/
        System.out.println("广度优先搜索序列为:");
        graph.broadFirstSearch();
    }
}


剑指Offer--图的操作的更多相关文章

  1. 剑指Offer——Java实现栈和队列的互模拟操作

    剑指Offer--Java实现栈和队列的互模拟操作 栈模拟队列   题目:JAVA实现用两个栈来实现一个队列,完成队列的Push和Pop操作.队列中的元素为int类型.   思路:其实就是把队列正常入 ...

  2. [剑指offer]09用两个栈实现队列插入和删除操作,C++实现

    原创博文,转载请注明出处! # 本文为牛客网<剑指offer>刷题笔记 1.题目 # 用两个栈实现队列的插入和删除操作 2.思路 栈服从先入后出的原则处理数据,队列服从先入先出的原则处理数 ...

  3. 面试经典算法题集锦——《剑指 offer》小结

    从今年 3 月份开始准备找实习,到现在校招结束,申请的工作均为机器学习/数据挖掘算法相关职位,也拿到了几个 sp offer.经历这半年的洗礼,自己的综合能力和素质都得到了一个质的提升. 实话说对于未 ...

  4. 剑指Offer——知识点储备--Linux基本命令+Makefile

    剑指Offer--知识点储备–Linux基本命令 1.linux下查看进程占用cpu的情况(top): 格式 top [-] [d delay] [q] [c] [S] [s] [i] [n] 主要参 ...

  5. 剑指Offer——知识点储备-故障检测、性能调优与Java类加载机制

    剑指Offer--知识点储备-故障检测.性能调优与Java类加载机制 故障检测.性能调优 用什么工具可以查出内存泄露 (1)MerroyAnalyzer:一个功能丰富的java堆转储文件分析工具,可以 ...

  6. 剑指Offer——知识点储备-J2EE基础

    剑指Offer--知识点储备-J2EE基础 9.2 jdk 1.8的新特性(核心是Lambda 表达式) 参考链接:http://www.bubuko.com/infodetail-690646.ht ...

  7. 剑指Offer——迅雷笔试题+知识点总结

    剑指Offer--迅雷笔试题+知识点总结 情景回顾 时间:2016.9.19 19:00-21:00 地点:山东省网络环境智能计算技术重点实验室 事件:迅雷笔试 总体来说,迅雷笔试内容体量不算多,主要 ...

  8. 剑指Offer——携程笔试题+知识点总结

    剑指Offer--携程笔试题+知识点总结 情景回顾 时间:2016.9.17 19:10-21:10 地点:山东省网络环境智能计算技术重点实验室 事件:携程笔试 总体来说,携程笔试内容与其它企业笔试题 ...

  9. 剑指Offer——归并排序思想应用

    剑指Offer--归并排序思想应用 前言 在学习排序算法时,初识归并排序,从其代码量上感觉这个排序怎么这么难啊.其实归并排序的思想很简单:将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列 ...

  10. 剑指Offer——巧妙使用sort(List<T>,Comparator<? super T>)比较器

    剑指Offer--巧妙使用sort(List<T>,Comparator<? super T>)比较器 先入为主 package cn.edu.ujn.offersword; ...

随机推荐

  1. ●BZOJ 2588 Spoj 10628. Count on a tree

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2588 题解: 主席树,在线,(求LCA)感觉主席树真的好厉害...在原树上建主席树.即对于原 ...

  2. hdu5652 India and China Origins(并查集)

    India and China Origins  Accepts: 49  Submissions: 426  Time Limit: 2000/2000 MS (Java/Others)  Memo ...

  3. Cookie 和 Session的基本使用

    cookie: 放在客户端上的键值对. 1.设置cookie obj = render(request,'index.html') obj.set_cookie('key','value') retu ...

  4. .net4.0设计模式(一)使用Lazy的单例模式

    延迟加载,亦称延迟实例化,延迟初始化等, 主要表达的思想是,把对象的创建将会延迟到使用时创建,而不是在对象实例化时创建对象,即用时才加载.这种方式有助于提高于应用程序的性能,避免浪费计算,节省内存的使 ...

  5. [ Java学习基础 ] Java的继承与多态

    看到自己写的东西(4.22的随笔[ Java学习基础 ] Java构造函数)第一次达到阅读100+的成就还是挺欣慰的,感谢大家的支持!希望以后能继续和大家共同学习,共同努力,一起进步!共勉! ---- ...

  6. python3全栈开发-并发编程,多进程的基本操作

    一 .multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程. ...

  7. unittest测试框架详谈及实操(二)

    类级别的setUp()方法与tearDown()方法 在实操(一)的例子中,通过setUp()方法为每个测试方法都创建了一个Chrome实例,并且在每个测试方法执行结束后要关闭实例.是不是觉得有个多余 ...

  8. flask的自带logger和celery的自带logger的使用

    在celery和flask框架中都有自带的logger使用方法.下面记录一下相关的使用. flask中使用logger flask中的app对象FLASK()自带了logger方法,其调用的方式为: ...

  9. c# 判断datatable中是否存在某列

    if (datatable.columns.contains("要找的列名"))

  10. jquery 实现图片无缝向左滚动

    <script type="text/javascript" src="_pub/Script/jquery.js"></script> ...