图、图的DFS以及BFS遍历

1,679 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

图的基本介绍和存储形式在这里插入图片描述

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

图的创建图解和代码实现

在这里插入图片描述 我们的顶点使用tring类型,用ArrayList来保存;矩阵我们使用一个二维数组int[][]edges来实现。

代码实现:

package 图;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;

public class GraphDemo {

    //存储顶点集合(存储A、B、C、D、E)
    private ArrayList<String> vertexList;

    //存储图对应的邻接矩阵(1表示两点连通,0表示不连通)
    private int[][] edges;

    //表示边的数目
    private int numOfEdges;

    //定义个数组boolean[],记录某个节点是否被访问
    private boolean[] isVisited;

    public static void main(String[] args) {
        //测试
        int n = 5; //节点的个数
        String VertexValue[] = {"A","B","C","D","E"};
        GraphDemo g = new GraphDemo(n);
        for (String value:
             VertexValue) {
            g.insert(value);
        }

        //添加边
        //A-B A-C B-C B-D B-E
        g.insertEdge(0,1,1); //A-B
        g.insertEdge(0,2,1);
        g.insertEdge(1,2,1);
        g.insertEdge(1,3,1);
        g.insertEdge(1,4,1);

        //展示图
        g.showGraph();
        
    }

    //构造器,初始化图的各项数据
    public GraphDemo(int n){ //n是顶点的个数
        edges = new int[n][n];  //n*n的二维矩阵
        vertexList = new ArrayList<>(n); //初始化长度为n
        numOfEdges = 0; //边数初始化为0
        isVisited = new boolean[5];
    }


    //图中常用的方法

    //1.返回节点的个数
    public int getNumOfvertex(){
        return vertexList.size();
    }

    //2.得到边的数目
    public int getNumOfEdges(){
        return numOfEdges;
    }

    //3.返回节点i(下标)对应的数据 0->"A"  1->"B" 2->"C"
    public String getValueByIndex(int i){
        return vertexList.get(i);
    }

    //4.返回v1、v2的权值
    public int getWeight(int v1,int v2){
        return edges[v1][v2];
    }

    //5.显示图对应的矩阵
    public void showGraph(){
        for (int[] link: edges) {
            System.err.println(Arrays.toString(link));
        }
    }


    //插入节点方法
    public void insert(String vertex){
        vertexList.add(vertex);
    }

    //添加边的方法
    /*
        v1表示这一串顶点在邻接矩阵上列的顺序,即第一行第二行第三行...分别对应A、B、C...
        v2表示这一串顶点在邻接矩阵上行的顺序,即第一列第二列第三列...分别对应A、B、C...
        isChat表示这两个点之间是否有连通(1为连通,0表示不连通)
     */
    public void insertEdge(int v1,int v2,int isChat){
        edges[v1][v2] = isChat;
        edges[v2][v1] = isChat;
        numOfEdges++;
    }


}

图的深度优先遍历(DFS)

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 代码实现DFS、BFS:

package 图;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;

public class GraphDemo {

    //存储顶点集合(存储A、B、C、D、E)
    private ArrayList<String> vertexList;

    //存储图对应的邻接矩阵(1表示两点连通,0表示不连通)
    private int[][] edges;

    //表示边的数目
    private int numOfEdges;

    //定义个数组boolean[],记录某个节点是否被访问
    private boolean[] isVisited;

    public static void main(String[] args) {
        //测试
        int n = 5; //节点的个数
        String VertexValue[] = {"A","B","C","D","E"};
        GraphDemo g = new GraphDemo(n);
        for (String value:
             VertexValue) {
            g.insert(value);
        }

        //添加边
        //A-B A-C B-C B-D B-E
        g.insertEdge(0,1,1); //A-B
        g.insertEdge(0,2,1);
        g.insertEdge(1,2,1);
        g.insertEdge(1,3,1);
        g.insertEdge(1,4,1);

//        g.showGraph();

        //测试dfs
//        System.out.println("深度遍历");
//        g.dfs();

        //测试bfs
        System.out.println("广度遍历");
        g.bfs();
    }

    //构造器,初始化图的各项数据
    public GraphDemo(int n){ //n是顶点的个数
        edges = new int[n][n];  //n*n的二维矩阵
        vertexList = new ArrayList<>(n); //初始化长度为n
        numOfEdges = 0; //边数初始化为0
        isVisited = new boolean[5];
    }

    //深度优先遍历算法:DFS
    //得到第一个邻接节点的下标 w
    /*
        如果存在就返回对应的下标,否则返回-1
     */
    public int getFirstNeighbor(int index){
        for (int i = 0; i < vertexList.size(); i++) {
            if(edges[index][i] > 0) return i;
        }
        return -1;
    }

    //根据前一个邻接节点的下标来获取下一个邻接节点
    public int getNextNeighbor(int v1,int v2){
        for (int i = v2+1; i < vertexList.size(); i++) {
            if(edges[v1][i] > 0) return i;
        }
        return -1;
    }

    //dfs正经开始
    //i一开始就是0
    public void dfs(boolean[] isVisited,int i){
        //首先我们访问该节点,输出
        System.out.print(getValueByIndex(i)+"->");
        //将节点设置为已经访问
        isVisited[i] = true;
        //查找节点i的第一个邻接节点w
        int w = getFirstNeighbor(i);

        while (w != -1){ //说明有邻接节点
            if(!isVisited[w]){
                dfs(isVisited,w);
            }
            //如果w已经被访问过了
            w = getNextNeighbor(i,w);
        }

    }

    //对dnf进行一个重载,遍历我们所有的节点,并进行dfs
    //作用:遍历所有节点,进行dfs(回溯)
    public void dfs(){
        for (int i = 0; i < getNumOfvertex(); i++) {
            if(!isVisited[i]) {
                dfs(isVisited,i);
            }
        }
    }


    //对一个节点进行广度优先遍历的方法
    private void bfs(boolean[] isVisited,int i){
        int u; //表示队列的头结点对应下标
        int w; //邻接节点w
        //队列,记录节点访问的顺序
        LinkedList queue = new LinkedList();
        //访问节点,输出节点信息
        System.out.print(getValueByIndex(i)+"->");
        //标记为已访问
        isVisited[i] = true;
        //将节点放入队列
        queue.addLast(i);
        while (!queue.isEmpty()){
            //取出队列的头结点下标
            u = (Integer)queue.removeFirst();
            //得到第一个邻接节点的下标w
            w = getFirstNeighbor(u);
            while (w != -1){ //找到
                //是否访问过?
                if(!isVisited[w]){
                    //为false,说明没被访问过,输出节点信息
                    System.out.print(getValueByIndex(w)+"->");
                    //标记被访问
                    isVisited[w] = true;
                    //放入队列
                    queue.addLast(w);
                }
                //以u为前驱节点,找w后面的下一个节点
                w = getNextNeighbor(u,w); //体现出广度优先

            }
        }
    }

    //遍历所有节点,都进行广度优先搜索
    public void bfs(){
        for (int i = 0; i < getNumOfvertex(); i++) {
            if(!isVisited[i]){
                bfs(isVisited,i);
            }
        }
    }


    //图中常用的方法

    //1.返回节点的个数
    public int getNumOfvertex(){
        return vertexList.size();
    }

    //2.得到边的数目
    public int getNumOfEdges(){
        return numOfEdges;
    }

    //3.返回节点i(下标)对应的数据 0->"A"  1->"B" 2->"C"
    public String getValueByIndex(int i){
        return vertexList.get(i);
    }

    //4.返回v1、v2的权值
    public int getWeight(int v1,int v2){
        return edges[v1][v2];
    }

    //5.显示图对应的矩阵
    public void showGraph(){
        for (int[] link: edges) {
            System.err.println(Arrays.toString(link));
        }
    }


    //插入节点方法
    public void insert(String vertex){
        vertexList.add(vertex);
    }

    //添加边的方法
    /*
        v1表示这一串顶点在邻接矩阵上列的顺序,即第一行第二行第三行...分别对应A、B、C...
        v2表示这一串顶点在邻接矩阵上行的顺序,即第一列第二列第三列...分别对应A、B、C...
        isChat表示这两个点之间是否有连通(1为连通,0表示不连通)
     */
    public void insertEdge(int v1,int v2,int isChat){
        edges[v1][v2] = isChat;
        edges[v2][v1] = isChat;
        numOfEdges++;
    }


}