Skip to content

Latest commit

 

History

History
252 lines (187 loc) · 5.84 KB

File metadata and controls

252 lines (187 loc) · 5.84 KB

图

一个图就是一些顶点的集合,这些顶点通过一系列边结对(连接)。顶点用圆圈表示,边就是这些圆圈之间的连线。顶点之间通过边连接。

1. 图的表示方法

图有两种主要的表示方法:邻接矩阵和邻接表。请实现这两种表示方法,并提供基本的图操作。

邻接矩阵表示法

用一个二维数组表示图,如果顶点i和顶点j之间有边,则 matrix[i][j] = 1(无权图)或等于边的权重(有权图)。

要求实现:

  1. 创建图的邻接矩阵表示
  2. 添加边的操作
  3. 删除边的操作
  4. 判断两个顶点是否相邻
  5. 获取某个顶点的所有邻接顶点

邻接表表示法

用链表数组表示图,每个顶点对应一个链表,链表中存储该顶点的所有邻接顶点。

要求实现:

  1. 创建图的邻接表表示
  2. 添加边的操作
  3. 删除边的操作
  4. 判断两个顶点是否相邻
  5. 获取某个顶点的所有邻接顶点

示例:

对于如下无向图:
  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]

2. 图的遍历算法

实现图的深度优先搜索(DFS)和广度优先搜索(BFS)算法。

深度优先搜索(DFS)

从指定的起始顶点开始,沿着一条路径尽可能深入,直到无法继续,然后回溯到前一个顶点,继续探索其他路径。

要求实现:

  1. 递归版本的DFS
  2. 非递归版本的DFS(使用栈)
  3. 输出遍历的顶点序列
  4. 判断图的连通性

广度优先搜索(BFS)

从指定的起始顶点开始,先访问所有相邻的顶点,然后再访问距离起始顶点更远的顶点。

要求实现:

  1. BFS遍历算法(使用队列)
  2. 输出遍历的顶点序列
  3. 计算从起始顶点到其他顶点的最短距离(边数)
  4. 输出最短路径

示例:

对于如下图:
  0---1---4
  |   |   
  2---3   

从顶点0开始:
DFS遍历结果: 0 -> 1 -> 4 -> 3 -> 2
BFS遍历结果: 0 -> 1 -> 2 -> 4 -> 3

3. 最短路径算法

Dijkstra算法

求解单源最短路径问题,适用于非负权重的图。

要求实现:

  1. Dijkstra算法求从源顶点到所有其他顶点的最短距离
  2. 输出最短路径树
  3. 重构从源顶点到任意顶点的最短路径

示例:

带权图:
  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算法

求解所有顶点对之间的最短路径,可以处理负权重边(但不能有负权重环)。

要求实现:

  1. Floyd-Warshall算法求所有顶点对的最短距离
  2. 检测负权重环
  3. 重构任意两个顶点间的最短路径

示例:

距离矩阵结果:
    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

4. 最小生成树算法

Kruskal算法

基于边的贪心算法,按权重从小到大选择边,使用并查集避免产生环。

要求实现:

  1. 实现并查集数据结构
  2. Kruskal算法求最小生成树
  3. 输出最小生成树的边和总权重

Prim算法

基于顶点的贪心算法,从任意顶点开始,逐步扩展最小生成树。

要求实现:

  1. Prim算法求最小生成树
  2. 输出最小生成树的边和总权重
  3. 优化版本(使用优先队列)

示例:

带权无向图:
    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)

5. 课程表

现在你总共有 n 门课需要选,记为 0 到 n-1。

在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1]

给定课程总量以及它们的先决条件,判断是否可能完成所有课程的学习?

要求实现:

  1. 使用DFS检测有向图中的环
  2. 使用拓扑排序(Kahn算法)
  3. 输出可能的课程学习顺序

示例 1:

输入: 
2, [[1,0]] 

输出: 
true

解释: 总共有 2 门课程。学习课程 1 之前,你需要完成课程 0。所以这是可能的。

示例 2:

输入: 
2, [[1,0],[0,1]]

输出: 
false

解释: 总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0;并且学习课程 0 之前,你还应先完成课程 1。这是不可能的。

说明:

  • 输入的先决条件是由边缘列表表示的图形,而不是邻接矩阵。详情请参见图的表示法。
  • 你可以假定输入的先决条件中没有重复的边。

6. 最小高度树

对于一个具有树特征的无向图,我们可选择任何一个节点作为根。图因此可以成为树,在所有可能的树中,具有最小高度的树被称为最小高度树。给出这样的一个图,写出一个函数找到所有的最小高度树并返回他们的根节点。

格式:

  • 该图包含 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]