在构建图数据结构时,无向图(Undirected Graph) 和 有向图(Directed Graph) 的处理方式不同,影响着 存储方式、访问逻辑和应用场景。以下是基于代码的分析:
🔹 1. 无向图(Undirected Graph)
🔹 代码解析
java
复制编辑
Map<Integer, Map<Integer, Integer>> graph = new HashMap<>();
private void buildGraph(int [][] edges, Map<Integer, Map<Integer, Integer>> graph){
for(int [] edge: edges){
int u = edge[0];
int v = edge[1];
int weight = edge[2];
// 初始化节点
graph.putIfAbsent(u, new HashMap<>());
graph.putIfAbsent(v, new HashMap<>());
// 无向图:双向存储边
graph.get(u).put(v, weight);
graph.get(v).put(u, weight);
}
}
🔹 关键点
-
双向存储边:
java 复制编辑 graph.get(u).put(v, weight); graph.get(v).put(u, weight);- u → v,v → u 都存储,确保无向图的双向性。
-
适用场景:
- 最短路径搜索(Dijkstra, Floyd-Warshall)
- 连通性问题(DFS, BFS)
- 最小生成树(Kruskal, Prim)
-
时间复杂度:
- 构建图的时间复杂度 O(E) ,其中
E是边数。 - 访问
graph.get(u).put(v, weight)是 O(1) 。
- 构建图的时间复杂度 O(E) ,其中
🔸 2. 有向图(Directed Graph)
🔸 代码解析
java
复制编辑
Map<Integer, Map<Integer, Integer>> graph = new HashMap<>();
Map<Integer, Integer> IndegreeMap = new HashMap<>();
private void buildGraph(int [][] edges, Map<Integer, Map<Integer, Integer>> graph, Map<Integer, Integer> IndegreeMap){
for(int [] edge: edges){
int u = edge[0];
int v = edge[1];
int weight = edge[2];
// 初始化节点
graph.putIfAbsent(u, new HashMap<>());
// 有向图:仅存 u → v
graph.get(u).put(v, weight);
// 记录 v 的入度
IndegreeMap.put(v, IndegreeMap.getOrDefault(v, 0) + 1);
}
}
🔸 关键点
-
单向存储边:
java 复制编辑 graph.get(u).put(v, weight);- 只存储 u → v,不存储 v → u,确保方向性。
-
引入入度(IndegreeMap) :
java 复制编辑 IndegreeMap.put(v, IndegreeMap.getOrDefault(v, 0) + 1);-
用于 拓扑排序(Topological Sorting) ,例如:
- 课程安排(Course Schedule)
- 任务调度(Task Scheduling)
- DAG 最短路径(Shortest Path in DAG)
-
-
适用场景:
- 任务调度(拓扑排序)
- 单向最短路径(Dijkstra, Bellman-Ford)
- 有向无环图(DAG)问题
-
时间复杂度:
- 构建图的时间复杂度 O(E) 。
- 访问
graph.get(u).put(v, weight)是 O(1) 。
🆚 Undirected vs. Directed Graph 总结
| 对比项 | 无向图 (Undirected Graph) | 有向图 (Directed Graph) |
|---|---|---|
| 边的存储 | 双向存储(u → v 和 v → u) | 单向存储(u → v) |
| 数据结构 | Map<Integer, Map<Integer, Integer>> | Map<Integer, Map<Integer, Integer>> + IndegreeMap |
| 入度计算 | ❌ 不需要 | ✅ 需要(用于拓扑排序) |
| 适用场景 | 最短路径、连通性、最小生成树 | 拓扑排序、DAG 处理、单向路径 |
| 时间复杂度 | O(E) | O(E) |
🚀 结论
- 无向图 适用于 最短路径、连通性检查、最小生成树 等问题,需要双向存储边。
- 有向图 适用于 拓扑排序、DAG 处理、单向最短路径 等问题,并且需要记录 入度 以支持相关算法。