图的逻辑结构和具体实现
图一般由节点和边构成
节点的实现:
public class Vertex {
/**
* 顶点
*/
private int id;
/**
* 相邻点
*/
private Vertex[] neighbors;
}
邻接表和邻接矩阵
// 邻接矩阵
// graph[x] 存储 x 的所有邻居节点
List<Integer>[] graph;
// 邻接矩阵
// matrix[x][y] 记录 x 是否有一条指向 y 的边
boolean[][] matrix;
邻接表相对而言占用空间较小
邻接矩阵可以快速判断两个顶点是否相邻
加权有向图
// 邻接矩阵
// graph[x] 存储 x 的所有邻居节点
List<int[]>[] graph;
// 邻接矩阵
// matrix[x][y] 记录 x 是否有一条指向 y 的边
int[][] matrix;
图的遍历
图和多叉树最大的区别是,图是可能包含环的,你从图的某一个节点开始遍历,有可能走了一圈又回到这个节点。需要一个辅助数组visited
记录是否访问过。
题目实战
力扣第 797 题「所有可能路径」,函数签名如下:
List<List<Integer>> allPathsSourceTarget(int[][] graph);
题目输入一幅有向无环图,这个图包含n
个节点,标号为0, 1, 2,..., n - 1
,请你计算所有从节点0
到节点n - 1
的路径。
输入的这个graph
其实就是「邻接表」表示的一幅图,graph[i]
存储这节点i
的所有邻居节点。
比如输入graph = [[1,2],[3],[3],[]]
算法应该返回[[0,1,3],[0,2,3]]
,即0
到3
的所有路径。
代码如下:
public class Solution {
List<List<Integer>> ret = new ArrayList<>();
/**
* 简单图的遍历
*/
public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
LinkedList<Integer> path = new LinkedList<>();
traverse(graph,0,path);
return ret;
}
private void traverse(int[][] graph, int v, LinkedList<Integer> path) {
path.addLast(v);
if (v == graph.length-1) {
// Java语言特性,需要拷贝集合,否者最后都是存入空
ret.add(new LinkedList<>(path));
}
for (int n : graph[v]) {
traverse(graph,n,path);
}
path.removeLast();
}
}