CodeGuide项目中的图数据结构详解
一、什么是图数据结构
图(Graph)是一种非常重要的非线性数据结构,它由一组顶点(Vertex)和一组边(Edge)组成。与树结构相比,图结构更加灵活和通用,能够表示更加复杂的关系网络。
图的基本概念
- 顶点(Vertex):图中的基本元素,也称为节点(Node)
- 边(Edge):连接两个顶点的线,可以是有向的也可以是无向的
- 度(Degree):与顶点相连的边的数量
- 路径(Path):从一个顶点到另一个顶点经过的边的序列
二、图的分类
在CodeGuide项目中,图按照两个维度进行分类:
1. 按方向分类
| 类型 | 特点 | 示例 |
|---|---|---|
| 无向图 | 边没有方向性 | 微信好友关系 |
| 有向图 | 边有方向性 | 微博关注关系 |
2. 按权重分类
| 类型 | 特点 | 示例 |
|---|---|---|
| 无权图 | 边没有权重值 | 简单的社交关系 |
| 有权图 | 边有权重值 | 地图中的距离 |
三、图的实现方式
CodeGuide项目提供了三种主要的图实现方式:
1. 邻接矩阵实现
使用二维数组来表示图的连接关系:
// 邻接矩阵实现
protected int[][] table;
特点:
- 实现简单直观
- 适合稠密图
- 空间复杂度高(O(n²))
2. 邻接表实现(链表)
使用数组+链表的结构:
// 邻接表链表实现
protected LinkedList<Integer[]>[] table;
特点:
- 节省空间
- 适合稀疏图
- 查找效率不如矩阵高
3. 邻接表实现(红黑树)
使用数组+红黑树的结构:
// 邻接表红黑树实现
private TreeSet<Integer>[] table;
特点:
- 查找效率高
- 适合需要频繁查找的场景
- 实现复杂度较高
四、图的遍历算法
1. 深度优先搜索(DFS)
算法思想:
- 从起始顶点出发,沿着一条路径尽可能深地搜索
- 当无法继续深入时,回溯到上一个顶点
- 重复上述过程直到所有顶点都被访问
实现代码:
private void dfs(int v) {
visited[v] = true;
pre.add(v); // 前序遍历
for (int w : graph.adj(v)) {
if (!visited[w]) {
dfs(w);
}
}
post.add(v); // 后序遍历
}
2. 广度优先搜索(BFS)
算法思想:
- 从起始顶点出发,先访问所有相邻顶点
- 然后依次访问这些相邻顶点的相邻顶点
- 类似"涟漪"扩散的方式逐层访问
实现代码:
public void bfs(int s) {
Queue<Integer> queue = new LinkedList<>();
visited[s] = true;
queue.add(s);
while (!queue.isEmpty()) {
int v = queue.remove();
order.add(v);
for (int w : G.adj(v)) {
if (!visited[w]) {
queue.add(w);
visited[w] = true;
}
}
}
}
五、图的应用场景
图数据结构在实际开发中有广泛应用:
- 社交网络:好友关系、关注关系
- 地图导航:路径规划、最短路径
- 任务调度:依赖关系管理
- 推荐系统:用户兴趣图谱
- 网络拓扑:路由器连接关系
六、常见面试问题解析
1. 图的使用场景是什么?
图适合表示多对多的复杂关系,如社交网络、交通网络、任务依赖关系等需要表示复杂连接关系的场景。
2. 图的广度遍历和深度遍历有什么区别?
广度优先遍历(BFS)使用队列实现,按层次遍历;深度优先遍历(DFS)使用栈(递归)实现,沿着一条路径深入到底再回溯。
3. 如何表示图的权重?
可以通过邻接矩阵中的数值或邻接表中存储的额外属性来表示权重。例如:
- 邻接矩阵:
table[x][y] = weight - 邻接表:
table[x].add(new Integer[]{y, weight})
七、学习建议
- 先理解图的基本概念和术语
- 从简单的邻接矩阵实现开始学习
- 手动绘制图结构帮助理解
- 多练习遍历算法的实现
- 结合实际应用场景思考
通过CodeGuide项目中的图实现,可以系统地掌握图数据结构的核心概念和实现方法,为后续学习更复杂的图算法打下坚实基础。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



