📜  数据结构-图(1)

📅  最后修改于: 2023-12-03 15:26:09.216000             🧑  作者: Mango

数据结构-图

图是一种非常重要的数据结构,它由节点和边组成,用来表示各种复杂的关系。在计算机科学中,图有着广泛的应用,例如:路由、社交网络分析、最短路径问题等。

图的基本概念
  • 顶点:图中的元素,可以用数字或字母表示。
  • :图中连接顶点之间的线,可以表示两个顶点之间的关系。
  • 有向图:边是有方向的图,每条边都有一个起点和一个终点。
  • 无向图:边是无方向的图,两个顶点之间的边没有方向。
  • 权重:边上的数值或费用。
图的存储方式

图的存储方式有两种基本方法:邻接矩阵和邻接表。

邻接矩阵

邻接矩阵是使用二维数组来表示顶点和边之间的关系,其中矩阵的行和列分别对应顶点,而矩阵中的值表示两个顶点之间的关系。如果两个顶点之间有边相连,则矩阵中对应的值为1;否则为0。

    | 1 | 2 | 3 |
----|---|---|---|
  1 | 0 | 1 | 1 |
----|---|---|---|
  2 | 1 | 0 | 1 |
----|---|---|---|
  3 | 1 | 1 | 0 |

邻接矩阵的优点是可以快速地判断两个顶点之间是否有边相连,缺点是占用的空间较大,对于稀疏矩阵来说,大量空间会被浪费。

邻接表

邻接表是使用链表来表示每个顶点所连接的边,每个顶点保存一个链表,链表中的节点保存当前顶点连接的其他顶点和边。邻接表可以有效地处理稀疏图,但判断两个顶点之间是否有边需要遍历链表,时间复杂度可能会比较高。

1 -> 2 -> 3
2 -> 1 -> 3
3 -> 1 -> 2
图的遍历

图的遍历指的是从图中的一个顶点出发,依次遍历所有的节点,并访问每个节点。图的遍历有两种常用的方法,分别是深度优先遍历和广度优先遍历。

深度优先遍历

深度优先遍历从图中的一个顶点出发,依次遍历该顶点所连接的所有节点。如果节点没有被访问过,则将其标记为已访问,并递归遍历该节点的相邻节点。

深度优先遍历使用栈来保存访问的顶点,遍历时先访问起点并入栈,如果它有子节点,则访问其中一个子节点,将该子节点入栈,如果没有子节点,或者所有的子节点都已经访问过,则将当前节点出栈。

深度优先遍历的时间复杂度为O(V+E),其中V是顶点的数量,E是边的数量。

广度优先遍历

广度优先遍历从图中的一个顶点出发,依次遍历离该顶点最近的所有节点。遍历时使用队列来保存已访问的顶点,先访问起点并入队列,然后依次访问与该顶点相邻的所有节点,并将这些节点入队列。访问过的节点标记为已访问。

广度优先遍历的时间复杂度为O(V+E),其中V是顶点的数量,E是边的数量。

图的算法

图的算法包括最短路径算法、最小生成树算法等。

最短路径算法

最短路径算法用来查找两个顶点之间的最短路径,其中Dijkstra算法和Bellman-Ford算法是两种比较常用的最短路径算法。

Dijkstra算法

Dijkstra算法使用贪心策略,在处理前一个节点时,找到所有相邻节点的最短路径,然后选择一个距离最短的节点,将它添加到已访问的节点中,并将该节点的距离值保存起来。然后继续遍历其相邻节点并更新它们的距离值,直到所有节点都被访问过。Dijkstra算法只适用于处理没有负权值边的图。

Bellman-Ford算法

Bellman-Ford算法适用于处理有负权值边的图,它通过遍历每一条边来更新每个顶点的距离值。Bellman-Ford算法中还会检测是否有负环路,如果有,算法将返回False。

最小生成树算法

最小生成树算法用来查找一个无向图中所有顶点的连通子集,该子集可以连接所有顶点并且满足权值最小。

其中Kruskal算法和Prim算法是两种常用的最小生成树算法。

Kruskal算法

Kruskal算法使用贪心策略,按照边的权值从小到大的顺序选择边,并保证创建的边不会形成环路,直到生成树中包括了所有的顶点为止。

Prim算法

Prim算法使用贪心策略,从一个随机选择的顶点开始建立树,并选择连接树中节点和树外节点的最短边。每次添加一条边都会将一个新的节点添加到树中,直到生成树包含了所有的顶点。Prim算法比Kruskal算法更适合处理有较多边的稠密图。