数据结构课上学的邻接表存储图只能用来学习使用,真正写算法题的是否如果也写那么多个类,构建图和DFS操作这么多还这么复杂,那肯定时间不够,所以下面介绍一种刷题的时候比较实用的一种方式,一般不需要创建类,或者最多只需创建一个类
如果每个边没有权重,使用ArrayList<LinkedList<Integer> G来存储图
1 public class Solution1 {
2 // 邻接表存储图
3 public static final int MAXV = 1000;
4 public static boolean[] vis = new boolean[MAXV];
5 public static int n;
6 //
7 public static ArrayList<LinkedList<Integer>> G = new ArrayList<>(MAXV); // 存储图的邻接表
8
9 public static void main(String[] args) {
10 Scanner in = new Scanner(System.in);
11 // 读取一个图的数据
12 n = in.nextInt();
13 int e = in.nextInt();
14
15 // 读取所有边的数据
16 for(int i = 0; i < e; i++){
17 int u = in.nextInt();
18 int v = in.nextInt();
19 G.get(u).add(v);
20 G.get(v).add(u);
21 }
22
23 // DFS遍历图
24 DFSTrave();
25
26 }
27 }
深度优先遍历
1 public static void DFSTrave(){
2 for(int u = 0; u < n; u++){
3 if(vis[u] == false){
4 DFS(u, 1);
5 }
6 }
7 }
8
9 // 从u顶点开始遍历该连通分量
10 private static void DFS(int u, int depth) {
11 vis[u] = true; // 设置u已被访问
12 // 遍历u的所有邻接点
13 for(int i = 0; i < G.get(u).size(); i++){
14 int v = G.get(u).get(i);
15 if(vis[v] == false){ // 如果这个邻接点没有访问过,DFS访问它
16 DFS(v, depth + 1);
17 }
18 }
19 }
广度优先遍历
1 public static boolean[] inq = new boolean[MAXV];
2 private static void BFS(int u) {
3 // 初始化inq数组
4 Arrays.fill(inq, false);
5 Queue<Integer> queue = new LinkedList<Integer>();
6 // 入队u
7 queue.offer(u);
8 // 标记u已入队
9 inq[u] = true;
10
11 // 循环
12 while(!queue.isEmpty()){
13 // 出队队首元素
14 Integer top = queue.poll();
15
16 // 所有未入队邻接点入队
17 for(int i = 0; i < G.get(top).size(); i++){
18 int v = G.get(top).get(i);
19 if(inq[v] == false){
20 queue.offer(v);
21 inq[v] = true;
22 }
23 }
24
25 }
26 }
如果边有权重,需要创建一个类来表示AdjV邻接点, 使用ArrayList<LinkedList<AdjV>> G来存储图
1 public class Solution2 {
2 // 邻接表存储图
3 public static final int MAXV = 1000;
4 public static boolean[] vis = new boolean[MAXV];
5 public static int n;
6
7 public static class AdjV{
8 public int v; // 邻接点
9 public int weight; // 边的权重
10 public AdjV(int v, int weight){
11 this.v = v;
12 this.weight = weight;
13 }
14 }
15
16 public static ArrayList<LinkedList<AdjV>> G = new ArrayList<>(MAXV); // 存储图的邻接表
17
18 public static void main(String[] args) {
19 Scanner in = new Scanner(System.in);
20 // 读取一个图的数据
21 n = in.nextInt();
22 int e = in.nextInt();
23
24 // 读取所有边的数据
25 for(int i = 0; i < e; i++){
26 int u = in.nextInt();
27 int v = in.nextInt();
28 int weight = in.nextInt();
29 G.get(u).add(new AdjV(v, weight));
30 G.get(v).add(new AdjV(u, weight));
31 }
32
33 // DFS遍历图
34 DFSTrave();
35
36 }
37 }
对应的深度优先遍历
1 public static void DFSTrave(){
2 for(int u = 0; u < n; u++){
3 if(vis[u] == false){
4 DFS(u, 1);
5 }
6 }
7 }
8
9 // 从u顶点开始遍历该连通分量
10 private static void DFS(int u, int depth) {
11 vis[u] = true; // 设置u已被访问
12 // 遍历u的所有邻接点
13 for(int i = 0; i < G.get(u).size(); i++){
14 AdjV adjV = G.get(u).get(i);
15 if(vis[adjV.v] == false){ // 如果这个邻接点没有访问过,DFS访问它
16 DFS(adjV.v, depth + 1);
17 }
18 }
19 }
广度优先遍历,
1 public static void DFSTrave(){
2 for(int u = 0; u < n; u++){
3 if(vis[u] == false){
4 BFS(u); // 遍历u所在的连通块
5 }
6 }
7 }
8
9 public static boolean[] inq = new boolean[MAXV];
10 private static void BFS(int u) {
11 // 初始化inq数组
12 Arrays.fill(inq, false);
13 Queue<Integer> queue = new LinkedList<>();
14 // 入队u
15 queue.offer(u);
16 // 标记u已入队
17 inq[u] = true;
18
19 // 循环
20 while(!queue.isEmpty()){
21 // 出队队首元素
22 Integer top = queue.poll();
23
24 // 所有未入队邻接点入队
25 for(int i = 0; i < G.get(top).size(); i++){
26 AdjV adjV = G.get(top).get(i);
27 if(inq[adjV.v] == false){
28 queue.offer(adjV.v);
29 inq[adjV.v] = true;
30 }
31 }
32
33 }
34 }