五、最小生成树之Kruskal和Prim

1.算法介绍

    在实际问题中常常要遇到布线和租用的优化情况,在保持连通的情况下达到最小成本。这就是最小生成树(minimum spanning tree)或最优树(optimal tree)算法的由来。

    最小生成树的两个经典算法—Kruskal与Prim,都是用于求无向连通图的最小生成树算法。

2.算法过程

Kruskal过程:

(i):初始化。集合TE和数组visit,其中TE用来存储最小生成树的边,visit通过访问标识来检测环

(ii):将图G(V,E)的所有边,按照权值不减顺序排列,选取其中的第一个边e(u,v),如果u和v的visit都为0(即都没访问过,不存在环),则将边e加入集合TE中,设置相应的visit元素

(iii):检测visit是否全部为1,如果都访问过了,则结束算法;否则,跳转到(ii)

Kruskal的复杂度一般表示为O(mlogn),其中m为图的边数,而n为图的顶点数

Prim过程:

(i):初始化。集合TE、S、数组distant和closest,将图的第一个节点1放入S中,distant[1]=0,closest[1]=0。其中TE用来存储最小生成树的边,S用来记录在集合TE中的顶点,distant用来记录任意节点v∈V-S到S的最小距离,closest用来保存节点v和S距离最近的节点。

(ii):如果S中的顶点个数小于v,则repeat:

  从S中取出最后一个节点v,对于每个节点u∈V-S,如果distant[u]<e(u,v),则distant[u]更新为e(u,v),并且将closest[u]=v

  更新完毕后,遍历节点u∈V-S,找出distant中的最小值distant[i],并取出其closest[i]=k,则将顶点i放入S中,将边e(i,k)放入TE中

Prim算法复杂度为O(v^2)

3.算法示例


import networkx as nx
def Kruskal(G=nx.Graph()):
    TE=[]
    visit=[]
    for node in G.nodes():
        visit.append(0)
    sorted_edge=[]
    for edge in G.edges():
        u=edge[0]
        v=edge[1]
        weight=G.get_edge_data(u,v)['weight']
        if len(sorted_edge) is 0:
            sorted_edge.append((u,v))
        else:
            inc=0
            while inc<len(sorted_edge):
                if G.get_edge_data(sorted_edge[inc][0],sorted_edge[inc][1])['weight']>weight:
                    sorted_edge.insert(inc,(u,v))
                    break
                inc=inc+1
            if inc==len(sorted_edge):
                sorted_edge.append((u,v))
    print sorted_edge
    while len(TE)<G.number_of_nodes()-1:
        item=sorted_edge[0]
        del sorted_edge[0]
        u=item[0]
        v=item[1]
        if visit[v-1]==0 or visit[u-1]==0:
            TE.append(item)
            visit[v-1]=1
            visit[u-1]=1
    print 'Kruskal',TE
def Prim(G=nx.Graph()):
    TE=[]
    S=[]
    distant=[]
    closest=[]
    i=0
    while i<G.number_of_nodes():
        distant.append(100)
        closest.append(0)
        i=i+1
    distant[1]=0
    closest[1]=1
    S.append(1)
    while len(S)<G.number_of_nodes():
        item=S[len(S)-1]
        for node in G.nodes():
            if node not in S and G.has_edge(item,node):
                if distant[node-1]>G.get_edge_data(item,node)['weight']:
                    distant[node-1]=G.get_edge_data(item,node)['weight']
                    closest[node-1]=item
        i=index=0
        while i<len(distant):
            if distant[i]<distant[index] and i+1 not in S:
                index=i
            i=i+1
        S.append(index+1)
        TE.append((closest[index],index+1))
    print "Prime",TE
G=nx.Graph()
G.add_weighted_edges_from([(1,2,1),(1,3,4),(1,4,1),(1,5,3),(1,6,3),(2,3,2),(2,5,4),(3,4,2),(4,5,4),(4,6,5),(5,6,3)])
Kruskal(G)
Prim(G)



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大胖5566

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值