最小生成树算法---Kruscal算法和Prim算法(入门)

来源:互联网 发布:手机淘宝首页大图尺寸 编辑:程序博客网 时间:2024/06/05 06:27

问题描述

假设现在有n个城市,我们要在城市之间修路,使得我们无论从哪一个城市出发,都能通过某种路线到达另一个城市。在不同的城市之间修路,所需费用也不同,求如果要使得每个城市之间连通,最少的花费是多少。
假设城市是结点,结点间的连线的权重就是费用,我们要求的最小花费所选取的边和所有的结点所构成的就是最小生成树。

算法描述

  • 最小生成树的唯一性
    最小生成树不一定是唯一的。
    如图下图1,图2,红色的边连接的结点所构成的两种树都是最小生成树。
    这里写图片描述

    1 

    这里写图片描述
    2 

  • Kruscal的算法过程
    采用贪心的策略,每次从所有边中选取最小的边,限制条件是加入这条边后不能使当前的结点形成回路。
    下面图3-图11是Kruscal算法的选取边的过程。
    这里写图片描述

    3 

    这里写图片描述
    4 

    这里写图片描述
    5 

    这里写图片描述
    6 

    这里写图片描述
    7 

    这里写图片描述
    8 

    这里写图片描述
    8 

    这里写图片描述
    10 

    这里写图片描述
    11 

  • Prim算法过程
    同样是采用贪心的策略,第一步任意选取一个结点加入集合A,选择边的时候,选择连接A和其余不再A中点的最小权重的边(和Dijkstra单源最短路算法类似)。
    下面图12-图20是采用Prime算法的生成过程。

    这里写图片描述

    12 

    这里写图片描述
    13 

    这里写图片描述
    14 

    这里写图片描述
    15 

    这里写图片描述
    16 

    这里写图片描述
    17 

    这里写图片描述
    18 

    这里写图片描述
    19 

    这里写图片描述
    20 

算法实现

假设G1(V,E)图中的最小生成树是G2(V,A) (AV  )

  • Kruscal算法
    1 将边集按照权值从小到大排序
    2 遍历边集选取边e
    3 判断加入e是否使得A集合中结点形成回路(e连接的2个结点都已经在A中)
    4 如果没形成则将e加入A中
    5 重复2-4步
    6 G2(V,A)即最小生成树
Created with Raphaël 2.1.0开始边集遍历完成?结束遍历边集选取边e形成回路?将e加入A集合yesnoyesno
  • Prime算法
    1 任意选取一点加入集合A中
    2 选取连接A和A之外的最小权重边加入A
    3 A中包含所有结点则结束运算
    4 否则重复第2步
Created with Raphaël 2.1.0开始 任意选取一点加入集合A中选取连接A和A之外的最小权重边加入AA中包含所有结点?结束yesno

区别与联系

不论是Kruscal算法还是Prim算法,都是采用了贪心的策略,Kruscal算法是对边集的操作,Prim算法是对点集的操作。

Kruscal算法中,集合A是一个森林,其结点就是给定图的结点。每次加入到集合A中的安全边永远是权重最小的连接两个不同分量的边。
Prim算法中,集合A是一棵,每次加入到A中的安全边永远是连接A和A之外 的某个结点的边中权重最小的边。

参考资料:
算法导论-Thomas H.Cormen、Charles E.Leiserson
wiki百科

1 0