美文网首页
算法_图论_深度优先遍历_非递归(Java)

算法_图论_深度优先遍历_非递归(Java)

作者: StayHungriest | 来源:发表于2019-11-02 23:58 被阅读0次

1. 利用栈实现图的深度优先遍历

2. 注意,这里有个坑,操作不当可能就写成了非深度优先遍历

3. 代码中将两种情况都写了出来,看不懂的话请跟着邻接矩阵走一遍就非常易懂了

4. 两种情况输出如下:第一种是深度优先,第二种是操作不当造成的非深度优先

v0
v2
v4
v1
v3
-------无情的分割线-------
v0
v2
v4
v3
v1

5. 直接上代码

import java.util.Stack;
public class RecursionDfs {
    //初始化邻接矩阵
    static int[][] graph = {
          {0,1,1,0,0},
          {1,0,0,1,1},
          {1,0,0,1,1},
          {0,1,1,0,0},
          {0,1,1,0,0},
    };
    
    //是否访问
    static boolean[] isVisited = new boolean[5];
    
    static Stack<Integer> stack = new Stack();
    
    //主方法:我们想要利用栈来完成深度优先遍历,但是存在一种情况可能造成非深度遍历,下面有两种调用顺便解释
    public static void main(String[] args) {
        dfsOfStack();
        isVisited = new boolean[]{false, false, false, false, false};//重置是否访问
        System.out.println("-------无情的分割线-------");
        NotDfsOfStack();
    }
    
    // 栈深度优先遍历(入栈前不判断是否在栈中,重复入栈,但访问前判断是否访问,注:重复入栈保证了深度优先遍历)
    public static void dfsOfStack() {
        stack.add(0); // 遍历起始点0
        int index = 0; // 存储从栈中出栈的下标
        while(stack.size() != 0) { // 如果栈为空则遍历结束
            index = stack.pop(); // 出栈操作
            if(!isVisited[index]) { //!!!注:这里判断了是否已访问过,因为后面重复入栈了
                System.out.println("v" + index);
                isVisited[index] = true;
                for(int i = 0; i<isVisited.length; i++) {//遍历每个顶点
                    if(graph[index][i] == 1 && !isVisited[i]) {//==1表示与此顶点有连线,!isVisited[i]表示此顶点还未访问,则进行递归访问
                            stack.add(i); //!!!注:没有判断是否已在栈中,导致重复入栈
                    }
                }
            }
            
        }
    }
    
    // 栈非深度优先遍历(入栈前判断是否在栈中,不重复入栈)
    public static void NotDfsOfStack() {
        stack.add(0); // 遍历起始点0
        boolean[] marked = new boolean[5]; //是否入栈过
        int index = 0; // 存储从栈中出栈的下标
        marked[0] = true;
        while(stack.size() != 0) { // 如果栈为空则遍历结束
            index = stack.pop(); // 出栈操作
            System.out.println("v" + index);
            for(int i = 0; i<isVisited.length; i++) {//遍历每个顶点
                if(graph[index][i] == 1 && !marked[i]) {//==1表示与此顶点有连线,!isVisited[i]表示此顶点还未访问,则进行递归访问
                        stack.add(i);
                        marked[i] = true; //!!!注:入栈时将其设为访问过,不重复入栈,压在前面的元素可能就只有最后才遍历
                }
            }
        }
    }
}
代码中的无向图.png

6. 那么有没有不重复入栈的深度优先遍历呢?

貌似是没有的,因为如果栈中有前面遍历到的顶点,这次出栈的时候又遍历到了,如果不重复入栈的话,岂不是要等所有顶点遍历完才遍历最先入栈的顶点?这就造成了非深度优先遍历了。
其实,判断是否重复入栈,跟第一种方法,访问节点前先判断是否已经访问过了是差不多的运算效率。所以,不判断是否重复入栈也罢。

相关文章

  • 算法_图论_深度优先遍历_非递归(Java)

    1. 利用栈实现图的深度优先遍历 2. 注意,这里有个坑,操作不当可能就写成了非深度优先遍历 3. 代码中将两种情...

  • 1、邻接矩阵 2、邻接表 3、广度优先遍历 4、深度优先遍历①递归 ②非递归 Dijkstra算法 Floyd-W...

  • 算法_图论_深度优先遍历_递归(Java)

    1. 写在前面 作为一个初步接触的萌新,我认为很有必要将我学习算法的心路历程给记录下来。记录也是笔记,方便以后的复...

  • 5. 深度优先、广度优先

    1. 二叉树的深度优先遍历和广度优先遍历2. 深度优先搜索递归和非递归实现 深度优先(DFS):前序遍历 广度优先...

  • 深度优先遍历和广度优先遍历

    以html节点为列进行深度优先和广度优先遍历 1. 深度优先遍历 递归 非递归,栈表示法 2. 广度优先遍历 队列表示法

  • javascript实现多叉树 深度优先遍历和广度优先遍历(代码

    本文目录 回顾数组本篇使用的五个方法 深度优先遍历 (递归方法) 思路+代码 深度优先遍历 (非递归方法) 思...

  • 深度优先遍历&广度优先遍历

    二叉树的[深度优先遍历的非递归的通用做法是采用栈,广度优先遍历的非递归的通用做法是采用队列 深度优先遍历中,具体分...

  • 前端面试考点之数据结构

    1、深度优先和广度优先的区别 1) 二叉树的深度优先遍历的非递归的通用做法是采用栈,广度优先遍历的非递归的通用做法...

  • js-树的遍历

    数据 广度优先遍历 深度优先遍历 深度优先不递归

  • 深度优先搜索

    深度优先搜索思路 深度优先搜索 = 回溯法可以通过遍历或者分治法的思想实现深度优先搜索而递归和迭代 (非递归)两种...

网友评论

      本文标题:算法_图论_深度优先遍历_非递归(Java)

      本文链接:https://www.haomeiwen.com/subject/jpfkbctx.html