图论-图的深度优先遍历-Java

news2024/11/25 6:39:49

回顾力扣144/94//145/102/589/590/429,熟练掌握递归和非递归写法。

图论不强调非递归。

使用邻接表

1个连通分量

在这里插入图片描述Graph.java

package Chapt02_DFS;
import java.io.File;
import java.io.IOException;
import java.util.TreeSet;
import java.util.Scanner;


/// 暂时只支持无向无权图
public class Graph {

    private int V;
    private int E;
    private TreeSet<Integer>[] adj;

    public Graph(String pathStr){

        File file = new File(pathStr);

        try(Scanner scanner = new Scanner(file)){

            V = scanner.nextInt();
            if(V < 0) throw new IllegalArgumentException("V must be non-negative");
            adj = new TreeSet[V];
            for(int i = 0; i < V; i ++)
                adj[i] = new TreeSet<Integer>();

            E = scanner.nextInt();
            if(E < 0) throw new IllegalArgumentException("E must be non-negative");

            for(int i = 0; i < E; i ++){
                int a = scanner.nextInt();
                validateVertex(a);
                int b = scanner.nextInt();
                validateVertex(b);

                if(a == b) throw new IllegalArgumentException("Self Loop is Detected!");
                if(adj[a].contains(b)) throw new IllegalArgumentException("Parallel Edges are Detected!");

                adj[a].add(b);
                adj[b].add(a);
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }
    }

    private void validateVertex(int v){
        if(v < 0 || v >= V)
            throw new IllegalArgumentException("vertex " + v + "is invalid");
    }

    public int V(){
        return V;
    }

    public int E(){
        return E;
    }

    public boolean hasEdge(int v, int w){
        validateVertex(v);
        validateVertex(w);
        return adj[v].contains(w);
    }

    public Iterable<Integer> adj(int v){
        validateVertex(v);
        return adj[v];
    }

    public int degree(int v){
        validateVertex(v);
        return adj[v].size();
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();

        sb.append(String.format("V = %d, E = %d\n", V, E));
        for(int v = 0; v < V; v ++){
            sb.append(String.format("%d : ", v));
            for(int w : adj[v])
                sb.append(String.format("%d ", w));
            sb.append('\n');
        }
        return sb.toString();
    }

    public static void main(String[] args){

        Graph g = new Graph("g2.txt");
        System.out.print(g);
    }
}

GraphDFS.java

package Chapt02_DFS;

import java.util.ArrayList;

public class GraphDFS {

    private Graph G;
    private boolean[] visited;

    //order存放遍历结果
    private ArrayList<Integer> order = new ArrayList<>();

    //在构造函数中对图遍历
    public GraphDFS(Graph G){

        this.G = G;
        /* public int V(){ return V;} 返回顶点的数量*/
        visited = new boolean[G.V()];
        dfs(0); //从第0个节点开始遍历
    }

    private void dfs(int v){
        visited[v] = true; //v这个顶点遍历过了
        order.add(v); //把v放到order数组中

        //把v的相邻顶点w进行遍历,如果相邻顶点没有被访问过则递归地对w顶点进行dfs
        for(int w: G.adj(v))
            if(!visited[w])
                dfs(w);
    }

    // 返回一个可遍历的对象,具体是数组、链表、哈希表或者红黑树对用户屏蔽
    // 使用本方法访问遍历的元素
    public Iterable<Integer> order(){
        return order;
    }

    public static void main(String[] args){

        Graph g = new Graph("g2.txt");
        GraphDFS graphDFS = new GraphDFS(g);
        System.out.println(graphDFS.order());
    }
}

在这里插入图片描述

多个连通分量

在这里插入图片描述

只需要对GraphDFS中的构造函数进行改进
在这里插入图片描述
在这里插入图片描述

GraphDFS.java

package Chapt02_DFS;

import java.util.ArrayList;

public class GraphDFS {

    private Graph G;
    private boolean[] visited;

    //order存放遍历结果
    private ArrayList<Integer> order = new ArrayList<>();

    //在构造函数中对图遍历
    public GraphDFS(Graph G){

        this.G = G;
        /* public int V(){ return V;} 返回顶点的数量*/
        visited = new boolean[G.V()];

        for (int v = 0; v < G.V(); v++) {
            if(!visited[v]) dfs(v);
        }
 //       dfs(0); //从第0个节点开始遍历
    }

    private void dfs(int v){
        visited[v] = true; //v这个顶点遍历过了
        order.add(v); //把v放到order数组中

        //把v的相邻顶点w进行遍历,如果相邻顶点没有被访问过则递归地对w顶点进行dfs
        for(int w: G.adj(v))
            if(!visited[w])
                dfs(w);
    }

    // 返回一个可遍历的对象,具体是数组、链表、哈希表或者红黑树对用户屏蔽
    // 使用本方法访问遍历的元素
    public Iterable<Integer> order(){
        return order;
    }

    public static void main(String[] args){

        Graph g = new Graph("g3.txt");
        GraphDFS graphDFS = new GraphDFS(g);
        System.out.println(graphDFS.order());
    }
}

图的先序遍历和后续遍历

在这里插入图片描述

package Chapt02_DFS;

import java.util.ArrayList;

public class GraphDFS {

    private Graph G;
    private boolean[] visited;

    //order存放遍历结果
//    private ArrayList<Integer> order = new ArrayList<>();
    private ArrayList<Integer> pre = new ArrayList<>(); // 存放先序遍历的结果
    private ArrayList<Integer> post = new ArrayList<>(); // 存放后续遍历的结果


    //在构造函数中对图遍历
    public GraphDFS(Graph G){

        this.G = G;
        /* public int V(){ return V;} 返回顶点的数量*/
        visited = new boolean[G.V()];

        for (int v = 0; v < G.V(); v++) {
            if(!visited[v]) dfs(v);
        }
 //       dfs(0); //从第0个节点开始遍历
    }

    private void dfs(int v){
        visited[v] = true; //v这个顶点遍历过了
//        order.add(v); //把v放到order数组中
        pre.add(v); /*****************/

        //把v的相邻顶点w进行遍历,如果相邻顶点没有被访问过则递归地对w顶点进行dfs
        for(int w: G.adj(v))
            if(!visited[w])
                dfs(w);
        post.add(v); /*****************/
    }

    // 返回一个可遍历的对象,具体是数组、链表、哈希表或者红黑树对用户屏蔽
    // 使用本方法访问遍历的元素
    public Iterable<Integer> pre(){
        return pre;
    }
    public Iterable<Integer> post(){
        return post;
    }
    public static void main(String[] args){

        Graph g = new Graph("g3.txt");
        GraphDFS graphDFS = new GraphDFS(g);
        System.out.println(graphDFS.post());
        System.out.println(graphDFS.pre());
    }
}

在这里插入图片描述

使用邻接矩阵

逻辑一模一样
AdjMatrix.java

package Chapt02_DFS;
import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;

public class AdjMatrix {

    private int V;
    private int E;
    private int[][] adj;

    public AdjMatrix(String filename){

        File file = new File(filename);

        try(Scanner scanner = new Scanner(file)){

            V = scanner.nextInt();
            if(V < 0) throw new IllegalArgumentException("V must be non-negative");
            adj = new int[V][V];

            E = scanner.nextInt();
            if(E < 0) throw new IllegalArgumentException("E must be non-negative");

            for(int i = 0; i < E; i ++){
                int a = scanner.nextInt();
                validateVertex(a);
                int b = scanner.nextInt();
                validateVertex(b);

                if(a == b) throw new IllegalArgumentException("Self Loop is Detected!");
                if(adj[a][b] == 1) throw new IllegalArgumentException("Parallel Edges are Detected!");

                adj[a][b] = 1;
                adj[b][a] = 1;
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }
    }

    private void validateVertex(int v){
        if(v < 0 || v >= V)
            throw new IllegalArgumentException("vertex " + v + "is invalid");
    }

    public int V(){
        return V;
    }

    public int E(){
        return E;
    }

    public boolean hasEdge(int v, int w){
        validateVertex(v);
        validateVertex(w);
        return adj[v][w] == 1;
    }

    public ArrayList<Integer> adj(int v){
        validateVertex(v);
        ArrayList<Integer> res = new ArrayList<>();
        for(int i = 0; i < V; i ++)
            if(adj[v][i] == 1)
                res.add(i);
        return res;
    }

    public int degree(int v){
        return adj(v).size();
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();

        sb.append(String.format("V = %d, E = %d\n", V, E));
        for(int i = 0; i < V; i ++){
            for(int j = 0; j < V; j ++)
                sb.append(String.format("%d ", adj[i][j]));
            sb.append('\n');
        }
        return sb.toString();
    }

    public static void main(String[] args){

        AdjMatrix adjMatrix = new AdjMatrix("g3.txt");
        System.out.print(adjMatrix);
    }
}

AdjMatrixDFS.java

package Chapt02_DFS;
import java.util.ArrayList;

public class AdjMatrixDFS {

    private AdjMatrix G;
    private boolean[] visited;

    private ArrayList<Integer> pre = new ArrayList<>();
    private ArrayList<Integer> post = new ArrayList<>();

    public AdjMatrixDFS(AdjMatrix G){

        this.G = G;
        visited = new boolean[G.V()];
        for(int v = 0; v < G.V(); v ++)
            if(!visited[v])
                dfs(v);
    }

    private void dfs(int v){

        visited[v] = true;
        pre.add(v);
        for(int w: G.adj(v))
            if(!visited[w])
                dfs(w);
        post.add(v);
    }

    public Iterable<Integer> pre(){
        return pre;
    }

    public Iterable<Integer> post(){
        return post;
    }

    public static void main(String[] args){

        AdjMatrix g = new AdjMatrix("g3.txt");
        AdjMatrixDFS graphDFS = new AdjMatrixDFS(g);
        System.out.println("DFS preOrder : " + graphDFS.pre());
        System.out.println("DFS postOrder : " + graphDFS.post());
    }
}

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

使用接口

Graph.java

public interface Graph {

    int V();
    int E();
    boolean hasEdge(int v, int w);
    Iterable<Integer> adj(int v);
    int degree(int v);
}

在不同的图表中重写接口里的方法,其实是把不同图的方法都抽象了出来

邻接表

import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Scanner;

public class AdjList implements Graph{

    private int V;
    private int E;
    private LinkedList<Integer>[] adj;

    public AdjList(String pathStr){

        File file = new File(pathStr);

        try(Scanner scanner = new Scanner(file)){

            V = scanner.nextInt();
            if(V < 0) throw new IllegalArgumentException("V must be non-negative");
            adj = new LinkedList[V];
            for(int i = 0; i < V; i ++)
                adj[i] = new LinkedList<Integer>();

            E = scanner.nextInt();
            if(E < 0) throw new IllegalArgumentException("E must be non-negative");

            for(int i = 0; i < E; i ++){
                int a = scanner.nextInt();
                validateVertex(a);
                int b = scanner.nextInt();
                validateVertex(b);

                if(a == b) throw new IllegalArgumentException("Self Loop is Detected!");
                if(adj[a].contains(b)) throw new IllegalArgumentException("Parallel Edges are Detected!");

                adj[a].add(b);
                adj[b].add(a);
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }
    }

    private void validateVertex(int v){
        if(v < 0 || v >= V)
            throw new IllegalArgumentException("vertex " + v + "is invalid");
    }

    public int V(){
        return V;
    }

    public int E(){
        return E;
    }

    public boolean hasEdge(int v, int w){
        validateVertex(v);
        validateVertex(w);
        return adj[v].contains(w);
    }

    public LinkedList<Integer> adj(int v){
        validateVertex(v);
        return adj[v];
    }

    public int degree(int v){
        return adj[v].size();
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();

        sb.append(String.format("V = %d, E = %d\n", V, E));
        for(int v = 0; v < V; v ++){
            sb.append(String.format("%d : ", v));
            for(int w : adj[v])
                sb.append(String.format("%d ", w));
            sb.append('\n');
        }
        return sb.toString();
    }

    public static void main(String[] args){

        Graph adjList = new AdjList("g.txt");
        System.out.print(adjList);
    }
}

邻接矩阵

import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;

public class AdjMatrix implements Graph {

    private int V;
    private int E;
    private int[][] adj;

    public AdjMatrix(String filename){

        File file = new File(filename);

        try(Scanner scanner = new Scanner(file)){

            V = scanner.nextInt();
            if(V < 0) throw new IllegalArgumentException("V must be non-negative");
            adj = new int[V][V];

            E = scanner.nextInt();
            if(E < 0) throw new IllegalArgumentException("E must be non-negative");

            for(int i = 0; i < E; i ++){
                int a = scanner.nextInt();
                validateVertex(a);
                int b = scanner.nextInt();
                validateVertex(b);

                if(a == b) throw new IllegalArgumentException("Self Loop is Detected!");
                if(adj[a][b] == 1) throw new IllegalArgumentException("Parallel Edges are Detected!");

                adj[a][b] = 1;
                adj[b][a] = 1;
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }
    }

    private void validateVertex(int v){
        if(v < 0 || v >= V)
            throw new IllegalArgumentException("vertex " + v + "is invalid");
    }

    public int V(){
        return V;
    }

    public int E(){
        return E;
    }

    public boolean hasEdge(int v, int w){
        validateVertex(v);
        validateVertex(w);
        return adj[v][w] == 1;
    }

    public Iterable<Integer> adj(int v){
        validateVertex(v);
        ArrayList<Integer> res = new ArrayList<>();
        for(int i = 0; i < V; i ++)
            if(adj[v][i] == 1)
                res.add(i);
        return res;
    }

    public int degree(int v){
        validateVertex(v);
        int res = 0;
        for(int i = 0; i < V; i ++)
            res += adj[v][i];
        return res;
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();

        sb.append(String.format("V = %d, E = %d\n", V, E));
        for(int i = 0; i < V; i ++){
            for(int j = 0; j < V; j ++)
                sb.append(String.format("%d ", adj[i][j]));
            sb.append('\n');
        }
        return sb.toString();
    }

    public static void main(String[] args){

        Graph adjMatrix = new AdjMatrix("g.txt");
        System.out.print(adjMatrix);
    }
}

使用红黑树构造邻接表

import java.io.File;
import java.io.IOException;
import java.util.TreeSet;
import java.util.Scanner;

public class AdjSet implements Graph{

    private int V;
    private int E;
    private TreeSet<Integer>[] adj;

    public AdjSet(String pathStr){

        File file = new File(pathStr);

        try(Scanner scanner = new Scanner(file)){

            V = scanner.nextInt();
            if(V < 0) throw new IllegalArgumentException("V must be non-negative");
            adj = new TreeSet[V];
            for(int i = 0; i < V; i ++)
                adj[i] = new TreeSet<Integer>();

            E = scanner.nextInt();
            if(E < 0) throw new IllegalArgumentException("E must be non-negative");

            for(int i = 0; i < E; i ++){
                int a = scanner.nextInt();
                validateVertex(a);
                int b = scanner.nextInt();
                validateVertex(b);

                if(a == b) throw new IllegalArgumentException("Self Loop is Detected!");
                if(adj[a].contains(b)) throw new IllegalArgumentException("Parallel Edges are Detected!");

                adj[a].add(b);
                adj[b].add(a);
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }
    }

    private void validateVertex(int v){
        if(v < 0 || v >= V)
            throw new IllegalArgumentException("vertex " + v + "is invalid");
    }

    public int V(){
        return V;
    }

    public int E(){
        return E;
    }

    public boolean hasEdge(int v, int w){
        validateVertex(v);
        validateVertex(w);
        return adj[v].contains(w);
    }

    public Iterable<Integer> adj(int v){
    // public TreeSet<Integer> adj(int v){
        validateVertex(v);
        return adj[v];
    }

    public int degree(int v){
        validateVertex(v);
        return adj[v].size();
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();

        sb.append(String.format("V = %d, E = %d\n", V, E));
        for(int v = 0; v < V; v ++){
            sb.append(String.format("%d : ", v));
            for(int w : adj[v])
                sb.append(String.format("%d ", w));
            sb.append('\n');
        }
        return sb.toString();
    }

    public static void main(String[] args){

        Graph adjSet = new AdjSet("g.txt");
        System.out.print(adjSet);
    }
}

GraphDFS.java

package Chapt02_DFS;

import java.util.ArrayList;

public class GraphDFS {

    private Graph G;
    private boolean[] visited;

    private ArrayList<Integer> pre = new ArrayList<>();
    private ArrayList<Integer> post = new ArrayList<>();

    public GraphDFS(Graph G){

        this.G = G;
        visited = new boolean[G.V()];
        for(int v = 0; v < G.V(); v ++)
            if(!visited[v])
                dfs(v);
    }

    private void dfs(int v){

        visited[v] = true;
        pre.add(v);
        for(int w: G.adj(v))
            if(!visited[w])
                dfs(w);
        post.add(v);
    }

    public Iterable<Integer> pre(){
        return pre;
    }

    public Iterable<Integer> post(){
        return post;
    }

    public static void main(String[] args){

        Graph g1 = new AdjSet("g3.txt");
        GraphDFS graphDFS1 = new GraphDFS(g1);
        System.out.println("DFS preOrder : " + graphDFS1.pre());
        System.out.println("DFS postOrder : " + graphDFS1.post());
        System.out.println();

        Graph g2 = new AdjList("g3.txt");
        GraphDFS graphDFS2 = new GraphDFS(g2);
        System.out.println("DFS preOrder : " + graphDFS2.pre());
        System.out.println("DFS postOrder : " + graphDFS2.post());
        System.out.println();

        Graph g3 = new AdjMatrix("g3.txt");
        GraphDFS graphDFS3 = new GraphDFS(g3);
        System.out.println("DFS preOrder : " + graphDFS3.pre());
        System.out.println("DFS postOrder : " + graphDFS3.post());
        System.out.println();
    }
}

在这里插入图片描述

使用非递归的方法遍历图——使用栈

package Chapt02_DFS;

import java.util.ArrayList;
import java.util.Stack;

public class GraphDFSnr {

    private Graph G;
    private boolean[] visited;

    private ArrayList<Integer> pre = new ArrayList<>();


    public GraphDFSnr(Graph G){

        this.G = G;
        visited = new boolean[G.V()];
        for(int v = 0; v < G.V(); v ++)
            if(!visited[v])
                dfs(v);
    }

    private void dfs(int v){

        Stack<Integer> stack = new Stack<>();
        stack.push(v);
        visited[v] = true;
        while(!stack.empty()){
            int cur = stack.pop();
            pre.add(cur);
            for(int w: G.adj(v))
                if(!visited[w]){
                    stack.push(w);
                    visited[w] = true;
                }
        }
    }


    public Iterable<Integer> pre(){
        return pre;
    }



    public static void main(String[] args){

        Graph g1 = new AdjSet("g3.txt");
        GraphDFSnr graphDFS1 = new GraphDFSnr(g1);
        System.out.println("DFS preOrder : " + graphDFS1.pre());

        System.out.println();

        Graph g2 = new AdjList("g3.txt");
        GraphDFSnr graphDFS2 = new GraphDFSnr(g2);
        System.out.println("DFS preOrder : " + graphDFS2.pre());

        System.out.println();

        Graph g3 = new AdjMatrix("g3.txt");
        GraphDFSnr graphDFS3 = new GraphDFSnr(g3);
        System.out.println("DFS preOrder : " + graphDFS3.pre());

        System.out.println();
    }
}

在这里插入图片描述

联通分量的数量

在这里插入图片描述

public class CC {

    private Graph G;
    private boolean[] visited;
    private int cccount = 0;

    public CC(Graph G){

        this.G = G;
        visited = new boolean[G.V()];
        for(int v = 0; v < G.V(); v ++)
            if(!visited[v]){
                dfs(v);
                cccount ++; // 在if循环内
            }
    }

    private void dfs(int v){

        visited[v] = true;
        for(int w: G.adj(v))
            if(!visited[w])
                dfs(w);
    }

    public int count(){
        return cccount;
    }

    public static void main(String[] args){

        Graph g = new AdjList("g3.txt");
        CC cc = new CC(g);
        System.out.println(cc.count());
    }
}

在这里插入图片描述

具体求解无向图的联通分量

在这里插入图片描述
list并不是必要的,可以通过设置visited的值来区别不同的联通分量。

package Chapt02_DFS;
import java.util.ArrayList;

public class CC {

    private Graph G;
    private int[] visited; // boolean 设置为 int
    private int cccount = 0;

    public CC(Graph G){

        this.G = G;
        visited = new int[G.V()];
        for(int i = 0; i < visited.length; i ++)
            visited[i] = -1; // 把未遍历的设置为-1

        for(int v = 0; v < G.V(); v ++)
            if(visited[v] == -1){
                dfs(v, cccount); //dfs(int v, int ccid),ccid初始值为ccount==0 
                cccount ++; //遍历完一组以后,ccount的值+1
            }
    }

    private void dfs(int v, int ccid){
        visited[v] = ccid;
        for(int w: G.adj(v))
            if(visited[w] == -1)
                dfs(w, ccid);
    }

    public int count(){
        for(int e: visited)
            System.out.print(e + " ");
        System.out.println();
        return cccount;
    }

    public static void main(String[] args){

        Graph g = new AdjList("g3.txt");
        CC cc = new CC(g);
        System.out.println(cc.count());
    }
}

在这里插入图片描述

判断两个顶点是否属于同一连通分量 / 这个图有多少联通分量,每个联通分量有多少顶点

把验证代码调整为public
在这里插入图片描述
Graph.java

import java.io.File;
import java.io.IOException;
import java.util.TreeSet;
import java.util.Scanner;


/// 暂时只支持无向无权图
public class Graph {

    private int V;
    private int E;
    private TreeSet<Integer>[] adj;

    public Graph(String filename){

        File file = new File(filename);

        try(Scanner scanner = new Scanner(file)){

            V = scanner.nextInt();
            if(V < 0) throw new IllegalArgumentException("V must be non-negative");
            adj = new TreeSet[V];
            for(int i = 0; i < V; i ++)
                adj[i] = new TreeSet<Integer>();

            E = scanner.nextInt();
            if(E < 0) throw new IllegalArgumentException("E must be non-negative");

            for(int i = 0; i < E; i ++){
                int a = scanner.nextInt();
                validateVertex(a);
                int b = scanner.nextInt();
                validateVertex(b);

                if(a == b) throw new IllegalArgumentException("Self Loop is Detected!");
                if(adj[a].contains(b)) throw new IllegalArgumentException("Parallel Edges are Detected!");

                adj[a].add(b);
                adj[b].add(a);
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }
    }

    public void validateVertex(int v){
        if(v < 0 || v >= V)
            throw new IllegalArgumentException("vertex " + v + "is invalid");
    }

    public int V(){
        return V;
    }

    public int E(){
        return E;
    }

    public boolean hasEdge(int v, int w){
        validateVertex(v);
        validateVertex(w);
        return adj[v].contains(w);
    }

    public Iterable<Integer> adj(int v){
        validateVertex(v);
        return adj[v];
    }

    public int degree(int v){
        validateVertex(v);
        return adj[v].size();
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();

        sb.append(String.format("V = %d, E = %d\n", V, E));
        for(int v = 0; v < V; v ++){
            sb.append(String.format("%d : ", v));
            for(int w : adj[v])
                sb.append(String.format("%d ", w));
            sb.append('\n');
        }
        return sb.toString();
    }

    public static void main(String[] args){

        Graph g = new Graph("g.txt");
        System.out.print(g);
    }
}

CC.java

package Chapt02_DFS.connected;
import Chapt02_DFS.AdjList;
import Chapt02_DFS.Graph;

import java.util.ArrayList;

public class CC {

    private Graph_1 G;
    private int[] visited;
    private int cccount = 0;

    public CC(Graph_1 G){

        this.G = G;
        visited = new int[G.V()];
        for(int i = 0; i < visited.length; i ++)
            visited[i] = -1;

        for(int v = 0; v < G.V(); v ++)
            if(visited[v] == -1){
                dfs(v, cccount);
                cccount ++;
            }
    }

    private void dfs(int v, int ccid){

        visited[v] = ccid;
        for(int w: G.adj(v))
            if(visited[w] == -1)
                dfs(w, ccid);
    }

    public int count(){
        return cccount;
    }

    // 判断两个顶点是否属于同一连通分量
    public boolean isConnected(int v, int w){
        G.validateVertex(v);
        G.validateVertex(w);
        return visited[v] == visited[w];
    }

    public ArrayList<Integer>[] components(){ // 每个联通分量设置一个ArrayList

        ArrayList<Integer>[] res = new ArrayList[cccount];

        for(int i = 0; i < cccount; i ++) // 设置联通分量的ArrayList
            res[i] = new ArrayList<Integer>();

        for(int v = 0; v < G.V(); v ++) // 填充每个连通分量的ArrayList
            res[visited[v]].add(v); // visited[v]是组名,表示是哪个连通分量

        return res;
    }

    public static void main(String[] args){

        Graph_1 g = new Graph_1("g3.txt");
        CC cc = new CC(g);
        System.out.println(cc.count());

        System.out.println(cc.isConnected(0, 6));
        System.out.println(cc.isConnected(5, 6));

        ArrayList<Integer>[] comp = cc.components(); // 把res数组给了comp数组

        for(int ccid = 0; ccid < comp.length; ccid ++){ // ccid = 0、1
            System.out.print(ccid + " : ");

            for(int w: comp[ccid]) //把res[1]/res[2]里的值取出来
                System.out.print(w + " ");

            System.out.println();
        }
    }
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/994772.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

66.C++多态与虚函数

目录 1.什么是多态 2.多态的分类 3.对象转型 3.1 向上转型&#xff1a; 3.2 向下转型&#xff1a; 4.虚函数 1.什么是多态 生活中的多态&#xff0c;是指的客观的事物在人脑中的主观体现。例如&#xff0c;在路上看到⼀只哈士奇&#xff0c;你可以看做是哈士奇&#xf…

Unity实战(10):如何将某个相机的画面做成贴图(RenderTexture)

目录 前言 一、创建物体、材质与相机 二、将RenderTexture赋给材质 2.1 修改rt1的一些属性 2.2 将rtMat1材质的shader改为Unlit/Texture&#xff0c;并将rt1赋给这个材质 三、效果呈现 前言 本文记录如何将某个相机的画面做成贴图&#xff0c;即游戏某些场景中小地图做法…

时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测

时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测 目录 时序预测 | MATLAB实现ICEEMDAN-iMPA-BiLSTM时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 ICEEMDAN-iMPA-BiLSTM功率/风速预测 基于改进的自适应经验模态分解改进海洋捕食者算法双向长短期记忆…

基于SSM的农产品推广应用网站

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

华为云云耀云服务器L实例评测|centos系统搭建git私服

搭建git私服 前言一、云服务器二、服务器安装git三、服务器git配置1.创建文件用于存放公钥2.设置文件权限3.配置本地公钥 四、服务器部署git仓库四、git仓库到本地总结 前言 之前一直想搭建一个属于自己的git私服&#xff0c;然后没赶上厂商的活动&#xff0c;这次正好赶上华为…

学习笔记——树上哈希

普通子树哈希 树上的很多东西都是转化成链上问题的&#xff0c;比如树上哈希 树上哈希&#xff0c;主要是用于树的同构这个东西上的 什么是树的同构&#xff1f; 如图&#xff0c;不考虑节点编号&#xff0c;三棵树是同构的 将树转化成链&#xff0c;一般有两种方式&#xf…

mongodb安装全过程详解

mongodb安装全过程详解 安装mongodb环境安装mongodb shell 安装mongodb环境 进入mongodb官网下载社区版服务器 点击跳转下载地址 选择适应自己系统的版本&#xff0c;然后下载 下图为下载后的文件&#xff0c;双击进行安装 需要注意的两个点 ①选择完整安装 ②不下载mongo…

C语言——指针进阶(二)

目录 七.函数指针数组 八.指向函数指针数组的指针 九.回调函数 结尾 七.函数指针数组 说白了函数指针数组就是函数指针名字后面添加[ ]&#xff0c;二者结合成为数组。 那么这个函数指针数组到底有什么用呢&#xff1f;先不用着急&#xff0c;下面用一个计算器功能代码为大…

【Linux】——网络基础:http协议

目录 前言 应用层 认识协议 协议的概念 传输结构化数据 序列化和反序列化 网络版本计算器 服务器端Server 客户端Client 协议定制 其它 运行效果 HTTP协议 HTTP的简介 认识URL urlencode和urldecode HTTP协议格式 HTTP请求 HTTP响应 HTTP的方法 GET和POST…

时序分解 | MATLAB实现基于LMD局部均值分解的信号分解分量可视化

时序分解 | MATLAB实现基于LMD局部均值分解的信号分解分量可视化 目录 时序分解 | MATLAB实现基于LMD局部均值分解的信号分解分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 LMD局部均值分解 直接替换Excel即可运行包含频谱图相关系数图 Matlab语言 1.算法新颖…

UMA 2 - Unity Multipurpose Avatar☀️七.UMA API介绍

文章目录 🟥 UMA Data DNA参数引用位置🟥 UMA API介绍🟥 UMA Data DNA参数引用位置 我们想通过代码去控制如图所示参数,达到捏脸的目的.下面就是可以控制的代码: _dna["headSize"].Set(1); _avatar.BuildCharacter();我们观察发现操控代码类似Material去设置…

01_瑞萨GUI(LVGL)移植实战教程之软件和硬件准备

本系列教程配套出有视频教程&#xff0c;观看地址&#xff1a;https://www.bilibili.com/video/BV1gV4y1e7Sg 1. 软件和硬件准备 1.1 本节要点 本节学习如何搭建开发环境&#xff0c;硬件接线&#xff0c;为我们后续的学习做好基础必要的准备。 1.2资料准备 本文档所有用到…

flink 端到端一致性

背景 我们经常会混淆flink提供的状态一致性保证和数据端到端一致性保证的关系&#xff0c;总以为他们表达的是同一个意思&#xff0c;事实上&#xff0c;他们不是一个含义&#xff0c;flink只能保证其维护的内部状态的一致性&#xff0c;而数据端到端的一致性需要数据源&#…

Python下载、安装及如何配置Pycharm(Windows 11)详细教程

本文介绍在Windows 11系统Python的下载、安装及配置Pycharm 一、下载 官网地址&#xff1a;https://www.python.org/downloads/windows/ 1、选择Python 3.10.5版本下载 二、安装 1、选择自定义安装 2、全部默认勾选&#xff0c;点击Next 3、自定义安装路径 建议勾选inst…

il2cpp分析-gobal-metadata.dat解密

gobal-metadata.dat解密 工具:010Editor,IDA 7.5,Jadx,VS Code 样本Last Island of Survival_6.3_Apkpure.xapk 分析Il2cpp文件 打开ida,把libil2cpp拖到ida中按快捷键ShiftF12等待字符串分析完后,搜索global-metadata.dat 双击搜索出来的结果 点击aGlobalMetadata 然后…

【并发编程八股】进程、线程、并发编程三大特性

目录 进程与线程的概念&#xff1f;串行、并行、并发的概念&#xff1f;同步异步、阻塞非阻塞的概念&#xff1f;线程的创建的方式&#xff1f;继承 Thread 类&#xff0c;重写 run 方法实现Runnable接口&#xff0c;重写 run 方法实现Callable&#xff0c;重写 call 方法&…

蚂蚁链发布全新Web3品牌ZAN,涉及RWA、合规等服务

9月8日&#xff0c;在外滩大会见解论坛「从科幻到科技&#xff1a;Web3、元宇宙、AIGC」现场上&#xff0c;蚂蚁集团旗下的蚂蚁链联合Everest Ventures Group、HASHKEY、Morpheus labs发布全新Web3品牌ZAN。原蚂蚁链CTO张辉担任ZAN CEO。 该品牌致力于服务Web3机构客户与Web3应…

【数据结构】学习笔记

文章目录 绪论线性表栈、队列、数组串树与二叉树图查找排序 绪论 线性表 栈、队列、数组 串 树与二叉树 图 查找 排序

2023/9/9总结

nodejs Node.js 是基于chrome的v8引擎封装&#xff0c;独立执行于JavaScript代码的环境 Node.js环境中没有BOM和DOM 作用&#xff1a; 编写后端程序&#xff1a;提供数据和网页资源等 前端工程化&#xff1a;集成各种开发中使用的工具和技术 fs模块--读写文件 模块&#xf…

(LeetCode)两数相加深入分析Java版

两数相加&#xff08;题目如下&#xff09; 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数…