数据结构课上学的邻接表存储图只能用来学习使用,真正写算法题的是否如果也写那么多个类,构建图和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 }