图 生成树

图为什么会有生成树?图不是顶点和边的集合吗?顶点确定了,边也确定了,这个图不就固定了吗?

 

你提出的这个问题非常好,它触及了图的结构和生成树的核心概念。的确,图是由顶点(节点)和边(连接节点的线)组成的,它是一个固定的结构。但是,生成树是一个图中的特定子结构,并不是说图本身就自然地包含生成树。下面我将详细解释图和生成树之间的关系。

图和生成树的关系

  1. 图是固定的结构
    图是由顶点集合和边集合组成的。每一条边是连接两个顶点的,因此图的结构是由这些元素(顶点和边)决定的。对于一个给定的图,顶点和边是已经确定的。图的定义是一个静态的结构,它表示了节点和它们之间的连接。

  2. 生成树是图的一个子集
    生成树不是图的一部分,而是从图中提取出来的一个子结构。一个 生成树 是图中所有顶点的一个子图,但它的边数是 n-1,其中 n 是图中顶点的数量。生成树通过选择图中一部分边,保持连通性且没有环,来形成一个树状结构。

    图与生成树的区别

    • 图可能包含多个环,可能有很多条边。

    • 生成树没有环,是一个树状结构,且每个生成树包含的边数量固定为 n-1 条,其中 n 是图的顶点数量。

  3. 为什么图可以有生成树
    生成树的存在并不是由图的具体结构决定的,而是通过选择图中的一部分边来构造一个新的结构。这是因为 的定义本身就要求是 连通的且无环的,而图作为一个包含多个边的结构,可以通过删除部分边来满足这一要求。简单来说,生成树是从图中通过删除一些边形成的

    具体来说:

    • 如果图是连通的(即任意两个顶点之间都有路径相连),则它一定有生成树。

    • 生成树所包含的边 n-1 条是图中所有可能边的一个子集,且这些边的选择是为了保证图中所有顶点都在生成树中,并且没有环。

  4. 为什么生成树是唯一的?
    一个图的 生成树不一定是唯一的。实际上,一个连通图可以有 多个不同的生成树。这取决于选择的边的不同。例如,对于一个简单的三角形图,生成树可以选择任意两条边,而不选择第三条边。不同的边组合会得到不同的生成树。

图的生成树的生成过程

在一个给定的图中,生成树可以通过不同的算法生成。常见的生成树算法包括:

  • Prim 算法:从一个节点开始,逐步将最小的边加入树中,直到所有节点都被包含。

  • Kruskal 算法:将所有边按权重排序,然后逐步选择最小的边加入生成树,确保不会形成环。

这两个算法都能生成一个 最小生成树,即边权和最小的生成树。

生成树的存在条件

  1. 连通图:图必须是连通的,即任意两个顶点之间都有路径连接,否则不能生成一个包含所有顶点的生成树。

  2. 无向图:因为生成树是无向图中的子图,在有向图中则需要特殊处理。

生成树的应用

生成树广泛应用于很多实际问题,特别是在网络设计、通信、计算机网络优化等领域:

  • 最小生成树(MST):最小生成树是加权图的生成树,要求生成树的边权和最小。用于最小化网络中连接所有节点的总成本。

  • 网络布局:用于找到网络连接的最短路径,以最少的成本连接所有的节点(如电话网络、电力网等)。

总结

  • 图本身是由固定的顶点和边构成的,但图中的生成树是一个通过选择图中部分边来构造的子结构,它满足 连通性无环性 的要求。

  • 生成树可以有多个,但每个生成树都会包含所有顶点,且其边数是 n-1

  • 生成树的构建通常是通过一些算法来实现,比如 Prim 算法Kruskal 算法

图的生成树提供了一种将复杂图形结构简化为树形结构的方法,这在优化、设计和计算中有很多实际应用。

 

Prim's Algorithm

好的,我们将使用普里姆(Prim)算法,以顶点 a 为起点,来找出这个连通图的最小生成树(MST)。

 

普里姆算法简介

image

普里姆算法是一种贪心算法,用于在加权连通图中寻找最小生成树。其基本思想是:

  1. 初始化:选择一个起始顶点,并将其放入一个集合 U 中,该集合表示已经包含在最小生成树中的顶点。

  2. 循环:重复以下步骤,直到所有顶点都进入集合 U 中。

    • 在所有连接集合 U 内的顶点与集合 U 外的顶点的边中,找到一条权值最小的边。

    • 将这条权值最小的边加入最小生成树,并将该边所连接的 U 外的顶点加入集合 U


 

计算过程

 

给定的图信息:

  • 顶点(Vertices): {a, b, c, d, e, f, g}

  • 边(Edges)和权重(Weights):

    • ad(9), ab(2), af(5), bf(8), fg(1), bg(4), cg(6), bc(7), ec(10), be(3), bd(1), de(2)

以 a 为起点,逐步构建最小生成树:

初始状态:

  • 已选顶点集合 U = {a}

  • 最小生成树边集合 T = {}

  • 总权重 = 0

第 1 步:

  • 从集合 U = {a} 出发,寻找连接到集合外顶点的权值最小的边。

  • 候选边:(a, b) 权重 2,(a, f) 权重 5,(a, d) 权重 9。

  • 选择 (a, b),因为它的权重最小。

  • 操作:

    • 将顶点 b 加入 U。现在 U = {a, b}。

    • 将边 (a, b) 加入 T

    • 总权重 = 2。

第 2 步:

  • 从集合 U = {a, b} 出发,寻找连接到集合外顶点的权值最小的边。

  • 候选边 (忽略已连接到U内顶点的边):

    • 从 a: (a, f) 权重 5, (a, d) 权重 9

    • 从 b: (b, d) 权重 1, (b, e) 权重 3, (b, g) 权重 4, (b, c) 权重 7, (b, f) 权重 8

  • 在所有候选边中,(b, d) 的权重最小。

  • 操作:

    • 将顶点 d 加入 U。现在 U = {a, b, d}。

    • 将边 (b, d) 加入 T

    • 总权重 = 2 + 1 = 3。

第 3 步:

  • 从集合 U = {a, b, d} 出发,寻找连接到集合外顶点的权值最小的边。

  • 候选边:

    • 从 a: (a, f) 权重 5

    • 从 b: (b, e) 权重 3, (b, g) 权重 4, (b, c) 权重 7, (b, f) 权重 8

    • 从 d: (d, e) 权重 2

  • 在所有候选边中,(d, e) 的权重最小。

  • 操作:

    • 将顶点 e 加入 U。现在 U = {a, b, d, e}。

    • 将边 (d, e) 加入 T

    • 总权重 = 3 + 2 = 5。

第 4 步:

  • 从集合 U = {a, b, d, e} 出发,寻找连接到集合外顶点的权值最小的边。

  • 候选边:

    • 从 a: (a, f) 权重 5

    • 从 b: (b, g) 权重 4, (b, c) 权重 7, (b, f) 权重 8

    • 从 d: (无新的边)

    • 从 e: (e, c) 权重 10

  • 在所有候选边中,(b, g) 的权重最小。

  • 操作:

    • 将顶点 g 加入 U。现在 U = {a, b, d, e, g}。

    • 将边 (b, g) 加入 T

    • 总权重 = 5 + 4 = 9。

第 5 步:

  • 从集合 U = {a, b, d, e, g} 出发,寻找连接到集合外顶点的权值最小的边。

  • 候选边:

    • 从 a: (a, f) 权重 5

    • 从 b: (b, c) 权重 7, (b, f) 权重 8

    • 从 e: (e, c) 权重 10

    • 从 g: (g, f) 权重 1, (g, c) 权重 6

  • 在所有候选边中,(g, f) 的权重最小。

  • 操作:

    • 将顶点 f 加入 U。现在 U = {a, b, d, e, g, f}。

    • 将边 (g, f) 加入 T

    • 总权重 = 9 + 1 = 10。

第 6 步:

  • 从集合 U = {a, b, d, e, g, f} 出发,寻找连接到集合外顶点的权值最小的边。此时只剩下顶点 c 不在集合中。

  • 候选边:

    • 从 b: (b, c) 权重 7

    • 从 e: (e, c) 权重 10

    • 从 g: (g, c) 权重 6

  • 在所有候选边中,(g, c) 的权重最小。

  • 操作:

    • 将顶点 c 加入 U。现在 U = {a, b, c, d, e, f, g}。

    • 将边 (g, c) 加入 T

    • 总权重 = 10 + 6 = 16。

算法结束:

  • 所有顶点都已包含在集合 U 中,最小生成树构建完成。


 

最终结果

 

该连通图的最小生成树包含以下几条边:

  1. a — b (权重 2)

  2. b — d (权重 1)

  3. d — e (权重 2)

  4. b — g (权重 4)

  5. g — f (权重 1)

  6. g — c (权重 6)

最小生成树的总权重为:16

 

INF (无穷大) = 32767

--- 处理图 1 (顶点 A-G) ---

===================================
Prim 算法结果 (从顶点 A 开始):
-----------------------------------
  当前 V-U 集合中的候选边 (lowcost > 0 且 < INF):
    * 边 (B, A),权重: 2
    * 边 (D, A),权重: 9
    * 边 (F, A),权重: 5

--- 步骤 1.a: 查找 V-U 中 lowcost 最小的顶点 (min_cost 初始为 INF) ---
--- 查找完成:选取顶点 B,最小权重: 2 ---
--- 步骤 1.b: 更新 lowcost 和 closest (新加入顶点 B) ---
  * 检查顶点 V-U 中的 C:新边 (B,C) 权值 7 < 旧边 (A,C) 权值 INF,**更新** lowcost[C]=7,closest[C]=B。
  * 检查顶点 V-U 中的 D:新边 (B,D) 权值 1 < 旧边 (A,D) 权值 9,**更新** lowcost[D]=1,closest[D]=B。
  * 检查顶点 V-U 中的 E:新边 (B,E) 权值 3 < 旧边 (A,E) 权值 INF,**更新** lowcost[E]=3,closest[E]=B。
  * 检查顶点 V-U 中的 F:新边 (B,F) 权值 8 >= 旧边 (A,F) 权值 5,**不更新**。
  * 检查顶点 V-U 中的 G:新边 (B,G) 权值 4 < 旧边 (A,G) 权值 INF,**更新** lowcost[G]=4,closest[G]=B。
---------------------------------------------------------
  当前 V-U 集合中的候选边 (lowcost > 0 且 < INF):
    * 边 (C, B),权重: 7
    * 边 (D, B),权重: 1
    * 边 (E, B),权重: 3
    * 边 (F, A),权重: 5
    * 边 (G, B),权重: 4

--- 步骤 2.a: 查找 V-U 中 lowcost 最小的顶点 (min_cost 初始为 INF) ---
--- 查找完成:选取顶点 D,最小权重: 1 ---
--- 步骤 2.b: 更新 lowcost 和 closest (新加入顶点 D) ---
  * 检查顶点 V-U 中的 C:新边 (D,C) 权值 INF >= 旧边 (B,C) 权值 7,**不更新**。
  * 检查顶点 V-U 中的 E:新边 (D,E) 权值 2 < 旧边 (B,E) 权值 3,**更新** lowcost[E]=2,closest[E]=D。
  * 检查顶点 V-U 中的 F:新边 (D,F) 权值 INF >= 旧边 (A,F) 权值 5,**不更新**。
  * 检查顶点 V-U 中的 G:新边 (D,G) 权值 INF >= 旧边 (B,G) 权值 4,**不更新**。
---------------------------------------------------------
  当前 V-U 集合中的候选边 (lowcost > 0 且 < INF):
    * 边 (C, B),权重: 7
    * 边 (E, D),权重: 2
    * 边 (F, A),权重: 5
    * 边 (G, B),权重: 4

--- 步骤 3.a: 查找 V-U 中 lowcost 最小的顶点 (min_cost 初始为 INF) ---
--- 查找完成:选取顶点 E,最小权重: 2 ---
--- 步骤 3.b: 更新 lowcost 和 closest (新加入顶点 E) ---
  * 检查顶点 V-U 中的 C:新边 (E,C) 权值 10 >= 旧边 (B,C) 权值 7,**不更新**。
  * 检查顶点 V-U 中的 F:新边 (E,F) 权值 INF >= 旧边 (A,F) 权值 5,**不更新**。
  * 检查顶点 V-U 中的 G:新边 (E,G) 权值 INF >= 旧边 (B,G) 权值 4,**不更新**。
---------------------------------------------------------
  当前 V-U 集合中的候选边 (lowcost > 0 且 < INF):
    * 边 (C, B),权重: 7
    * 边 (F, A),权重: 5
    * 边 (G, B),权重: 4

--- 步骤 4.a: 查找 V-U 中 lowcost 最小的顶点 (min_cost 初始为 INF) ---
--- 查找完成:选取顶点 G,最小权重: 4 ---
--- 步骤 4.b: 更新 lowcost 和 closest (新加入顶点 G) ---
  * 检查顶点 V-U 中的 C:新边 (G,C) 权值 6 < 旧边 (B,C) 权值 7,**更新** lowcost[C]=6,closest[C]=G。
  * 检查顶点 V-U 中的 F:新边 (G,F) 权值 1 < 旧边 (A,F) 权值 5,**更新** lowcost[F]=1,closest[F]=G。
---------------------------------------------------------
  当前 V-U 集合中的候选边 (lowcost > 0 且 < INF):
    * 边 (C, G),权重: 6
    * 边 (F, G),权重: 1

--- 步骤 5.a: 查找 V-U 中 lowcost 最小的顶点 (min_cost 初始为 INF) ---
--- 查找完成:选取顶点 F,最小权重: 1 ---
--- 步骤 5.b: 更新 lowcost 和 closest (新加入顶点 F) ---
  * 检查顶点 V-U 中的 C:新边 (F,C) 权值 INF >= 旧边 (G,C) 权值 6,**不更新**。
---------------------------------------------------------
  当前 V-U 集合中的候选边 (lowcost > 0 且 < INF):
    * 边 (C, G),权重: 6

--- 步骤 6.a: 查找 V-U 中 lowcost 最小的顶点 (min_cost 初始为 INF) ---
--- 查找完成:选取顶点 C,最小权重: 6 ---
--- 步骤 6.b: 更新 lowcost 和 closest (新加入顶点 C) ---
---------------------------------------------------------

-----------------------------------
最小生成树的总权重: 16
===================================

 

 

 

 

 

 

 

 

 

posted @ 2025-10-15 18:48  ChuckLu  阅读(13)  评论(0)    收藏  举报