java语言实现图的广度优先遍历和深度优先遍历

  • 图的遍历
    • 深度优先遍历
    • 广度优先遍历

深度优先遍历
  • 介绍
    • 从初始访问顶点出发,初始访问顶点可能会有很多个邻接顶点,深度优先遍历的方法是先访问第一个未被访问过的邻接顶点,然后以这个邻接顶点作为初始顶点,再访问它的第一个未被访问过的邻接顶点,以此类推。
    • 如果访问到某一个顶点,发现它的邻接顶点都被访问过,就访问它上一个顶点的其他未被访问过的邻接顶点。如果这样回退到最初始的顶点,发现所有的邻接顶点都被访问过,则遍历结束。
    • 这是一个递归过程
  • 算法
    • 1.访问初始顶点 v ,并且将其标记为已访问
    • 2.访问顶点 v 的第一个邻接顶点 neighbor
    • 3.如果 neighbor 存在,则执行步骤 4 ,否则,回到步骤 1,从 v 的下一个顶点继续
    • 4.如果 neighbor 未被访问,则对其进行深度优先遍历
    • 5.访问结束之后,访问 v 的下一个邻接顶点
    • 6.所有顶点访问过之后结束

广度优先遍历
  • 介绍
    • 从初始访问顶点出发,初始访问顶点可能会有很多个邻接顶点,广度优先遍历的方法是依次访问所有的未被访问过的邻接顶点,然后以第一个未被访问过的邻接顶点作为初始顶点,再访问它的所有的未被访问过的邻接顶点,以此类推。
    • 如果访问到某一个顶点,发现它的邻接顶点都被访问过,就访问它上一个顶点的其他邻接顶点的未被访问过的邻接顶点。如果这样回退到最初始的顶点,发现所有的邻接顶点都被访问过,则遍历结束。
    • 遍历过程中需要有一个队列来记录访问顺序,以便以这个顺序来访问他们的邻接顶点
  • 算法
    • 1.访问初始顶点 v ,并且将其标记为已访问
    • 2.将这个顶点加入到队列中
    • 3.如果队列非空,执行步骤4,否则结束
    • 4.取出队列的头元素
    • 5.访问该头元素的所有未被访问过的邻接顶点,标为已访问,并加入到队列中
    • 6.如果该有元素没有未被访问过的邻接顶点,转到步骤3

代码
  • 除了深度和广度优先遍历算法,还定义了插入顶点、插入边、显示邻接矩阵的方法,还有顶点字母与邻接矩阵下标数字一一对应的方法,或者某个顶点的第一个邻接顶点以及下一个邻接顶点的方法
  • 代码如下
public class Graph {

    private ArrayList<String> vertexList;//顶点集合
    private int[][] edges;//邻接矩阵
    private boolean[] isVisited;//表示顶点是否被访问

    //n是顶点个数
    public Graph(int n) {
        this.vertexList = new ArrayList<>(n);
        this.edges = new int[n][n];
        this.isVisited = new boolean[n];
    }

    //插入节点
    public void insertVertex(String s){
        vertexList.add(s);
    }

    //插入边
    public void insertEdges(int v1, int v2){
        edges[v1][v2] = 1;
        edges[v2][v1] = 1;
    }

    //返回数字对应的顶点
    public String getVertex(int i){
        return vertexList.get(i);
    }

    //显示邻接矩阵
    public void showGraph(){
        for (int i = 0; i < vertexList.size(); i++) {
            for (int j = 0; j < vertexList.size(); j++) {
                System.out.print(edges[i][j]+"  ");
            }
            System.out.println();
        }
    }

    //得到顶点的第一个邻接顶点对应的数字
    public int getFirstNeighbor(int index){
        for (int i = 0; i < vertexList.size(); i++) {
            if (edges[index][i] == 1){
                return i;
            }
        }
        return -1;
    }

    //获取下一个顶点
    public int getNextNeighbor(int v1, int v2){
        for (int i = v2+1; i < vertexList.size(); i++) {
            if (edges[v1][i] == 1){
                return i;
            }
        }
        return -1;
    }

    /**
     * 深度优先遍历算法
     * @param isVisited  顶点访问情况
     * @param i  对应的顶点
     */
    public void deepFirstSearch(boolean[] isVisited, int i){
        //首先输出第一个顶点,并标记为已访问
        System.out.print(getVertex(i)+"-->");
        isVisited[i] = true;
        //找到下一个顶点
        int neighbor = getFirstNeighbor(i);
        while (neighbor != -1){
            if (!isVisited[neighbor]){
                deepFirstSearch(isVisited, neighbor);
            }
            neighbor = getNextNeighbor(i,neighbor);
        }
    }

    //遍历所有顶点
    public void deepFirstSearch(){
        for (int i = 0; i < vertexList.size(); i++) {
            if (!this.isVisited[i]){
                deepFirstSearch(this.isVisited,i);
            }
        }
    }

    /**
     * 广度优先搜索
     * @param isVisited
     * @param i
     */
    public void breadthFirstSearch(boolean[] isVisited, int i){
        int m;
        int nextNeighbor;
        LinkedList<Integer> queue = new LinkedList<>();
        //首先输出第一个顶点,并标记为已访问
        System.out.print(getVertex(i)+"-->");
        isVisited[i] = true;
        queue.addLast(i);
        while (!queue.isEmpty()){
            m = queue.removeFirst();
            nextNeighbor = getFirstNeighbor(m);
            while (nextNeighbor != -1){
                if (!isVisited[nextNeighbor]){
                    System.out.println(getVertex(nextNeighbor)+"-->");
                    isVisited[nextNeighbor] = true;
                    queue.addLast(nextNeighbor);
                }
                nextNeighbor = getNextNeighbor(m, nextNeighbor);
            }
        }
    }

    //广度所有顶点
    public void breadthFirstSearch(){
        for (int i = 0; i < vertexList.size(); i++) {
            if (!this.isVisited[i]){
                breadthFirstSearch(this.isVisited,i);
            }
        }
    }
}

测试代码

public class GraphDemo {
    public static void main(String[] args) {
        String[] vertexs = {"0","1","2","3","4","5","6","7"};
        int n = vertexs.length;
        Graph graph = new Graph(n);
        for (int i = 0; i < n; i++) {
            graph.insertVertex(vertexs[i]);
        }
        graph.insertEdges(0,1);
        graph.insertEdges(0,2);
        graph.insertEdges(1,3);
        graph.insertEdges(1,4);
        graph.insertEdges(2,5);
        graph.insertEdges(2,6);
        graph.insertEdges(5,6);
        graph.insertEdges(3,7);
        graph.insertEdges(4,7);

        graph.showGraph();

        System.out.println("deepth first search");
        //graph.deepFirstSearch();
        System.out.println();
        System.out.println("breadth first search");
        graph.breadthFirstSearch();
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值