最小生成树之克鲁斯卡尔算法的python实现

最小生成树之克鲁斯卡尔算法的python实现

克鲁斯卡尔算法是求连通网的最小生成树的另一种方法。与普里姆算法不同,它适合于求边稀疏的网的最小生成树。

算法思路

利用字典建立图

以字典的形式建立加权连通图,通常以各顶点为字典的键,与该顶点所能连通的其余顶点再次构成一个子字典。这个子字典的键为所能连通的顶点,值为这个有向边的权重。这个子字典则构成了一个完整的值。

例如以下加权连通图:

最小生成树之克鲁斯卡尔算法的python实现_第1张图片 

可表示为:

graph = {

            0: {1: 4, 7: 8},

            1: {2: 8, 7: 11},

            2: {8: 2, 5: 4, 3: 7},

            3: {4: 9, 5: 14},

            4: {5: 10},

            5: {6: 2},

            6: {7: 1, 8: 6},

            7: {8: 7}

        }

将所有边按权重大小排序

将所有边以三元组(始点,终点,权值)的形式放入到列表中。

并将其按照权值大小排序。

def init_distance(graph):
    distance_list = []
    for i in graph.keys():
        for j in graph[i].keys():
            if i != j:
                distance_list.append((i,j,graph[i][j]))
    distance_list.sort(key = lambda x:x[-1],reverse = False)
    return distance_list

依次查看边是否符合标准

在上一步骤中我们已经将所有边按权重大小排序完成,接着就是由小到大依次取出所有边,如果加入该边后所有已选择的边不构成闭环,则该边被成功选入,否则抛弃。

而查看是否构成闭环可以使用并查集的方法。

初始我们可以将所有顶点单独处于一个集合中,每次加入一条边时,判断该边的始点和终点是否处于同一个集合中,若是,则会构成闭环,若没有在同一个集合中,则不构成闭环。

graph = {
            0: {1: 4, 7: 8},
            1: {2: 8, 7: 11},
            2: {8: 2, 5: 4, 3: 7},
            3: {4: 9, 5: 14},
            4: {5: 10},
            5: {6: 2},
            6: {7: 1, 8: 6},
            7: {8: 7},
            8: {}
        }

#初始化并查集,使每一个节点单独存在于一个集合中
def init_set(graph):
    set_dic = dict()
    for i,j in zip(range(len(graph)),graph.keys()):
        set_dic[i] = {j}
    return set_dic

#将边及权重以三元组 "(始点,终点,权重)"的形式存放在数列中,
#并按照权重大小进行由低到高排序
def init_distance(graph):
    distance_list = []
    for i in graph.keys():
        for j in graph[i].keys():
            if i != j:
                distance_list.append((i,j,graph[i][j]))
    distance_list.sort(key = lambda x:x[-1],reverse = False)
    return distance_list

set_dic = init_set(graph)
distance_list = init_distance(graph)
choice = []#以选取边的列表,choice:选择

#判断边的首尾两顶点是否在同一个集合内,若不在,则构不成环,
#将此边放入choice列表中
for edge in distance_list:
    for i in set_dic.keys():
        if edge[0] in set_dic[i]:
            shou = i
        if edge[1] in set_dic[i]:
            wei = i
    if shou != wei:
        set_dic[shou] = set_dic[shou] | set_dic[wei]
        del set_dic[wei]
        choice.append(edge)
        
print(sum([x[-1] for x in choice]))

 

你可能感兴趣的:(数据结构与算法python版,python,算法,数据结构,图论)