最小生成树

来源:互联网 发布:php 循环拼接字符串 编辑:程序博客网 时间:2024/06/07 20:53
最小生成树
    最小生成树(无向图)
    连通图由N个顶点组成,生成树必须包含有N个顶点,N-1条边
    (1)只能用连通图的边来构造最小生成树
    (2)只能恰好好用N-1条边来连接图中的节点
    (3)选用的N-1条边不能构成回路
    
    连通图
    在无向图中V1到V2有路径,则称V1和V2是连通的,如图中任意两个顶点都是连通的,则称此图是连通图

    构造最小生成树的方法,kruskal(克鲁斯卡尔)算法和prim(普利姆)算法求出,这两个算法都采用逐步求解的贪心算法策略
    贪心算法:是指在问题求解时,总是做出当前看起来最好的选择。也就是说贪心算法做出的不是整体最优的选择,而是某种意义上的局部最优解。贪心算法不是对所有的问题都能得到整体的最优解

    1.普利姆算法
    普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克(英语:Vojtěch Jarník)发现;并在1957年由美国计算机科学家罗伯特·普里姆(英语:Robert C. Prim)独立发现;1959年,艾兹格·迪科斯彻再次发现了该算法。因此,在某些场合,普里姆算法又被称为DJP算法、亚尔尼克算法或普里姆-亚尔尼克算法。
    从指定顶点开始将它加入集合中,然后将集合内的顶点与集合外的顶点所构成的所有边中选取权值最小的一条边作为生成树的边,并将集合外的那个顶点加入到集合中,表示该顶点已连通.再用集合内的顶点与集合外的顶点构成的边中找最小的边,并将相应的顶点加入集合中,如此下去直到全部顶点都加入到集合中,即得最小生成树。

    求下图的最小生成树
    从0点出发,每次都选权值小的一路径
    
    普利姆算法的实现较为简单,选取起始节点,判断它与其各个dst顶点间边权值的大小,每次都取权值小的边
    

    2.克鲁斯卡尔算法
    Kruskal算法是一种用来寻找最小生成树的算法,由Joseph Kruskal在1956年发表。用来解决同样问题的还有Prim算法和Boruvka算法等。三种算法都是贪婪算法的应用。和Boruvka算法不同的地方是,Kruskal算法在图中存在相同权值的边时也有效。
    方法:将图中边按其权值由小到大的次序顺序选取,若选边后不形成回路,则保留作为一条边,若形成回路则除去.依次选够(n-1)条边,即得最小生成树.(n为顶点数)

    求下图的最下生成树
    选出一条具有最小权值,且两端点不在同一个集合中(保证不构成回路),则加入生成树。

             


    克鲁斯卡尔算法的具体实现(以邻接表形式)
    
  
   

    测试用例
   

    程序分析图
   

    关于图的完整代码可以在https://github.com/zknn/VS2013---Copy/tree/Graph/Graph查看
  
原创粉丝点击