python实现Kruskal && Prim算法

一、Kruskal算法

def find(forest, item):
    """返回未变化的双亲节点,如果变化了找到未变化的为止"""
    if forest[item] != item: # 双亲节点和当前节点不一致,变化了说明这条边已经添加MST
        forest[item] = find(forest, forest[item])  # 找到双亲节点未变化的点
    return forest[item]


def Kruskal(nodes, edges):
    '''基于不相交集实现Kruskal算法'''
    forest = {}  
    MST = []
    for item in nodes:  # 双亲节点初始化
        forest[item] = item

    edges = sorted(edges, key=lambda element: element[2])  # 排序
    num_sides = len(nodes) - 1  # 最小生成树的边数等于顶点数减一
    for e in edges:
        node1, node2, _ = e
        parent1 = find(forest, node1) # 找到node1的双亲节点
        parent2 = find(forest, node2)
        if parent1 != parent2:     # 双亲节点不一致
            MST.append(e)
            num_sides -= 1
            if num_sides == 0:     # 注意控制条件是最小生成树的边满足条件
                return MST
            else:                  # 改变该顶点的双亲节点
                forest[parent1] = parent2
   


def main():
    nodes = set(list('ABCDEFGHI'))  # 注意集合无序
    edges = [("A", "B", 4), ("A", "H", 8),
             ("B", "C", 8), ("B", "H", 11),
             ("C", "D", 7), ("C", "F", 4),
             ("C", "I", 2), ("D", "E", 9),
             ("D", "F", 14), ("E", "F", 10),
             ("F", "G", 2), ("G", "H", 1),
             ("G", "I", 6), ("H", "I", 7)]
    print(Kruskal(nodes, edges))
 


if __name__ == '__main__':
    main()

二、Prim算法

1.数据结构:邻接矩阵

2.思路

(1)初始化visit、dist列表

(2)下述步骤重复n次

  • 找出dist列表中最小的距离以及其下标nextIndex
  • 通过graph中nextIndex行的元素更新dist

3.代码实现

import math

def prim(graph, start=0):

    visit_list = []                # 记录每次选择的顶点
    vertex_num = len(graph)
    visit = [False] * vertex_num
    dist = [math.inf] * vertex_num # 选择某个顶点的边长度

    for i in range(vertex_num):

        minDist = math.inf
        nextIndex = start
        # 寻找dis列表中最小的距离以及下标
        for j in range(vertex_num):
            if dist[j] < minDist and not visit[j]:
                minDist = dist[j]
                nextIndex = j

        visit_list.append(nextIndex)
        visit[nextIndex] = True

        # 通过graph中nextIndex行的元素更新dist
        for j in range(vertex_num):
            if dist[j] > graph[nextIndex][j] and not visit[j]:
                dist[j] = graph[nextIndex][j]
    return dist, visit_list

def main():
    # 邻接矩阵存储图
    graph = [
        [0, 6, 3, math.inf, math.inf, math.inf],
        [6, 0, 2, 5, math.inf, math.inf],
        [3, 2, 0, 3, 4, math.inf],
        [math.inf, 5, 3, 0, 2, 3],
        [math.inf, math.inf, 4, 2, 0, 5],
        [math.inf, math.inf, math.inf, 3, 5, 0],
    ]

    dis, visit = prim(graph) # 最小生成树边的集合:dis[:start] union dis[start+1:]
    print(dis, visit)  # [inf, 2, 3, 3, 2, 3] [0, 2, 1, 3, 4, 5]

if __name__ == '__main__':
    main()

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我来为您解答这个问题。 首先,Prim算法Kruskal算法都是用来生成最小生成树的算法,它们的基本思想都是贪心算法。 下面分别介绍Prim算法Kruskal算法的实现方法。 1. Prim算法 Prim算法的基本思想是从任意一点开始,不断选择与当前生成树相邻的最短边,直到生成一棵包含所有点的最小生成树。 下面是Prim算法Python实现: ```python def prim(graph): # 初始化节点集合、边集合和已访问的节点集合 nodes = set(graph.keys()) edges = [] visited = set() # 从任意一个节点开始 current_node = nodes.pop() visited.add(current_node) # 对每个节点进行遍历 while nodes: # 获取当前节点相邻的边集合 adjacent_edges = [(weight, current_node, node) for node, weight in graph[current_node].items() if node in nodes] # 选择最短的边 weight, from_node, to_node = sorted(adjacent_edges)[0] # 将边添加到边集合中 edges.append((from_node, to_node, weight)) # 将当前节点添加到已访问的节点集合中 visited.add(to_node) # 将当前节点设置为新的节点 current_node = to_node # 从节点集合中删除已经访问过的节点 nodes.discard(current_node) return edges ``` 2. Kruskal算法 Kruskal算法的基本思想是将所有边按照权重从小到大排序,然后依次加入生成树中,如果加入后形成环,则不加入。 下面是Kruskal算法的Python实现: ```python def kruskal(graph): # 初始化节点集合、边集合和并查集 nodes = set(graph.keys()) edges = [] disjoint_set = {node: {node} for node in nodes} # 将所有边按照权重排序 sorted_edges = sorted([(weight, from_node, to_node) for from_node, adjacent_nodes in graph.items() for to_node, weight in adjacent_nodes.items()]) # 遍历所有边 for weight, from_node, to_node in sorted_edges: # 判断边的两个端点是否已经在同一个集合中 if disjoint_set[from_node] & disjoint_set[to_node]: continue # 将边添加到边集合中 edges.append((from_node, to_node, weight)) # 合并两个集合 disjoint_set[from_node] |= disjoint_set[to_node] disjoint_set[to_node] = disjoint_set[from_node] return edges ``` 以上就是Prim算法Kruskal算法的Python实现。希望能对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值