最小生成树——Prim算法与Kruskal算法

最小生成树

一个连通图的生成树是一个极小的连通子图,包含有图中全部的顶点,但只有足以构成一棵树的n-1条边。我们把构造连通网的最小代价生成树称为最小生成树 ( M i n i m u m C o s t S p a n n i n g T r e e ) (Minimum Cost Spanning Tree) (MinimumCostSpanningTree)

Prim算法

普里姆 ( P r i m ) ( Prim ) (Prim)算法是以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树的。
算法思想:假设 N = ( V , { E } ) N=( V,\{E\} ) N=(V,{E})是连通网, T E TE TE N N N上最小生成树中边的集合。算法从 U = { u 0 } U =\{u_0\}%( u_0\in P) U={u0} T E = { } TE=\{\} TE={}开始。重复执行下述操作:在所有 u ∈ U , v ∈ V − U u\in U,v\in V- U uU,vVU的边 ( u , v ) ∈ E (u,v)\in E (u,v)E中找一条代价最小的边 ( u 0 , v 0 ) (u_0,v_0) (u0,v0)并入集合 T E TE TE,同时 v 0 v_0 v0并入 U U U,直至 U = V U=V U=V为止。此时 T E TE TE中必有 n − 1 n-1 n1条边,则 T = ( V , T E ) T= (V,{TE}) T=(V,TE) N N N的最小生成树。

Prim代码

这里我们只需要网 G G G的顶点与边的列表即可

# -*- coding: utf-8 -*-
"""
Created on Mon Mar 25 09:18:08 2019

@author: Administrator
"""

from numpy import *
def Prim(G):
    V=G.vertices 					#例V=['A','B','C',...]
    E=G.edges_list[:] 				#例E=[['A','B',weight],...]
    V_new=[V[0]]
    E_new=[]
    a=[None,None]                   #a储存找到的点与边
    i=1 							#用于防止死循环
    while(set(V_new)!=set(V)):
        MIN=inf
        for edge in E: 				#对E循环,找到符合要求的最小权的边
            if edge[0] in V_new and edge[1] not in V_new:
                if edge[2]<MIN:
                    a[0]=edge[1]
                    a[1]=edge
                    MIN=edge[2]
            elif edge[1] in V_new and edge[0] not in V_new:
                if edge[2]<MIN:
                    a[0]=edge[0]
                    a[1]=edge
                    MIN=edge[2]
            
        if a[0]:
            V_new.append(a[0])
            E_new.append(a[1])
        E.remove(a[1]) 					#将找到的最小权的边移除E
        
        i+=1
        if i>10000:break
    return V_new,E_new

Kruskal算法

克鲁斯卡尔 ( K r u s k a l ) (Kruskal) (Kruskal)算法是先将边按照其权的大小排序,从最小权的边起,依次将不足以构成环的边加入最小生成树中。
算法思想:假设 N = ( V , { E } ) N=(V,\{E\}) N=(V,{E})是连通网,则令最小生成树的初始状态为只有 n n n个顶点而无边的非连通图 T = { V , { } } T=\{V,\{\}\} T={V,{}},图中每个顶点自成一个连通分量。在 E E E中选择代价最小的边,若该边依附的顶点落在 T T T中不同的连通分量上,则将此边加入到 T T T中,否则舍去此边而选择下一条代价最小的边。依次类推,直至 T T T中所有顶点都在同一连通分量上为止。

Kruskal代码

同样,这里我们也只需要网 G G G的顶点与边的列表即可

# -*- coding: utf-8 -*-
"""
Created on Mon Mar 25 10:45:38 2019

@author: Administrator
"""

def Kruskal(G):
    vertices=G.vertices
    #例V=['A','B','C',...]
    edges=sorted(G.edges_list,key=lambda x:x[2]) 
    #例G.edges_list=[['A','B',weight1],...],再将之按权的大小排序,赋值给edges
    Edges=[]
    connected=[]
    for V in vertices:
            connected.append([V])
    for E in edges:
        for j in range(len(connected)):
            if E[0] in connected[j]:
                m=j
            if E[1] in connected[j]:
                n=j
        if m!=n: 									#若E[0]与E[1]所属的连通分量不同
            connected[m]=connected[m]+connected[n]  #将第m个连通分量与第n个连通分量合并于m处
            del connected[n] 						#删去第n个连通分量
            Edges.append(E)
    return Edges

    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值