博客摘录「 求最小生成树的新算法」2024年6月21日

将使用Kruskal算法作为例子,因为它是一种广泛使用且相对简单的最小生成树算法。

以下是Kruskal算法的Python实现:

class DisjointSet:
    def __init__(self, vertices):
        self.parent = {v: v for v in vertices}
        self.rank = {v: 0 for v in vertices}

    def find(self, item):
        if self.parent[item] != item:
            self.parent[item] = self.find(self.parent[item])
        return self.parent[item]

    def union(self, x, y):
        xroot = self.find(x)
        yroot = self.find(y)

        if self.rank[xroot] < self.rank[yroot]:
            self.parent[xroot] = yroot
        elif self.rank[xroot] > self.rank[yroot]:
            self.parent[yroot] = xroot
        else:
            self.parent[yroot] = xroot
            self.rank[xroot] += 1

def kruskal_mst(graph):
    edges = []
    for u in graph:
        for v, weight in graph[u].items():
            edges.append((weight, u, v))
    
    edges.sort()
    vertices = list(graph.keys())
    disjoint_set = DisjointSet(vertices)
    mst = []

    for edge in edges:
        weight, u, v = edge
        if disjoint_set.find(u) != disjoint_set.find(v):
            disjoint_set.union(u, v)
            mst.append((u, v, weight))

    return mst

# 示例使用
graph = {
    'A': {'B': 4, 'C': 2},
    'B': {'A': 4, 'C': 1, 'D': 5},
    'C': {'A': 2, 'B': 1, 'D': 8, 'E': 10},
    'D': {'B': 5, 'C': 8, 'E': 2, 'F': 6},
    'E': {'C': 10, 'D': 2, 'F': 3},
    'F': {'D': 6, 'E': 3}
}

minimum_spanning_tree = kruskal_mst(graph)
print("最小生成树的边:")
for edge in minimum_spanning_tree:
    print(f"{edge[0]} - {edge[1]} : {edge[2]}")

这段代码实现了Kruskal算法来找到给定图的最小生成树。以下是代码的主要部分解释:

  1. DisjointSet类实现了并查集数据结构,用于检测环路。
  2. kruskal_mst函数实现了Kruskal算法的主要逻辑:
    • 将所有边按权重排序
    • 遍历排序后的边,如果添加这条边不会形成环,就将它加入最小生成树
  3. 示例使用部分创建了一个图并调用kruskal_mst函数来找到最小生成树。

如果您需要我解释代码的任何特定部分,或者您想了解其他最小生成树算法(如Prim算法),请告诉我。我也可以根据您的需求修改或优化这个实现。

Prim算法是另一种常用的最小生成树算法。以下是Prim算法的Python实现:

import heapq

def prim_mst(graph):
    # 选择任意起始节点
    start_vertex = list(graph.keys())[0]
    
    mst = []
    visited = set([start_vertex])
    edges = [(cost, start_vertex, to) for to, cost in graph[start_vertex].items()]
    heapq.heapify(edges)

    while edges:
        cost, frm, to = heapq.heappop(edges)
        if to not in visited:
            visited.add(to)
            mst.append((frm, to, cost))

            for next_to, next_cost in graph[to].items():
                if next_to not in visited:
                    heapq.heappush(edges, (next_cost, to, next_to))

    return mst

# 示例使用
graph = {
    'A': {'B': 4, 'C': 2},
    'B': {'A': 4, 'C': 1, 'D': 5},
    'C': {'A': 2, 'B': 1, 'D': 8, 'E': 10},
    'D': {'B': 5, 'C': 8, 'E': 2, 'F': 6},
    'E': {'C': 10, 'D': 2, 'F': 3},
    'F': {'D': 6, 'E': 3}
}

minimum_spanning_tree = prim_mst(graph)
print("最小生成树的边:")
for edge in minimum_spanning_tree:
    print(f"{edge[0]} - {edge[1]} : {edge[2]}")

这段代码实现了Prim算法来找到给定图的最小生成树。以下是代码的主要部分解释:

  1. prim_mst 函数实现了Prim算法的主要逻辑:
    • 从任意起始节点开始
    • 使用优先队列(这里用 heapq 模块实现)来维护边的权重顺序
    • 每次选择与当前树相连的最小权重边,并将其添加到最小生成树中
    • 更新与新加入节点相连的边到优先队列中
    • 重复这个过程直到所有节点都被访问
  2. 使用 heapq 模块来实现优先队列,这样可以高效地获取最小权重的边。
  3. 使用 visited 集合来跟踪已经访问过的节点,避免形成环。
  4. 示例使用部分创建了一个图并调用 prim_mst 函数来找到最小生成树。

Prim算法和Kruskal算法的主要区别在于:

  • Prim算法是从单个顶点开始,逐步扩展最小生成树。
  • Kruskal算法是按照边的权重顺序来考虑所有边,不断添加不形成环的边。

两种算法都能得到正确的最小生成树,但在不同的图结构下可能有不同的性能表现。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百态老人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值