学习的时候,觉得这篇资料蛮好的:
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