JAVA实现图的广度优先遍历

一:广度优先遍历介绍.

      广度优先遍历(BFS),广度优先遍历是尽可能的更多的把相邻的元素都遍历了,然后在访问外层的,有点像中心开花由内到外.

     从图中任选一个顶点v,作为起始顶点.例如下图:BFS的遍历顺序是首先是V,然后是W1,W2,Y11,Y12,Y21,Y22.总是第一层访问完了,才访问第二层的,这就是二叉树的层序访问嘛.

 

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

二:广度优先遍历的实现.使用队列实现.

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

BFS的遍历序列如下:没有确定起始点就不唯一.这里是A是起点.

import java.util.LinkedList;
import java.util.Queue;
/**
 * title: com.lx.algorithm.graph
 * @author: lixing
 * date: 2018/10/31 17:57
 * description:广度优先遍历使用队列实现,(无向非连通图)非递归实现.
 */
public class BFSTest {

    /**
     * 存储节点信息
     */
    private char[] vertices;

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

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

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

    /**
     * 初始化
     */
    public BFSTest(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 bfs() {
        // 初始化所有的节点的访问标志
        for (int v = 0; v < visited.length; v++) {
            visited[v] = false;
        }
        Queue<Integer> queue = new LinkedList<Integer>();
        for (int i = 0; i < vexnum; i++) {
            if (visited[i] == false) {
                visited[i] = true;
                // 打印当前已经遍历的节点
                visit(i);
                // 添加到队列里面
                queue.add(i);
                // 只要队列不为空
                while (!queue.isEmpty()) {
                    // 出队节点,也就是这一层的节点.
                    int k = queue.poll();
                    // 遍历所有未被访问的邻接节点,放入队列
                    for (int j = 0; j < vexnum; j++) {
                        // 也就是访问这一层剩下的未被访问的节点
                        if (arcs[k][j] == 1 && visited[j] == false) {
                            visited[j] = true;
                            visit(j);
                            queue.add(j);
                        }
                    }
                }
            }
        }
        System.out.println();
        pritf(arcs);
    }

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

 运行结果:

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

三:深度优先对比广度优先遍历.

    1. 两种算法的时间复杂度都是一样的.

    2. 深度优先遍历涉及的辅助数据结构是栈,广度优先遍历涉及的队列.

    3. 广度优先遍历占用的内存比较多是横向元素入队的,如果这一层元素比较多,那么队内的元素就比较多,而深度优先遍历的栈内元素是深入栈的,每一条路径不会存储太对的元素,栈内元素依次出栈,占用内存减少.

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