博客
关于我
Java数据结构与算法-图(图深度优先、广度优先dfs-bfs,图创建、实现)[day12]
阅读量:675 次
发布时间:2019-03-16

本文共 5796 字,大约阅读时间需要 19 分钟。

图的深度优先搜索(Depth First Search)和广度优先搜索(Breadth First Search)实现

图的基本概念

图是一种用于表示多对多关系的数据结构,由顶点和边组成。顶点(Vertex)可以称为节点,边(Edge)表示顶点之间的连接。图可以分为无向图和有向图。无向图的边没有方向ality,而有向图的边具有明确的方向。边也可以带权重(Weight),这样的图也称为网(Graph with weights)。

顶点之间的连接可以通过边来表示,并形成路径。例如,从节点D到C的路径包括D→B→C和D→A→B→C两种可能。

图的表示方式

图的表示方式主要有两种:邻接矩阵和邻接表。

  • 邻接矩阵(邻接矩阵):这个方法使用一个二维数组来表示图的结构。对于n个顶点的图,矩阵中的每个元素表示对应的两个顶点之间是否存在边。矩阵中的非零值表示边的存在。

  • 邻接表(邻接表):这个方法使用一个数组来表示每个顶点的邻接点。它只关心存在的边,不需要像邻接矩阵那样为所有不存边的情况预留空间,从而实现了空间上的优化。

  • 图的创建与代码实现

    我们创建一个Graph类来处理图的操作。

    import java.util.ArrayList;import java.util.Arrays;import java.util.LinkedList;public class Graph {    private ArrayList
    vertexList; private int[][] edges; private String[] vertexNames; private int numOfEdges; private boolean[] isVisited; LinkedList
    queue; public Graph(int n) { edges = new int[n][n]; vertexList = new ArrayList<>(); numOfEdges = 0; isVisited = new boolean[n]; queue = new LinkedList<>(); } public void insertVertex(String vertex) { vertexList.add(vertex); } public void insertEdge(int v1, int v2, int weight) { if (v1 >= 0 && v1 < edges.length && v2 >= 0 && v2 < edges.length) { edges[v1][v2] = weight; edges[v2][v1] = weight; numOfEdges++; } } public void dfs() { isVisited = new boolean[getMaxNodeId()]; for (int i = 0; i < getMaxNodeId(); i++) { if (!isVisited[i]) { dfsTraversal(isVisited, i); } } } private void dfsTraversal(boolean[] isVisited, int i) { isVisited[i] = true; printVertex(i); int firstNeighbor = getFirstNeighbor(i); while (firstNeighbor != -1) { if (!isVisited[firstNeighbor]) { dfsTraversal(isVisited, firstNeighbor); } firstNeighbor = getNextNeighbor(i, firstNeighbor); } } public void bfs() { isVisited = new boolean[getMaxNodeId()]; for (int i = 0; i < getMaxNodeId(); i++) { if (!isVisited[i]) { bfsTraversal(isVisited, i); } } } private void bfsTraversal(boolean[] isVisited, int i) { isVisited[i] = true; queue.add(i); System.out.print(getValueByIndex(i) + "=>"); while (!queue.isEmpty()) { int u = queue.poll(); int firstNeighbor = getFirstNeighbor(u); while (firstNeighbor != -1) { if (!isVisited[firstNeighbor]) { isVisited[firstNeighbor] = true; System.out.print(getValueByIndex(firstNeighbor) + "=>"); queue.add(firstNeighbor); } firstNeighbor = getNextNeighbor(u, firstNeighbor); } } } private int getMaxNodeId() { return vertexList.size(); } private int getFirstNeighbor(int index) { for (int j = 0; j < vertexList.size(); j++) { if (edges[index][j] != 0) { return j; } } return -1; } private int getNextNeighbor(int v1, int v2) { for (int j = v2 + 1; j < vertexList.size(); j++) { if (edges[v1][j] != 0) { return j; } } return -1; } public void showGraph() { for (int[] link : edges) { System.out.println(Arrays.toString(link)); } } public String getValueByIndex(int i) { return vertexList.get(i); } public static void main(String[] args) { int n = 5; String[] Vertexs = {"A", "B", "C", "D", "E"}; Graph graph = new Graph(n); for (String vertex : Vertexs) { graph.insertVertex(vertex); } graph.insertEdge(0, 1, 1); graph.insertEdge(0, 2, 1); graph.insertEdge(1, 2, 1); graph.insertEdge(1, 3, 1); graph.insertEdge(1, 4, 1); graph.showGraph(); System.out.println("深度遍历"); graph.dfs(); System.out.println(); System.out.println("广度遍历"); graph.bfs(); }}

    深度优先搜索(Depth First Search)实现

    深度优先搜索是一个递归算法,它从图的起始顶点开始,尽可能深入访问它的邻接顶点,尽量避免回溯。一旦到达不能再继续深入的顶点时,才会回溯,从而访问另一个邻接顶点。这个过程直到所有顶点都被访问完毕。

    深度优先遍历的步骤:

  • 访问当前顶点,标记为已访问。
  • 查找当前顶点的第一个未访问的邻接顶点。
  • 如果找到,则继续深度优先访问该邻接顶点。
  • 如果没有找到,回到步骤2,继续查找下一个未访问的邻接顶点。
  • 当所有邻接顶点都被访问过后,结束当前深度优先过程,返回到上一个调用。
  • 深度优先遍历示例代码注释:

    private void dfsTraversal(boolean[] isVisited, int i) {    isVisited[i] = true;    printVertex(i); // 打印当前顶点    int firstNeighbor = getFirstNeighbor(i); // 获取当前顶点的第一个邻接顶点    while (firstNeighbor != -1) { // 确保有邻接顶点存在        if (!isVisited[firstNeighbor]) {            dfsTraversal(isVisited, firstNeighbor); // 递归深度优先访问邻接顶点        }        firstNeighbor = getNextNeighbor(i, firstNeighbor); // 获取当前顶点的下一个邻接顶点    }}

    广度优先搜索(Breadth First Search)实现

    广度优先搜索使用一个队列来维护访问顺序,它首先访问图的起始顶点,然后依次访问其邻接顶点,将每个新访问的顶点入队。队列的先进先出(FIFO)特性确保了每层顶点都被访问完毕。

    广度优先遍历的步骤:

  • 访问当前顶点,标记为已访问。
  • 将当前顶点入队。
  • 按照队列顺序,连续输出队列中的顶点进行处理。
  • 取出队列中的顶点,查找其未访问的邻接顶点,将这些顶点依次入队。
  • 重复步骤4,直到队列为空为止。
  • 广度优先遍历示例代码注释:

    private void bfsTraversal(boolean[] isVisited, int i) {    isVisited[i] = true;    System.out.print(getValueByIndex(i) + "=>");    queue.add(i);    while (!queue.isEmpty()) {        int u = queue.poll(); // 取出队列的顶点        int firstNeighbor = getFirstNeighbor(u); // 获取顶点u的第一个邻接顶点        while (firstNeighbor != -1) {            if (!isVisited[firstNeighbor]) {                isVisited[firstNeighbor] = true;                System.out.print(getValueByIndex(firstNeighbor) + "=>");                queue.add(firstNeighbor); // 将邻接顶点入队            }            firstNeighbor = getNextNeighbor(u, firstNeighbor); // 获取顶点u的下一个邻接顶点        }    }}

    比较与优化

    深度优先搜索和广度优先搜索各有优缺点。深度优先搜索在处理路径问题、中图形遍历和具有特定结构的图中表现优异,常用于实现查找最短路径或判定图的连通性。而广度优先搜索在处理图的遍历、网络传播和路径查找中表现更好,特别是在查找最短路径时更为高效。

    通过合理选择算法和优化访问顺序,可以充分发挥图遍历技术的优势,实现更高效率的图形处理任务。

    转载地址:http://trvqz.baihongyu.com/

    你可能感兴趣的文章
    Netty源码—5.Pipeline和Handler一
    查看>>
    Netty源码—6.ByteBuf原理二
    查看>>
    Netty源码—7.ByteBuf原理四
    查看>>
    Netty的Socket编程详解-搭建服务端与客户端并进行数据传输
    查看>>
    Network Dissection:Quantifying Interpretability of Deep Visual Representations(深层视觉表征的量化解释)
    查看>>
    Network Sniffer and Connection Analyzer
    查看>>
    Nginx Location配置总结
    查看>>
    Nginx 反向代理解决跨域问题
    查看>>
    nginx 后端获取真实ip
    查看>>
    Nginx 学习总结(17)—— 8 个免费开源 Nginx 管理系统,轻松管理 Nginx 站点配置
    查看>>
    Nginx 我们必须知道的那些事
    查看>>
    oauth2-shiro 添加 redis 实现版本
    查看>>
    OAuth2.0_授权服务配置_Spring Security OAuth2.0认证授权---springcloud工作笔记140
    查看>>
    Objective-C实现A-Star算法(附完整源码)
    查看>>
    Objective-C实现atoi函数功能(附完整源码)
    查看>>
    Objective-C实现base64加密和base64解密算法(附完整源码)
    查看>>
    Objective-C实现base85 编码算法(附完整源码)
    查看>>
    Objective-C实现basic graphs基本图算法(附完整源码)
    查看>>
    Objective-C实现BCC校验计算(附完整源码)
    查看>>
    Objective-C实现bead sort珠排序算法(附完整源码)
    查看>>