图的深度优先遍历DFS、广度优先遍历BFS细解说(邻接矩阵+链表两种存储方式,递归+非递归)

一、图的深度优先遍历(邻接矩阵)

  1. 定义一个变量 vn 记录顶点数。
  2. 定义一个顶点一维数组 vertices 用于记录顶点名。
  3. 定义一个二维数组 graph ,也就是邻接矩阵。
  4. 定义一个一维数组 visited 记录顶点的访问情况。
  5. 定义一个二维i数组 edges 记录顶点之间的关系,也就是图中存在的边。(也可以直接从实际情况总结出图中的边的连接情况)

1、递归法

// 需要在调用的地方遍历每个点,确保每个点都访问到了。如果是连通的图,那循环一次就可以遍历完
for (int i = 0; i < vn; i++){
    dfsGraphTravel.dfsTravel(i);
}
class DFSGraphTravel{
    int vn; // 定点数
    private int[][] edges; // 边集合
    private boolean[] visited; // 访问集合
    private int[][] graph; // 邻接矩阵
    private String[] vertices; //顶点名集合

    // 初始化图
    public DFSGraphTravel(int vn, int[][] edges, String[] vertices){
        this.vn = vn;

        this.visited = new boolean[vn];
        for (int i = 0; i < vn; i++){
            this.visited[i] = false;
        }

        this.vertices = vertices;

        this.edges = edges;
        graph = new int[vn][vn];
        for (int i = 0; i < edges.length; i++){
            int start = edges[i][0];
            int end = edges[i][1];
            graph[start][end] = 1;
        }
    }

    // 递归法深度优先遍历
    public void dfsTravel(int v){
        // 如果访问过就返回
        if (visited[v]){
            return;
        }
        // 否则就访问,并将访问数组置为true
        visit(v);
        visited[v] = true;
        for (int j = 0; j < vn; j++){
            if (graph[v][j] == 1 && !visited[j]){
                visit(j);
                visited[j] = true;
                // 从该节点继续往下遍历,直到无法继续遍历
                dfsTravel(j);
            }
        }

    }
    public void visit(int v){
        System.out.print(vertices[v] + " ");
    }
}

2、借助栈的非递归法

class DFSGraphTravelByStack{
    int vn; // 定点数
    private int[][] edges; // 边集合
    private boolean[] visited; // 访问集合
    private int[][] graph; // 邻接矩阵
    private String[] vertices; //顶点名集合
	// 初始化图
    public DFSGraphTravelByStack(int vn, int[][] edges, String[] vertices){
        this.vn = vn;

        this.visited = new boolean[vn];
        for (int i = 0; i < vn; i++){
            this.visited[i] = false;
        }

        this.vertices = vertices;

        this.edges = edges;
        graph = new int[vn][vn];
        for (int i = 0; i < edges.length; i++){
            int start = edges[i][0];
            int end = edges[i][1];
            graph[start][end] = 1;
        }
    }
    // 借助栈的深度优先遍历
    public void dfsTravelByStack(){
        Stack<Integer> stack = new Stack<>();
        for (int v = 0; v < vn; v++){
            if (!visited[v]){
                visited[v] = true;
                visit(v);
                stack.push(v);
            }
            while (!stack.isEmpty()){
                int temp = stack.pop();
                for (int j = 0; j < vn; j++){
                    if (graph[temp][j] == 1 && !visited[j]){
                        visit(j);
                        visited[j] = true;
                        stack.push(j);
                        break;
                    }
                }
            }
        }
    }
    public void visit(int v){
        System.out.print(vertices[v] + " ");
    }
}

二、图的广度优先遍历(邻接矩阵法)

1、借助队列的非递归方法

// 需要在调用的地方遍历每个点,确保都访问到了
for (int i = 0; i < vn; i++){
    bfsGraphTravelByQueue.bfsTravelByQueue(i);
}
class BFSGraphTravelByQueue{
    int vn; // 定点数
    private int[][] edges; // 边集合
    private boolean[] visited; // 访问集合
    private int[][] graph; // 邻接矩阵
    private String[] vertices; //顶点名集合
    // 初始化图
    public BFSGraphTravelByQueue(int vn, int[][] edges, String[] vertices){
        this.vn = vn;

        this.visited = new boolean[vn];
        for (int i = 0; i < vn; i++){
            this.visited[i] = false;
        }

        this.vertices = vertices;

        this.edges = edges;
        graph = new int[vn][vn];
        for (int i = 0; i < edges.length; i++){
            int start = edges[i][0];
            int end = edges[i][1];
            graph[start][end] = 1;
        }
    }
    public void bfsTravelByQueue(int v){
        if (visited[v]){
            return;
        }
        visit(v);
        visited[v] = true;
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(v);
        while (!queue.isEmpty()){
            int temp = queue.poll();
            for (int j = 0; j < vn; j++){
                if (graph[temp][j] == 1 && !visited[j]){
                    visit(j);
                    visited[j] = true;
                    queue.offer(j);
                }
            }
        }
    }
    public void visit(int v){
        System.out.print(vertices[v] + " ");
    }
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值