首页 > 编程语言 >最小生成树 PRIM算法 - 附可运行代码

最小生成树 PRIM算法 - 附可运行代码

时间:2023-10-21 20:33:39浏览次数:39  
标签:tmp 附可 PRIM weight min graph selected vertex 算法

学习的时候,觉得这篇资料蛮好的:

https://www.cnblogs.com/JayShao/p/12381830.html

 

然后这篇文章比较新颖,自觉比较适合写代码的理解:

https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-algorithm-greedy-algo-2/

 

 

代码也比较齐全,我自己动手试试吧!

 

Prim:生成过程中,Edge 必然连着

 

source = [4,1,1,2,2,5,5,7,7,6,6,4]
destiny = [1,2,3,4,5,4,7,4,6,4,3,3]
weight = [1,2,4,3,10,7,6,4,1,8,5,2]


# -- 这个是错误解答: PRIM 用 AOV 试试
tmp_graph = pd.DataFrame()
tmp_graph['source'] = source
tmp_graph['destiny'] = destiny
tmp_graph['weight'] = weight
tmp_graph['num'] = tmp_graph.index
tmp_graph['tag'] = 0

 

基础准备函数

# ----------
# -- Prim 
# ----------
# -- SWAP
def swap_val(a, b):
    tmp = a; a = b; b = tmp;
    return a,b

# -- 改成无向图 def graph_order(g_in): for i in range(len(g_in)): if (g_in['source'][i]>g_in['destiny'][i] ): g_in['source'][i], g_in['destiny'][i] = swap_val(g_in['source'][i], g_in['destiny'][i]) # 一定要用return return g_in
# -- Minimum - return num def find_min_weight(g_in): # -- renew tmp_g = g_in.reset_index(drop=True) tmp_min = tmp_g['weight'][0] tmp_min_ind = tmp_g['num'][0] for i in range(1,len(tmp_g)): if (tmp_g['weight'][i] < tmp_min): tmp_min = tmp_g['weight'][i] tmp_min_ind = tmp_g['num'][i] return tmp_min, tmp_min_ind # -- 初始排序 tmp_graph = graph_order(tmp_graph) # ------ 获取节点向量 tmp_vertex = list(tmp_graph['source']) + list(tmp_graph['destiny']) tmp_vertex = list(set(tmp_vertex)) print(tmp_vertex) tmp_graph

 

微封装的循环搜索 Prim 算法

复杂 O(n2)

vertex_selected=[1]
edge_weight=[]
tmp_v_ind = 1


# -- End Case
# 1.vertes_selected 维度与原维度一致,显示被选入顺序
# 2.edge_weight 向量维度与原图维度一致,显示 Aggregated Weight
# 3.上述两个向量长度不一致

cnt_tot = len(tmp_graph)

j=0
is_break=0
count=0

while ( len(vertex_selected)<cnt_tot and is_break==0):
    
    tmp_2=pd.DataFrame()
    for i in range(len(vertex_selected)):
        
        # -- 处理 Ind 产生一个内部循环
        ind_select_1 = (tmp_graph['source']==vertex_selected[i])
        ind_select_2 = (tmp_graph['destiny']==vertex_selected[i])
        ind_select_3 = (tmp_graph['tag']==0)        
        
        ind_select=[]
        for k in range(len(ind_select_1)):
            ind_select.append( (ind_select_1[k] or ind_select_2[k]) and ind_select_3[k] )
        
        # print(ind_select)
        tmp_3 = tmp_graph[ind_select]
        
        if (i==0):
            tmp_2 = tmp_3
        else:
            tmp_2 = pd.concat([tmp_2, tmp_3])
    
    if (len(tmp_2)>0):
        
        # -- 找到最小值的 ind  
        min_weight, min_weight_ind = find_min_weight(tmp_2)
        
        # -- 两端 tag == 1
        tmp_graph['tag'][tmp_graph.num == min_weight_ind]=1  
        
        # -- 是否有环路 
        is_source_existed=0
        tmp_dest = tmp_graph['destiny'][min_weight_ind]
        for k2 in range(len(vertex_selected)):
            if (vertex_selected[k2]==tmp_dest):
                is_source_existed = 1
                break
        
        is_destiny_existed=0
        tmp_dest_1 = tmp_graph['source'][min_weight_ind]
        for k3 in range(len(vertex_selected)):
            if (vertex_selected[k3]==tmp_dest_1):
                is_destiny_existed=1
                break
                            
        # -- append 
        if ( is_source_existed==0 or is_destiny_existed==0):
            if (is_source_existed==0):
                vertex_selected.append(tmp_dest)
            else:
                if(is_destiny_existed==0):
                    vertex_selected.append(tmp_dest_1)    
            edge_weight.append(min_weight)  # Prim 生成一颗树
                
        #print("min_weight: ", min_weight, min_weight_ind)
        #print("vertex_selected: ", vertex_selected)
        #print("edge_weight: ", edge_weight)

        j=j+1
        count=count+1
        
    else:
        is_break=1  
    
print("Edge Weight: ", edge_weight, "\n")
print("Vertex Selected in Order: ", vertex_selected, "\n")
print("Number of Vertex in SET:", len(vertex_selected), "\n")

 

结论:

第一个向量是选入边的权重,该向量的权重之和就是 Spinning Tree 权重之和,向量维度就是边的数量;

第二个向量,是选入点的顺序(ID)。

 

Kruscal:最小生成树,AOE_sigma 必然最小,生成过程中,Edge 可不连续

并查集:https://www.bilibili.com/video/BV1b7411N798?p=55

王道数据结构,用森林的概念,识别出不同子集。

 

注意数据结构。

 

 

 

标签:tmp,附可,PRIM,weight,min,graph,selected,vertex,算法
From: https://www.cnblogs.com/shoelesscai/p/17779469.html

相关文章

  • 十大排序算法理解总结
    ......
  • 算法刷题记录-二分查找
    算法刷题记录-二分查找二分查找给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1。示例1:输入:nums=[-1,0,3,5,9,12],target=9输出:4解释:9出现在nums中并且下标为4示例2:......
  • js逆向·找到登录时目标网站的加密算法的几种方式
    js逆向·找到登录时目标网站的加密算法的几种方式为什么要去找到目标网站的加密密码方法:为了要把我们的payload正确的带入目标网站的服务器进行逻辑验证,那么就需要知道对方使用的什么加密或者编码规则来处理数据的,比如说我们输入的密码被base64编码了,然后发送给后端,后端会进行解......
  • Floyd算法
    Floyd算法 正如我们所知道的,Floyd算法用于求最短路径。Floyd算法可以说是Warshall算法的扩展,三个for循环就可以解决问题,所以它的时间复杂度为O(n^3)。Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点X到B。所以,我......
  • 算法篇---java算法应用
    算法篇---java算法应用 算法应用之百钱买白鸡(程序员副业--编程学习--业务交流--公众号:匠心程序定制)  案列说明:主要内容是:公鸡5元一只,母鸡3元一只,小鸡1元三只,问100元怎样可以买100鸡?思想:想要实现此算法,只要明白各种条件的关系即可,而且知道公鸡最多买20只,母鸡最多买33只......
  • 1.NCC算法实现及其优化[基础实现篇]
    NCC算法实现及其优化本文将集中探讨一种实现相对简单,效果较好的模板匹配算法(NCC)\[R(x,y)=\frac{\sum_{x',y'}(T'(x',y')\cdotI'(x+x',y+y'))}{\sqrt{\sum_{x',y'}T'(x',y')^2\cdot\sum_{x',y'}I'(x+x&......
  • Matching Network算法概述
    什么是MatchingNetwork1.论文地址:MatchingNetworksforOneShotLearning2.简介:基于MetricLearning部分思想,使用外部记忆来增强网络,提高网络的学习能力。3.创新点借鉴了注意力和外部记忆方面的经验来搭建网络基于meta-learning用task来训练,而不是metric-learning输入......
  • 棋盘覆盖——分治算法的典例
    问题描述在一个\({2^k}\times{2^k}(K\geqslant0)\)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格。棋盘覆盖问题要求用图所示的4种不同形状的\(L\)型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且任何2个\(L\)型骨牌不得重叠覆盖。问题分析算法设计......
  • 贪心算法实现
    贪心算法顾名思义,贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。当然,希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单......
  • 边缘检测算法
    边缘检测算法是在数字图像处理中常用的一种技术,用于检测图像中物体边缘的位置。以下是几种常见的边缘检测算法:Sobel算子:Sobel算子是一种基于梯度的算法,通过计算图像的水平和垂直方向的梯度值,并将其组合起来得到边缘强度。Sobel算子具有简单、快速的特点,常用于实时应用。Prewitt算子......