zoukankan      html  css  js  c++  java
  • 最小生成树-Prim算法和Kruskal算法

    Prim算法

    1.概览

    普里姆算法Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点英语Vertex (graph theory)),且其所有边的权值之和亦为最小。该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克英语Vojtěch Jarník)发现;并在1957年由美国计算机科学家罗伯特·普里姆英语Robert C. Prim)独立发现;1959年,艾兹格·迪科斯彻再次发现了该算法。因此,在某些场合,普里姆算法又被称为DJP算法、亚尔尼克算法或普里姆-亚尔尼克算法。

    2.算法简单描述

    1).输入:一个加权连通图,其中顶点集合为V,边集合为E;

    2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;

    3).重复下列操作,直到Vnew = V:

    a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);

    b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;

    4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。

    下面对算法的图例描述

    图例说明不可选可选已选(Vnew
     

    此为原始的加权连通图。每条边一侧的数字代表其权值。 - - -

    顶点D被任意选为起始点。顶点ABEF通过单条边与D相连。A是距离D最近的顶点,因此将A及对应边AD以高亮表示。 C, G A, B, E, F D
     

    下一个顶点为距离DA最近的顶点。BD为9,距A为7,E为15,F为6。因此,FDA最近,因此将顶点F与相应边DF以高亮表示。 C, G B, E, F A, D
    算法继续重复上面的步骤。距离A为7的顶点B被高亮表示。 C B, E, G A, D, F
     

    在当前情况下,可以在CEG间进行选择。CB为8,EB为7,GF为11。E最近,因此将顶点E与相应边BE高亮表示。 C, E, G A, D, F, B
     

    这里,可供选择的顶点只有CGCE为5,GE为9,故选取C,并与边EC一同高亮表示。 C, G A, D, F, B, E

    顶点G是唯一剩下的顶点,它距F为11,距E为9,E最近,故高亮表示G及相应边EG G A, D, F, B, E, C

    现在,所有顶点均已被选取,图中绿色部分即为连通图的最小生成树。在此例中,最小生成树的权值之和为39。 A, D, F, B, E, C, G
    定义一个图
    
    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],
                     ]        
    

      

    PS:画的不是很好 哈哈 意思是这样子的

    '''
    最小生成树 prim算法
    普里姆(Prim)算法:由线到点,适合边稠密。时间复杂度O(N^2)
    '''
    
    Debug_P = 0
    V_NUM   = 6
    MAX_NUM = 10000
    
    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_P):
            print("GraphArr = ", end = "")
            print(GraphArr)
        i = 0
        while i < V_NUM:
            V.append(i+1)
            i = i+1
    
    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(list):
        if(len(list) < 1):
            print("ERROR: Len Of List = ", len(list))
            exit(1)
    
        index = 0
        i = 0
        min_val = list[0]
        while i < len(list):
            if min_val > list[i]:
                min_val = list[i]
                index = i
            i = i+1
        if(Debug_P):
            print("[list_sort]: list = ", list, ", 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_P):
            print("########### entry min_wui ###########")
            print("lu = ", lu,", lv = ", lv)
        while i < len(U):
            while j < len(V):
                if(Debug_P):
                    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]}
                    if(Debug_P):
                        print("close_edge = ", close_edge)
                    vertex_list.append(close_edge)
                    edge_list.append(temp)
                j = j+1
            i = i+1
            j = 0
        if(Debug_P):
            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_P):
            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_P):
                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_P = 1
        py_prim(1)
    

      

  • 相关阅读:
    存储器管理
    进程与线程
    进程间通信 IPC(Inter-Process Communication)
    进程的同步与互斥
    【bzoj4806~bzoj4808】炮车马后——象棋四连击
    【bzoj1013】[JSOI2008]球形空间产生器sphere
    【bzoj5427】最长上升子序列(贪心+LIS)
    NOIP2018没有什么新闻
    【bzoj3170】[Tjoi2013]松鼠聚会(数学题)
    【bzoj5170】Fable(树状数组)
  • 原文地址:https://www.cnblogs.com/eternal1025/p/5244587.html
Copyright © 2011-2022 走看看