最小生成树算法之prim

4 篇文章 0 订阅
3 篇文章 0 订阅

输入无向图G=V,E),它的权重函数是w: E→R

输出一个最小生成树T----一棵用最小权重连接所有顶点的树:

移去任何属于(uv)∈TT被分割成两棵子树T1T2

还是用剪切和粘贴法来证明如下:

从它的性质我们可以知道它符合动态规划的两个性质,所以我们可以用动态规划来设计算法,但是此处还有一个更好的性质:子问题的最优解也是全局最优解

证明,同样适用反证法和剪切粘贴法

下面介绍贪心算法的一种----prim算法

有一个保存V-Apriority queue Q , 对Q中每一个顶点赋一个key,这个值是它连接到A中所有元素的least-weight edge

由pthon实现的代码如下:

# This Python file uses the following encoding: utf-8
'''
#最小生成树 prim算法的python实现 

普里姆(Prim)算法:由线到点,适合边稠密。时间复杂度O(N^2) 

href=http://blog.csdn.net/hguisu/article/details/7719428
'''
debug=0
MAX_NUM=10000
v_num=6

grapharr=[[0,6,1,5,MAX_NUM,MAX_NUM],
          [6,0,5,MAX_NUM,3,MAX_NUM],
          [1,5,0,5,5,4],
          [5,MAX_NUM,5,0,MAX_NUM,2],
          [MAX_NUM,3,6,MAX_NUM,0,6],
          [MAX_NUM,MAX_NUM,4,2,6,0],
          ]


######################################
#U放已经匹配好的顶点:
U=[]
#V初始化为所有顶点的集合: 
V=[]
#T放各个边:
T=[]
def init():
    if(debug):
        print("grapharr=",end="")
        print(grapharr)    
    i=0
    while i<v_num:
        V.append(i+1)
        i=i+1
    if(graph_check()=="合法"):
        print("合法")
    else:
        print("非法")
        exit(1)



def graph_check():
    print("检查图表数组是否合法")
    return "合法"


def prim_start_vertex(start):
    if(start<1):
        print("ERROR:start=",start)
        print("ERROR:change start to 1 by default!")
        start=1
        
    U.append(start)
    del V[start-1]


def list_sort(l):
    if(len(l)<1):
        print("ERROR:len of l =",len(l))
        exit(1) 
    
    index=0
    i=0
    min_val=l[0]
    while i < len(l):
        if min_val > l[i]:
            min_val=l[i]
            index=i

        i=i+1
    if(debug):
        print("[list_sort]:l=",l,";index=",index)
    return index



def min_wui():
    m=MAX_NUM
    close_edge={'u':-1,'v':-1}
    edge_list=[]
    vertex_list=[]
    i=0
    j=0
      #算出U和V之间所有边的长度:
    lu=len(U)
    lv=len(V)
    if(debug):
        print("##############entry min_wui###########")
        print("lu=",lu,";lv=",lv)
#    while i < len(U):
    for i in range(len(U)):
#        while j < len(V):
        for j in range(len(V)):
            if(debug):
                print("i=",i,";j=",j)
                print("U[i]=",U[i],";V[j]=",V[j])
            temp=grapharr[U[i]-1][V[j]-1]
            if(temp>0):
                if(temp<MAX_NUM):
                    close_edge={'u':U[i],'v':V[j]}
                    vertex_list.append(close_edge)
                    edge_list.append(temp)
                if(debug):                    
                    print("close_edge=",close_edge)
            

    if(debug):        
        print("vertex_list=",vertex_list)
        print("edge_list=",edge_list)     
    min_index=list_sort(edge_list)
    close_edge=vertex_list[min_index]
    U.append(close_edge['v'])
    del V[V.index(close_edge['v'])]
    if(debug):
        print("U=",U)
        print("V=",V)        
    return close_edge


def py_prim(start):
    init()
    prim_start_vertex(start)
    print("init values:")
    print("U=",U)
    print("V=",V)
    print("T=",T)
    while(len(U)!=v_num):
        if(debug):                
            print("len(U)=",len(U))
        our_edge=min_wui()
        T.append(our_edge)

    print("========RESULT============")
    print("U=",U)
    print("V=",V)
    print("T=",T)    


######################################
if(__name__=="__main__"):
    debug=0
    py_prim(1)

以上代码转自http://blog.csdn.net/playboyno/article/details/7829913

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值