1、
》》 一个连通图的生成树:图的极小连通图,它包含图中的所有顶点,并且只含尽可能少的边。
这意味着对于生成树来说,若砍去边的一条边,就会使生成树变成非连通图;若给它增加一条边,
就会形成图中的一条回路。
》》 对于一个带权连通无向图 G = ( V , E ) ,生成树不同,每棵树的权(即树中所有边上的权值
之和)也可能不同。设 H 为 G 的所有生成树的集合,若 H1 是 H 中“ 边的权之和最小”的那棵
生成树,则 H1 为 G 的最小生成树。
》》 最小生成树具有的性质:
1)、最小生成树不是唯一的,即最小生成树的树形不唯一, 所有的生成树集合中可能有多个
最小生成树。当图 G 中各边权值互不相等时, G 的最小生成树是唯一的;若无向连通图 G
的边比顶点数少 1 ,即 G 本身就是一棵树时,G 的最小生成树就是它本身。
2)、最小生成树的边的权值之和总是唯一的,虽然最小生成树不唯一,但其对应的边的权值之和
总是唯一的,而且是最小的。
3)、最小生成树的边数为顶点数减 1 。
》》 大多数的算法都利用了最小生成树的下列性质:
假设 G = (V , E)是一个带权连通无向图,U 是顶点集 V 的一个非空子集。若 (u,v)是
一条具有最小权值的边,其中 则必存在一棵包含(u,v) 的最小生成树。
补充1:基于上面性质的最小生成树算法主要有: Prim 算法 和 Kruskal 算法,它们都基于贪心算法
的策略。
2、普里姆(prim)算法【从顶点开始扩展】
》》 普里姆(prim)算法适合于边稠密的图。
》》 prim 算法构造最小生成树的过程【案例】
理解:已知上图中的所有点集 V = { V1 ,V2 , V3 , V4 , V5 , V6 }
准备两个点集合: H1 、 H2 , 且 H1 + H2 = V ,开始的时候, H1 为空,H2 = V
步骤1:首先从 H2 点集中取一个开始点 V1 , 并将 V1 放入到 H1 中。然后,查看 H2 中剩余的点集合中
哪些点集合与 V1 是连通的,并从这些连通的点集合中选取一个权值最小的作为 V1 的下一个连接点。
如上图中 与 V1连通且权值最小的是 V3 ,即把H2 点集中的 V3 放入到 H1 中,此时 H1 = { V1 , V3 } ,
H2 = { V2 , V4 , V5 , V6}
步骤2: “ 查看 H2 点集合中的所有点” 与 “ H1 点集合中的所有点” 的连通性,在 H2 集合中寻找与 H1 集合中
的所有点连通并且权值最小的点。如上图选中的是 V6 , 即将 H2 集合中的 V6 放入到 H1 集合中,此时
H1 = { V1 , V3 , V6 } , H2 = { V2,V4,V5 }
步骤3:“ 查看 H2 点集合中的所有点” 与 “ H1 点集合中的所有点” 的连通性,在 H2 集合中寻找与 H1 集合中
的所有点连通并且权值最小的点。如上图选中的是 V4 , 即将 H2 集合中的 V4 放入到 H1 集合中,此时
H1 = { V1 , V3 , V6 , V4 } , H2 = { V2,V5 }
步骤4: “ 查看 H2 点集合中的所有点” 与 “ H1 点集合中的所有点” 的连通性,在 H2 集合中寻找与 H1 集合中
的所有点连通并且权值最小的点。如上图选中的是 V2 , 即将 H2 集合中的 V2 放入到 H1 集合中,此时
H1 = { V1 , V3 , V6 , V4 , V2 } , H2 = { V5 }
步骤5: 最后将 H2 中剩余的 V5 放入到 H1 集合的末尾。 H1 = { V1 , V3 , V6 , V4 , V2 ,V5 } , H2 = { }
说明:H1 集合中的点集的顺序只是表明在构造最小生成树的过程中点的选取顺序,而在画最小生成树或者编辑
代码的时候,一定选的是“ 后面的点与前面的所有点之间的权值最小的路径 ” 。
3. 克鲁斯卡尔(Kruskal)算法【按权值递增次序来选择合适的边】
》》 Kruskal 算法适合于边稀疏而顶点较多的图。
》》 克鲁斯卡尔(Kruskal)算法来构造最小生成树【案例】
说明1:使用克鲁斯卡尔(Kruskal)算法来构造最小生成树的过程中,按照网中边的权值由小到大的顺序,
不断选取当前未选取的边的集合中权值最小的边。
说明2:通常在 Kruskal 算法中,采用“ 堆 ” 来存放边的集合。