一个图就是一些顶点的集合,这些顶点通过一系列边结对(连接)。顶点用圆圈表示,边就是这些圆圈之间的连线。顶点之间通过边连接。
图有两种主要的表示方法:邻接矩阵和邻接表。请实现这两种表示方法,并提供基本的图操作。
用一个二维数组表示图,如果顶点i和顶点j之间有边,则 matrix[i][j] = 1(无权图)或等于边的权重(有权图)。
要求实现:
- 创建图的邻接矩阵表示
- 添加边的操作
- 删除边的操作
- 判断两个顶点是否相邻
- 获取某个顶点的所有邻接顶点
用链表数组表示图,每个顶点对应一个链表,链表中存储该顶点的所有邻接顶点。
要求实现:
- 创建图的邻接表表示
- 添加边的操作
- 删除边的操作
- 判断两个顶点是否相邻
- 获取某个顶点的所有邻接顶点
示例:
对于如下无向图:
0---1
| |
2---3
邻接矩阵表示:
0 1 2 3
0 0 1 1 0
1 1 0 0 1
2 1 0 0 1
3 0 1 1 0
邻接表表示:
0: [1, 2]
1: [0, 3]
2: [0, 3]
3: [1, 2]
实现图的深度优先搜索(DFS)和广度优先搜索(BFS)算法。
从指定的起始顶点开始,沿着一条路径尽可能深入,直到无法继续,然后回溯到前一个顶点,继续探索其他路径。
要求实现:
- 递归版本的DFS
- 非递归版本的DFS(使用栈)
- 输出遍历的顶点序列
- 判断图的连通性
从指定的起始顶点开始,先访问所有相邻的顶点,然后再访问距离起始顶点更远的顶点。
要求实现:
- BFS遍历算法(使用队列)
- 输出遍历的顶点序列
- 计算从起始顶点到其他顶点的最短距离(边数)
- 输出最短路径
示例:
对于如下图:
0---1---4
| |
2---3
从顶点0开始:
DFS遍历结果: 0 -> 1 -> 4 -> 3 -> 2
BFS遍历结果: 0 -> 1 -> 2 -> 4 -> 3
求解单源最短路径问题,适用于非负权重的图。
要求实现:
- Dijkstra算法求从源顶点到所有其他顶点的最短距离
- 输出最短路径树
- 重构从源顶点到任意顶点的最短路径
示例:
带权图:
0--(4)--1--(2)--4
| |
(1) (3)
| |
2--(1)--3
从顶点0开始的最短距离:
到顶点1的距离: 4, 路径: 0->1
到顶点2的距离: 1, 路径: 0->2
到顶点3的距离: 2, 路径: 0->2->3
到顶点4的距离: 6, 路径: 0->1->4
求解所有顶点对之间的最短路径,可以处理负权重边(但不能有负权重环)。
要求实现:
- Floyd-Warshall算法求所有顶点对的最短距离
- 检测负权重环
- 重构任意两个顶点间的最短路径
示例:
距离矩阵结果:
0 1 2 3 4
0 0 4 1 2 6
1 4 0 5 3 2
2 1 5 0 1 7
3 2 3 1 0 5
4 6 2 7 5 0
基于边的贪心算法,按权重从小到大选择边,使用并查集避免产生环。
要求实现:
- 实现并查集数据结构
- Kruskal算法求最小生成树
- 输出最小生成树的边和总权重
基于顶点的贪心算法,从任意顶点开始,逐步扩展最小生成树。
要求实现:
- Prim算法求最小生成树
- 输出最小生成树的边和总权重
- 优化版本(使用优先队列)
示例:
带权无向图:
2 3
0---1-------4
| |\ |
6| |5\ |1
| | \ |
2---3---4---5
7 4 2
最小生成树(权重和 = 10):
边: (0,1,2), (1,4,3), (4,5,1), (3,4,4)
现在你总共有 n 门课需要选,记为 0 到 n-1。
在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1]
给定课程总量以及它们的先决条件,判断是否可能完成所有课程的学习?
要求实现:
- 使用DFS检测有向图中的环
- 使用拓扑排序(Kahn算法)
- 输出可能的课程学习顺序
示例 1:
输入:
2, [[1,0]]
输出:
true
解释: 总共有 2 门课程。学习课程 1 之前,你需要完成课程 0。所以这是可能的。
示例 2:
输入:
2, [[1,0],[0,1]]
输出:
false
解释: 总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0;并且学习课程 0 之前,你还应先完成课程 1。这是不可能的。
说明:
- 输入的先决条件是由边缘列表表示的图形,而不是邻接矩阵。详情请参见图的表示法。
- 你可以假定输入的先决条件中没有重复的边。
对于一个具有树特征的无向图,我们可选择任何一个节点作为根。图因此可以成为树,在所有可能的树中,具有最小高度的树被称为最小高度树。给出这样的一个图,写出一个函数找到所有的最小高度树并返回他们的根节点。
格式:
- 该图包含
n个节点,标记为0到n - 1。给定数字n和一个无向边edges列表(每一个边都是一对标签)。 - 你可以假设没有重复的边会出现在
edges中。由于所有的边都是无向边,[0, 1]和[1, 0]是相同的,因此不会同时出现在edges里。
示例 1:
输入:
n = 4,
edges = [[1, 0], [1, 2], [1, 3]]
0
|
1
/ \
2 3
输出:
[1]
示例 2:
输入:
n = 6,
edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]]
0 1 2
\ | /
3
|
4
|
5
输出:
[3, 4]