JAVA实现图的深度优先遍历.

一:深度优先遍历介绍.

       1. 深度优先遍历的定义:

          假设图中的所有的顶点都没有访问过,我们是任选一个顶点作为起始出发点(一般选择使用节点集的第一个元素作为起始顶点).

          深度核心思想就是从起始顶点出发,然后一致沿着可以到达的节点走,一条路一直走,直到不可达是,返回到上一个节点,接着走,直到这条路也走不通了,再次返回上一个节点,就这样,一致递归,直到图中的所有的节点都访问结束.

      2. 深度优先遍历的特点:

          遍历图的时候尽可能深的遍历,一条路走到结束.尽可能去最远的地方深度优先遍历结束后会得到一个深度优先队列,如果没有指定起始顶点,那么DFS序列就不唯一,不同的起始顶点得到的DFS序列就不唯一.

        消耗内存小,可以找到是否有解,难以寻找最优解.

      3. 深度优先遍历的实现方式:

          3.1 递归实现.

          3.2 非递归实现.(使用栈).

     4.  深度优先遍历的可以解决的问题模型:

          给定初始状态和目标状态,从初始状态判断到目标状态是否有解.

         用于二叉树的前中后序遍历.递归版/非递归版,在自己秋季校招面试时也手写过.

         二叉树的先序遍历(根-左-右).

   public List<TreeNode> preIterator(){
              return preIterator(root);
   }
   private List<TreeNode> preIterator(TreeNode node){
             List<TreeNode> list=new ArrayList<TreeNode>();
	     // 处理根节点
	     list.add(node);
	     // 递归处理左子树
	     if(node.left!=null){
                   list.addAll(preIterator(node.left));
	     }
	     // 递归处理右子树
	     if(node.right!=null){
                  list.addAll(preIterator(node.right));
	     }
            return list;
   }

二. 深度优先遍历的图.(15)

        《JAVA实现图的深度优先遍历.》

             如果从节点A开始进行深度优先遍历:DFS序列为:A B C D E F G H I 

三. 代码实现.(这里实现的是从第一个节点开始的DFS序列).递归实现.间接明了.

    1. 定义一位数组存储点集.

    2. 定义变量指定节点数.

    3.  定义Boolean型数组指定是否访问的标志.

    4. 定义二维数组保存边的信息(邻接矩阵实现).考虑时间复杂度.

    5. 初始化DFS.

    6. 实现深度优先遍历的核心代码.

public class DFS {
    /** 存储节点信息*/
    private char[] vertices;

    /** 存储边信息(邻接矩阵)*/
    private  int[][] arcs;

    /** 图的节点数*/
    private int vexnum;

    /** 记录节点是否已被遍历*/
    private boolean[] visited;

    /** 初始化*/
    public DFS(int n) {
        vexnum = n;
        vertices = new char[n];
        arcs = new int[n][n];
        visited = new boolean[n];
        for (int i = 0; i < vexnum; i++) {
            for (int j = 0; j < vexnum; j++) {
                arcs[i][j] = 0;
            }
        }
    }

    /** 添加边*/
    public void addEdge(int i, int j){
        if(i==j){
            return ;
        }
        // 无向图对称的.
        arcs[i][j]=1;
        arcs[j][i]=1;
    }

    /** 设置节点集*/
    public void setVertices(char[] vertices){
        this.vertices=vertices;
    }

    /** 设置节点访问标记*/
    public void setVisited(boolean[] visited){
        this.visited=visited;
    }

    /** 打印遍历节点*/
    public void visit(int i){
        System.out.print(vertices[i]+ " ");
    }

    /**
     *  输出邻接矩阵
     */
    public void pritf(int[][] arcs){
        for(int i=0;i<arcs.length;i++){
            for(int j=0;j<arcs[0].length;j++){
                System.out.print(arcs[i][j]+ "\t");
            }
            System.out.println();
        }
    }
    /** 从第i节点开始深度优先遍历*/
    public void traverse(int i){
        // 标记第i个节点已遍历
        visited[i]=true;
        // 打印当前已经遍历的节点
        visit(i);
        // 遍历邻接矩阵中第i个节点的直接连通节点
        for(int j=0;j<vexnum;j++){
            if(arcs[i][j]==1&&visited[j]==false){
                traverse(j);
            }
        }
    }

    public void dfs(){
        // 初始化节点访问标记
        for(int i=0;i<visited.length;i++){
            visited[i]=false;
        }
        // 从没有被遍历的节点开始深度优先遍历
        for(int i=0;i<vexnum;i++){
            // 如果没有被访问过.
            if(visited[i]==false){
                traverse(i);
            }
        }
        // 输出二维矩阵
        System.out.println();
        pritf(arcs);
    }
    public static void main(String[] args) {
        DFS dfs = new DFS(9);
        // 添加节点集
        char[] vertices = {'A','B','C','D','E','F','G','H','I'};
        // 设置顶点集
        dfs.setVertices(vertices);
        // 添加边
        dfs.addEdge(0, 1);
        dfs.addEdge(0, 5);
        dfs.addEdge(1, 0);
        dfs.addEdge(1, 2);
        dfs.addEdge(1, 6);
        dfs.addEdge(1, 8);
        dfs.addEdge(2, 1);
        dfs.addEdge(2, 3);
        dfs.addEdge(2, 8);
        dfs.addEdge(3, 2);
        dfs.addEdge(3, 4);
        dfs.addEdge(3, 6);
        dfs.addEdge(3, 7);
        dfs.addEdge(3, 8);
        dfs.addEdge(4, 3);
        dfs.addEdge(4, 5);
        dfs.addEdge(4, 7);
        dfs.addEdge(5, 0);
        dfs.addEdge(5, 4);
        dfs.addEdge(5, 6);
        dfs.addEdge(6, 1);
        dfs.addEdge(6, 3);
        dfs.addEdge(6, 5);
        dfs.addEdge(6, 7);
        dfs.addEdge(7, 3);
        dfs.addEdge(7, 4);
        dfs.addEdge(7, 6);
        dfs.addEdge(8, 1);
        dfs.addEdge(8, 2);
        dfs.addEdge(8, 3);
        System.out.print("深度优先遍历(递归实现):");
        dfs.dfs();
    }
}

  运行结果如下:

《JAVA实现图的深度优先遍历.》

非递归实现.基于栈实现.

import java.util.Stack;
/**
 * title: com.lx.algorithm.graph
 * @author: lixing
 * date: 2018/10/31 21:03
 * description:
 */
public class DFSStack {
    /** 存储节点信息*/
    private char[] vertices;

    /** 存储边信息(邻接矩阵)*/
    private  int[][] arcs;

    /** 图的节点数*/
    private int vexnum;

    /** 记录节点是否已被遍历*/
    private boolean[] visited;

    /** 初始化*/
    public DFSStack(int n) {
        vexnum = n;
        vertices = new char[n];
        arcs = new int[n][n];
        visited = new boolean[n];
        for (int i = 0; i < vexnum; i++) {
            for (int j = 0; j < vexnum; j++) {
                arcs[i][j] = 0;
            }
        }
    }

    /** 添加边*/
    public void addEdge(int i, int j){
        if(i==j){
            return ;
        }
        // 无向图对称的.
        arcs[i][j]=1;
        arcs[j][i]=1;
    }

    /** 设置节点集*/
    public void setVertices(char[] vertices){
        this.vertices=vertices;
    }

    /** 设置节点访问标记*/
    public void setVisited(boolean[] visited){
        this.visited=visited;
    }

    /** 打印遍历节点*/
    public void visit(int i){
        System.out.print(vertices[i]+ " ");
    }

    /**
     *  输出邻接矩阵
     */
    public void pritf(int[][] arcs){
        for(int i=0;i<arcs.length;i++){
            for(int j=0;j<arcs[0].length;j++){
                System.out.print(arcs[i][j]+ "\t");
            }
            System.out.println();
        }
    }

   public  void dfs(){
       // 初始化所有的节点的访问标志
       for (int v = 0; v < visited.length; v++) {
           visited[v] = false;
       }
        Stack<Integer> stack =new Stack<Integer>();
        for(int i=0;i<vexnum;i++){
            if(visited[i]==false){
                visited[i]=true;
                System.out.print(vertices[i]+" ");
                stack.push(i);
            }
            while(!stack.isEmpty()){
                // 当前出栈的节点
                int k = stack.pop();
                for(int j=0;j<vexnum;j++){
                    // 如果是相邻的节点且没有访问过.
                    if(arcs[k][j]==1&&visited[j]==false){
                        visited[j]=true;
                        System.out.print(vertices[j]+" ");
                        stack.push(j);
                        // 这条路结束,返回上一个节点.
                        break;
                    }
                }

            }
        }
       // 输出二维矩阵
       System.out.println();
       pritf(arcs);
    }

    public static void main(String[] args) {
        DFSTest dfs = new DFSTest(9);
        // 添加节点集
        char[] vertices = {'A','B','C','D','E','F','G','H','I'};
        // 设置顶点集
        dfs.setVertices(vertices);
        // 添加边
        dfs.addEdge(0, 1);
        dfs.addEdge(0, 5);
        dfs.addEdge(1, 0);
        dfs.addEdge(1, 2);
        dfs.addEdge(1, 6);
        dfs.addEdge(1, 8);
        dfs.addEdge(2, 1);
        dfs.addEdge(2, 3);
        dfs.addEdge(2, 8);
        dfs.addEdge(3, 2);
        dfs.addEdge(3, 4);
        dfs.addEdge(3, 6);
        dfs.addEdge(3, 7);
        dfs.addEdge(3, 8);
        dfs.addEdge(4, 3);
        dfs.addEdge(4, 5);
        dfs.addEdge(4, 7);
        dfs.addEdge(5, 0);
        dfs.addEdge(5, 4);
        dfs.addEdge(5, 6);
        dfs.addEdge(6, 1);
        dfs.addEdge(6, 3);
        dfs.addEdge(6, 5);
        dfs.addEdge(6, 7);
        dfs.addEdge(7, 3);
        dfs.addEdge(7, 4);
        dfs.addEdge(7, 6);
        dfs.addEdge(8, 1);
        dfs.addEdge(8, 2);
        dfs.addEdge(8, 3);
        System.out.print("深度优先遍历(非递归实现):");
        dfs.dfs();
    }
}

  运行结果:

《JAVA实现图的深度优先遍历.》

至此完成基于JAVA的深度优先遍历实现.

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/HcJsJqJSSM/article/details/83589781
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞