赞
踩
所谓图的遍历,即是对结点的访问。一个图有那么多个结点,如何遍历这些结点,需要特定策略,一般有两种访问策略。
1 深度优先遍历
2 广度优先遍历
图的深度优先搜索(Depth First Search) ,简称DFS。
1 深度优先遍历,从初始访问结点出发,初始访问结点可能有多个邻接结点,深度优先遍历的策略就是首先访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接结点。可以这样理解:每次都在访问完当前结点后首先访问当前结点的第一个邻接结点。
2 该访问策略是优先往纵向挖掘深入,而不是对一个结点的所有邻接结点进行横向访问。
3 深度优先搜索是一个递归的过程。
1 访问初始结点v,并标记结点v为已访问。
2 查找结点v的第一个邻接结点w。
3 若w存在,则继续执行4,如果w不存在,则回到第1步,将从v的下一个结点继续。
4 若w未被访问,对w进行深度优先遍历递归(即把w当做另一个v,然后进行步骤1、2、3)。
5 查找结点v的w邻接结点的下一个邻接结点,转到步骤3。
对下图进行深度优先搜索, 从A 开始遍历。
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.LinkedList;
-
- /**
- * @className: Graph
- * @description: 图
- * @date: 2021/3/28
- * @author: cakin
- */
- public class Graph {
- // 存储顶点集合
- private ArrayList<String> vertexList;
- // 存储图对应的邻结矩阵
- private int[][] edges;
- // 表示边的数目
- private int numOfEdges;
- // 表示某个结点是否被访问
- private boolean[] isVisited;
-
- /**
- * 功能描述:图的擦拭
- *
- * @param args 命令行
- * @author cakin
- * @date 2021/3/28
- */
- public static void main(String[] args) {
- // 顶点
- String Vertexs[] = {"A", "B", "C", "D", "E"};
- //String Vertexs[] = {"1", "2", "3", "4", "5", "6", "7", "8"};
- // 结点的个数
- int n = Vertexs.length;
- // 创建图对象
- Graph graph = new Graph(n);
- // 循环的添加顶点
- for (String vertex : Vertexs) {
- graph.insertVertex(vertex);
- }
- // 添加边
- graph.insertEdge(0, 1, 1); // A-B
- graph.insertEdge(0, 2, 1); // A-C
- graph.insertEdge(1, 2, 1); // B-C
- graph.insertEdge(1, 3, 1); // B-D
- graph.insertEdge(1, 4, 1); // B-E
-
- // 显示邻结矩阵
- graph.showGraph();
-
- // dfs测试
- System.out.println("dfs:");
- graph.dfs(); // A->B->C->D->E
- }
-
- // 构造器
- public Graph(int n) {
- // 初始化矩阵
- edges = new int[n][n];
- // 初始化 vertexList
- vertexList = new ArrayList<>(n);
- // 边的数量
- numOfEdges = 0;
- }
-
- /**
- * 功能描述:得到某个顶点的第一个邻接结点的下标 w
- *
- * @param index 顶点索引
- * @return 如果存在就返回对应的下标,否则返回-1
- */
- public int getFirstNeighbor(int index) {
- for (int j = 0; j < vertexList.size(); j++) {
- if (edges[index][j] > 0) {
- return j;
- }
- }
- return -1;
- }
-
- /**
- * 功能描述:根据前一个邻接结点的下标来获取下一个邻接结点
- *
- * @param v1 第1个顶点
- * @param v2 第2个顶点,也就是邻节点
- * @return int 邻节点的下一个邻节点
- * @author cakin
- * @date 2021/3/29
- */
- 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;
- }
-
- /**
- * 功能描述:深度优先遍历算法
- *
- * @author cakin
- * @date 2021/3/29
- * @param isVisited 节点是否被访问数组
- * @param i 被访问节点的下标
- * @return
- * @description:
- */
- private void dfs(boolean[] isVisited, int i) {
- // 输出被访问节点
- System.out.print(getValueByIndex(i) + "->");
- // 将该结点设置为已经访问
- isVisited[i] = true;
- // 查找结点i的第一个邻接结点w
- int w = getFirstNeighbor(i);
- while (w != -1) { // 找到该邻节点
- if (!isVisited[w]) {
- // 递归进行深度优先遍历算法
- dfs(isVisited, w);
- }
- // 如果w结点已经被访问过,找下一个邻节点
- w = getNextNeighbor(i, w);
- }
- }
-
- /**
- * 功能描述:对 dfs 进行一个重载, 遍历所有的结点,并进行 dfs
- *
- * @author cakin
- * @date 2021/3/29
- */
- public void dfs() {
- isVisited = new boolean[vertexList.size()];
- // 遍历所有的结点,进行 dfs
- for (int i = 0; i < getNumOfVertex(); i++) {
- if (!isVisited[i]) {
- dfs(isVisited, i);
- }
- }
- }
-
- /**
- * 功能描述:返回结点的个数
- *
- * @author cakin
- * @date 2021/3/28
- */
- public int getNumOfVertex() {
- return vertexList.size();
- }
-
- /**
- * 功能描述:显示图对应的矩阵
- *
- * @author cakin
- * @date 2021/3/28
- */
- public void showGraph() {
- for (int[] link : edges) {
- System.err.println(Arrays.toString(link));
- }
- }
-
- /**
- * 功能描述:得到边的数目
- *
- * @return 得到边的数目
- * @author cakin
- * @date 2021/3/28
- */
- public int getNumOfEdges() {
- return numOfEdges;
- }
-
- /**
- * 功能描述:返回结点i(下标)对应的数据
- *
- * @param i 节点下标
- * @return 节点对应的数据
- * @author cakin
- * @date 2021/3/28
- * @description: 举例如下:
- * 0->"A" 1->"B" 2->"C"
- */
- public String getValueByIndex(int i) {
- return vertexList.get(i);
- }
-
- /**
- * 功能描述:返回v1和v2的权值
- *
- * @param v1 第1个顶点的下标
- * @param v2 第2个顶点的下标
- * @return int 两个顶点间的权值
- * @author cakin
- * @date 2021/3/28
- */
- public int getWeight(int v1, int v2) {
- return edges[v1][v2];
- }
-
- /**
- * 功能描述:插入结点
- *
- * @param vertex 节点的数据
- * @author cakin
- * @date 2021/3/28
- */
- public void insertVertex(String vertex) {
- vertexList.add(vertex);
- }
-
- /**
- * 功能描述:添加边
- *
- * @param v1 第1个顶点对应的下标
- * @param v2 第2个顶点对应的下标
- * @param weight 表示第1个顶点和第2个顶点的权重
- */
- public void insertEdge(int v1, int v2, int weight) {
- edges[v1][v2] = weight;
- edges[v2][v1] = weight;
- numOfEdges++;
- }
- }
- [0, 1, 1, 0, 0]
- [1, 0, 1, 1, 1]
- [1, 1, 0, 0, 0]
- [0, 1, 0, 0, 0]
- [0, 1, 0, 0, 0]
- dfs:
- A->B->C->D->E->
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。