关于java:数据结构–图深度优先遍历和广度优先遍历Java

8次阅读

共计 4124 个字符,预计需要花费 11 分钟才能阅读完成。

数据结构–图(深度优先遍历和广度优先遍历)(Java)

<!– more –>

博客阐明

文章所波及的材料来自互联网整顿和集体总结,意在于集体学习和教训汇总,如有什么中央侵权,请分割自己删除,谢谢!

图的罕用概念

图是一种数据结构,其中结点能够具备零个或多个相邻元素。两个结点之间的连贯称为边。结点也能够称为顶点。

  • 顶点 (vertex)
  • 边 (edge)
  • 门路
  • 无向图

  • 有向图

  • 带权图

图的示意形式

图的示意形式有两种:二维数组示意(邻接矩阵);链表示意(邻接表)。

邻接矩阵

邻接矩阵是示意图形中顶点之间相邻关系的矩阵,对于 n 个顶点的图而言,矩阵是的 row 和 col 示意的是 1 ….n 个点。

邻接表

邻接矩阵须要为每个顶点都调配 n 个边的空间,其实有很多边都是不存在, 会造成空间的肯定损失

邻接表的实现只关怀存在的边,不关怀不存在的边。因而没有空间节约,邻接表由数组 + 链表组成

代码实现

package com.guizimo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;

public class Graph {

    private ArrayList<String> vertexList; 
    private int[][] edges; 
    private int numOfEdges; 
    private boolean[] isVisited;
    
    public static void main(String[] args) {

        int n = 8;
        String Vertexs[] = {"1", "2", "3", "4", "5", "6", "7", "8"};
        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, 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.showGraph();
        
        System.out.println(" 广度优先遍历
        graph.dfs(); 
        System.out.println(" 深度优先遍历
        graph.bfs();}
    
    public Graph(int n) {edges = new int[n][n];
        vertexList = new ArrayList<String>(n);
        numOfEdges = 0;
    }
    

    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 dfs(boolean[] isVisited, int i) {System.out.print(getValueByIndex(i) + "->");
        isVisited[i] = true;
        int w = getFirstNeighbor(i);
        while(w != -1) {if(!isVisited[w]) {dfs(isVisited, w);
            }
            w = getNextNeighbor(i, w);
        }
        
    }
    
    public void dfs() {isVisited = new boolean[vertexList.size()];
        for(int i = 0; i < getNumOfVertex(); i++) {if(!isVisited[i]) {dfs(isVisited, i);
            }
        }
    }
    
    // 广度优先遍历
    private void bfs(boolean[] isVisited, int i) {
        int u ; 
        int w ; 
        LinkedList queue = new LinkedList();
        System.out.print(getValueByIndex(i) + "=>");
        isVisited[i] = true;
        queue.addLast(i);
        
        while(!queue.isEmpty()) {u = (Integer)queue.removeFirst();
            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 bfs() {isVisited = new boolean[vertexList.size()];
        for(int i = 0; i < getNumOfVertex(); i++) {if(!isVisited[i]) {bfs(isVisited, i);
            }
        }
    }
    
    public int getNumOfVertex() {return vertexList.size();
    }
                       
    // 遍历
    public void showGraph() {for(int[] link : edges) {System.err.println(Arrays.toString(link));
        }
    }
                       
    public int getNumOfEdges() {return numOfEdges;}

    public String getValueByIndex(int i) {return vertexList.get(i);
    }
                       
    public int getWeight(int v1, int v2) {return edges[v1][v2];
    }
                       
    // 增加邻接矩阵
    public void insertVertex(String vertex) {vertexList.add(vertex);
    }
    
  // 插入权值
    public void insertEdge(int v1, int v2, int weight) {edges[v1][v2] = weight;
        edges[v2][v1] = weight;
        numOfEdges++;
    }
}

图的深度优先搜寻 (Depth First Search)

深度优先遍历,从初始拜访结点登程,初始拜访结点可能有多个邻接结点,深度优先遍历的策略就是首先拜访第一个邻接结点,而后再以这个被拜访的邻接结点作为初始结点,拜访它的第一个邻接结点,能够这样了解:每次都在拜访完以后结点后首先拜访以后结点的第一个邻接结点

算法
  • 拜访初始结点 v,并标记结点 v 为已拜访。
  • 查找结点 v 的第一个邻接结点 w。
  • 若 w 存在,则继续执行 4,如果 w 不存在,则回到第 1 步,将从 v 的下一个结点持续。
  • 若 w 未被拜访,对 w 进行深度优先遍历递归(即把 w 当做另一个 v,而后进行步骤 123)。
  • 查找结点 v 的 w 邻接结点的下一个邻接结点,转到步骤 3
代码
// 深度优先遍历
private void dfs(boolean[] isVisited, int i) {System.out.print(getValueByIndex(i) + "->");
  isVisited[i] = true;
  int w = getFirstNeighbor(i);
  while(w != -1) {if(!isVisited[w]) {dfs(isVisited, w);
    }
    w = getNextNeighbor(i, w);
  }

}

public void dfs() {isVisited = new boolean[vertexList.size()];
  for(int i = 0; i < getNumOfVertex(); i++) {if(!isVisited[i]) {dfs(isVisited, i);
    }
  }
}

图的广度优先搜寻 (Broad First Search)

相似于一个分层搜寻的过程,广度优先遍历须要应用一个队列以放弃拜访过的结点的程序,以便按这个程序来拜访这些结点的邻接结点

算法
  • 拜访初始结点 v 并标记结点 v 为已拜访。
  • 结点 v 入队列
  • 当队列非空时,继续执行,否则算法完结。
  • 出队列,获得队头结点 u。
  • 查找结点 u 的第一个邻接结点 w。
  • 若结点 u 的邻接结点 w 不存在,则转到步骤 3;否则循环执行以下三个步骤:

    • 若结点 w 尚未被拜访,则拜访结点 w 并标记为已拜访。
    • 结点 w 入队列
    • 查找结点 u 的继 w 邻接结点后的下一个邻接结点 w,转到步骤 6
代码
// 广度优先遍历
private void bfs(boolean[] isVisited, int i) {
  int u ; 
  int w ; 
  LinkedList queue = new LinkedList();
  System.out.print(getValueByIndex(i) + "=>");
  isVisited[i] = true;
  queue.addLast(i);

  while(!queue.isEmpty()) {u = (Integer)queue.removeFirst();
    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 bfs() {isVisited = new boolean[vertexList.size()];
  for(int i = 0; i < getNumOfVertex(); i++) {if(!isVisited[i]) {bfs(isVisited, i);
    }
  }
}

感激

尚硅谷

以及勤奋的本人,集体博客,GitHub

正文完
 0