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

news/2024/7/20 22:52:40 标签: 深度优先, 图论, java

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

图论不强调非递归。

使用邻接表

1个连通分量

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

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

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

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());
    }
}

图的先序遍历和后续遍历

在这里插入图片描述

java">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

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

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

java">public interface Graph {

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

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

邻接表

java">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);
    }
}

邻接矩阵

java">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);
    }
}

使用红黑树构造邻接表

java">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

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();
    }
}

在这里插入图片描述

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

java">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();
    }
}

在这里插入图片描述

联通分量的数量

在这里插入图片描述

java">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的值来区别不同的联通分量。

java">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

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

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.niftyadmin.cn/n/5015015.html

相关文章

java基础面试题 第四天

一、java基础面试题 第四天 1. String 为什么不可变&#xff1f; **不可变对象&#xff1a;**不可变对象在java中就是被final修饰的类就称为不可变对象&#xff0c;具体含义是&#xff0c;不可变对象一但被赋值以后&#xff0c;他的引用地址就不能被修改&#xff08;它的属性…

【多线程】Thread 类 详解

Thread 类 详解 一. 创建线程1. 继承 Thread 类2. 实现 Runnable 接口3. 其他变形4. 多线程的优势-增加运行速度 二. Thread 类1. 构造方法2. 常见属性3. 启动线程-start()4. 中断线程-interrupt()5. 线程等待-join()6. 线程休眠-sleep()7. 获取当前线程引用 三. 线程的状态1. …

聚类分析 | MATLAB实现基于SOM自组织特征映射聚类可视化

聚类分析 | MATLAB实现基于SOM自组织特征映射聚类可视化 目录 聚类分析 | MATLAB实现基于SOM自组织特征映射聚类可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于自组织特征映射聚类算法(SOM)的数据聚类可视化 可直接运行 注释清晰 Matlab语言 1.多特征输入&…

MySQL触发器使用指南大全

一、介绍 触发器是与表有关的数据库对象&#xff0c;指在insert/update/delete之前或之后&#xff0c;触发并执行触发器中定义的SQL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性&#xff0c;日志记录&#xff0c;数据校验等操作。 使用别名OLD和NEW来引…

阻塞队列学习总结

ArrayBlockingQueue&#xff1a;一个由数组结构组成的有界阻塞队列。 LinkedBlockingQueue&#xff1a;一个由链表结构组成的有界阻塞队列。 PriorityBlockingQueue&#xff1a;一个支持优先级排序的无界阻塞队列。 DelayQueue&#xff1a;一个使用优先级队列实现的延迟无界…

Vuex -mutations 传参修改仓库数据

文章目录 mutations 修改仓库数据一、mutations的基本修改二、mutations 传参修改数据1、 在触发事件的时候传递参数2、 提供事件方法&#xff0c;接收使用参数3、mutations方法接受使用参数传递参数注意事项&#xff1a; 三、综合代码&#xff08;练习、复习&#xff09;store…

【网络编程】学习成果day7:用sqlite3和fgetc将字典写入数据库中的数据表。

1.将字典写入数据库中的数据表 代码&#xff1a; linuxlinux:~/study/NETbc$ cat 03_dictsqlite3.c #include<myhead.h> #define MAX 50int do_insert(sqlite3* db);int main(int argc, const char *argv[]) {//打开数据库sqlite3 *dbNULL;if(sqlite3_open("./dic…

hive的语言元素

参考文档地址 http://www.hplsql.org/doc 数据类型 可以在HPL/SQL程序中使用以下数据类型&#xff1a; 数据类型描述BIGINT / INT864位整数BINARY_DOUBLE双精度浮点数BINARY_FLOAT单精度浮点数BINARY_INTEGER32位整数BIT0、1或NULLBOOL / BOOLEAN真或假CHAR(n) / CHARACTER…