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

目录

图的创建和常用方法

深度优先遍历(Depth First Search)

广度优先遍历(Broad First Search) 


图的创建和常用方法

//无向图
public class Graph {
    //顶点集合
    private ArrayList vertexList;
    //存储对应的邻接矩阵
    private int[][] edges;
    //边数
    private int numOfEdges;

    //构造方法
    //传入顶点数
    public Graph(int numOfVertex) {
        this.vertexList = new ArrayList<>(numOfVertex);
        this.edges = new int[numOfVertex][numOfVertex];
        this.numOfEdges = 0;//边数初始为0
    }
    //添加顶点
    public void  interVertex(String vertex){
        vertexList.add(vertex);
    }
    //添加边
    public void interEdge(int v1,int v2,int weight){
        edges[v1][v2] = weight;
        edges[v2][v1] = weight;
        numOfEdges++;
    }


//图中常用方法:
    //返回节点的个数
    public int getNumOfVertex(){
        return vertexList.size();
    }
    //得到边的数目
    public int getNumOfEdges(){
        return numOfEdges;
    }
    //返回节点i对应的数据,以添加的顺序为准
    public String getValueByIndex(int i){
        return vertexList.get(i);
    }
    //返回v1,v2的权值
    public int getWeight(int v1,int v2){
        return edges[v1][v2];
    }
    //显示图所对应的矩阵
    public void showGraph(){
        for(int[] link:edges){
            System.out.println(Arrays.toString(link));
        }
    }

    //测试
    public static void main(String[] args) {
        int n = 5;
        String[] vertexs={"A","B","C","D","E"};
        Graph graph = new Graph(n);
        //添加顶点
        for(String vertex:vertexs){
            graph.interVertex(vertex);
        }
        //添加边:A-C  A-B  A-E  B-D
        graph.interEdge(0,2,1);
        graph.interEdge(0,1,1);
        graph.interEdge(0,4,1);
        graph.interEdge(1,3,1);

        graph.showGraph();
    }
}

邻接矩阵: 

图的深度优先遍历和广度优先遍历_第1张图片 图的深度优先遍历和广度优先遍历_第2张图片

 

 

深度优先遍历(Depth First Search)

深度优先:每次访问当前节点后,首先访问当前节点的第一个邻接矩阵

添加标记顶点是否访问的数组:

 private boolean[] isVisted;

 在构造方法中初始化:

  this.isVisted = new boolean[numOfVertex];

得到第一个邻接节点的下标w: 

 //得到第一个邻接节点的下标w
    public int getFirstNeighbor(int index){
        for (int j = 0; j< vertexList.size(); j++) {
            if (edges[index][j]>0){
                return j;
            }
        }
        return -1;
    }

 根据前一个节点的坐标获取下一个邻接节点:

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

深度优先遍历: 

 //深度优先遍历
    private void dfs(boolean[] isVisted,int i){
        //首先访该节点,输出
        System.out.print(getValueByIndex(i)+"->");
        //访问标记
        isVisted[i] = true;
        //访问节点的第一个邻接节点
        int w = getFirstNeighbor(i);
        while (w!=-1){
            //有的话并且没有被访问过,就遍历该节点
            if (!isVisted[w]){
                dfs(isVisted,w);
            }
            //如果已经被访问过,就访问下一个
            w = getNextNeighbor(i,w);
        }
    }

 若是非连通图(有孤立点),需要将每个顶点深度遍历:

//若是非连通图,需要将每个顶点深度遍历
    public void dfs(){
        for (int i = 0; i < vertexList.size(); i++) {
            if (!isVisted[i]){
                dfs(isVisted,i);
            }
        }
    }

 如下图的深度遍历:

图的深度优先遍历和广度优先遍历_第3张图片

 

 //测试
    public static void main(String[] args) {
        int n = 6;
        String[] vertexs={"A","B","C","D","E","F"};
        Graph graph = new Graph(n);
        //添加顶点
        for(String vertex:vertexs){
            graph.interVertex(vertex);
        }
        //添加边:A-C  A-B  A-E  B-D
        graph.interEdge(0,2,1);
        graph.interEdge(0,1,1);
        graph.interEdge(0,4,1);
        graph.interEdge(1,3,1);

        graph.showGraph();

        graph.dfs();
    }

图的深度优先遍历和广度优先遍历_第4张图片

广度优先遍历(Broad First Search) 

 广度优先:先访问所有直接相邻的节点,然后访问所有与这些节点相邻的节点,以此类推,直到遍历完整个图。

//广度优先遍历
    //对一个节点进行广度优先算法
    private void bfs(boolean[] isVisted,int i){
        int u;//队列头结点的下标
        int w;//邻接节点
        LinkedList queue = new LinkedList();
    //  访问节点,输出
        System.out.print (getValueByIndex(i)+"=>");
    //    标记已访问
        isVisted[i]=true;
    //    添加到队列
        queue.addLast(i);
        while (!queue.isEmpty()){
            u = (Integer) queue.removeFirst();
            //得到第一个邻接节点的下标
            w = getFirstNeighbor(u);
            while (w!=-1){
                if (!isVisted[w]){
                    //没有访问过
                    System.out.print(getValueByIndex(w)+"=>");
                    isVisted[w] = true;
                    queue.addLast(w);
                }
                //以u为前一个节点,访问过去下一个节点
                w = getNextNeighbor(u, w);
            }
        }

    }
    //非连通图 广度优先遍历
    public void bfs(){
        this.isVisted = new boolean[vertexList.size()];
        for (int i = 0; i < vertexList.size(); i++) {
            if (!isVisted[i]){
                bfs(isVisted,i);
            }
        }
    }

测试:

System.out.println("广度优先");
graph.bfs();

 深度和广度测试:

图的深度优先遍历和广度优先遍历_第5张图片

public static void main(String[] args) {
        int n = 8;
        String[] vertexs={"1","2","3","4","5","6","7","8"};
        Graph graph = new Graph(n);
        //添加顶点
        for(String vertex:vertexs){
            graph.interVertex(vertex);
        }
        //添加边:1-2 1-3 2-4 2-5 4-8 5-8 3-6 3-7
        graph.interEdge(0,1,1);
        graph.interEdge(0,2,1);
        graph.interEdge(1,3,1);
        graph.interEdge(1,4,1);
        graph.interEdge(3,7,1);
        graph.interEdge(4,7,1);
        graph.interEdge(2,5,1);
        graph.interEdge(2,6,1);

        graph.showGraph();
        System.out.println("深度优先");
        graph.dfs();
        System.out.println();
        System.out.println("广度优先");
        graph.bfs();
    }

 图的深度优先遍历和广度优先遍历_第6张图片

 

你可能感兴趣的:(数据结构,深度优先,宽度优先,算法)