博客
关于我
最小生成树算法——Prim算法和Kruskal算法
阅读量:653 次
发布时间:2019-03-15

本文共 2348 字,大约阅读时间需要 7 分钟。

Prim算法与Kruskal算法是解决最小生成树问题的经典方法,两者各有特点且在实现上有显著差异。以下将分别阐述Prim算法和Kruskal算法的核心思想、代码实现及其适用场景。


Prim算法:加点法

Prim算法通过每次选择一条连接当前树的外点(不形成环)并加入树中,直到所有节点纳入树中。其关键步骤包括:

  • 初始化:选择一个起点(通常选1号点),将其加入树中,并设其入树权为0。其他点的入树权初始化为它们到起点的权值。
  • 松弛边:每次选择当前树中合权最小的边,将其另一端的点加入树中,并更新其到树中所有点的入树权。
  • 终止条件:当所有点纳入树中时,算法结束。
  • 示例代码(伪代码)

    // 读取输入:n为节点数,m为边数,G为邻接矩阵n, m = 读取输入G = 初始化邻接矩阵lowcost = [INF] * (n + 1)mst = [0] * (n + 1)  // 记录每个点的父节点visited = [False] * (n + 1)sum = 0起点 = 1lowcost[起点] = 0visited[起点] = Truemst[起点] = 0while 有未访问点:    min_cost = INF    min_point = -1    for j from 2到n:        if not visited[j] and lowcost[j] < min_cost:            min_cost = lowcost[j]            min_point = j    if min_point == -1:        break  // 图不连通    visited[min_point] = True    sum += min_cost    for j from 2到n:        if not visited[j]:            if G[min_point][j] < lowcost[j]:                lowcost[j] = G[min_point][j]                mst[j] = min_pointreturn mst, sum

    Kruskal算法:基于并查集的贪心算法

    Kruskal算法通过先对所有边按权值排序,然后每次选择权值最小的未被选的边,若该边的两端点不在同一个连通分量中,则将它们合并到同一连通分量中。其关键步骤包括:

  • 预处理:对所有边按权值从小到大排序。
  • 维护连通分量:使用并查集(Union-Find)数据结构来追踪每个节点所属的连通分量。
  • 选择边:每次选择未被处理的最小边,若该边的两端点在不同分量中,则将它们合并,直到所有节点形成一棵树。
  • 示例代码(伪代码)

    // 读取输入:n为节点数,m为边数// 为每条边创建对象,包含u, v, w属性edges = []for _ in range(m):    u, v, w = 读取输入    edges.append( (w, u, v) )// 间接排序:根据边的权重对r数组进行排序(避免直接操作边数组)r = list(range(m))w = [e[0] for e in edges]// Filmsort:间接排序def cmp(i, j):    if edges[i][0] < edges[j][0]:        return -1    return 1sort(r, key=cmp)edges_sorted = [ (w[i], u[i], v[i]) for i in r ]父 = [i for i in range(n + 1)]rank = [1] * (n + 1)def find(u):    while 父[u] != u:        father = parent[u]        u = father    return udef union(u, v):    u_root = find(u)    v_root = find(v)    if u_root == v_root:        return False    if rank[u_root] < rank[v_root]:        parent[u_root] = v_root        rank[v_root] += rank[u_root]    else:        parent[v_root] = u_root        rank[u_root] += v_root    return Truemst = []sum = 0for w, u, v in edges_sorted:    if parent[u] != parent[v]:        union(u, v)        sum += w        mst.append( (u, v) )    if len(mst) == n - 1:        breakreturn mst, sum

    两者的区别

    • Prim算法基于松弛操作,通过每次选择一个点进行扩展,适合直接处理边权矩阵(如图矩阵)。
    • Kruskal算法基于边排序,使用并查集来维护连通分量,适合处理边列表较多或边权重复杂的场景。

    常见题型

    以下是一些经典的最少生成树问题:

  • 最小生成树的构造
  • 图是否连通
  • 图的直径
  • 边重复添加对最小生成树的影响
  • 边加权后的最小生成树

  • 通过掌握这两种方法,你可以任意处理给定的图,将其转化为最小生成树并计算权重总和。这对你的学习和解决实际问题具有重要意义。

    转载地址:http://vcfmz.baihongyu.com/

    你可能感兴趣的文章
    MYSQL一直显示正在启动
    查看>>
    MySQL一站到底!华为首发MySQL进阶宝典,基础+优化+源码+架构+实战五飞
    查看>>
    MySQL万字总结!超详细!
    查看>>
    Mysql下载以及安装(新手入门,超详细)
    查看>>
    MySQL不会性能调优?看看这份清华架构师编写的MySQL性能优化手册吧
    查看>>
    MySQL不同字符集及排序规则详解:业务场景下的最佳选
    查看>>
    Mysql不同官方版本对比
    查看>>
    MySQL与Informix数据库中的同义表创建:深入解析与比较
    查看>>
    mysql与mem_细说 MySQL 之 MEM_ROOT
    查看>>
    MySQL与Oracle的数据迁移注意事项,另附转换工具链接
    查看>>
    mysql丢失更新问题
    查看>>
    MySQL两千万数据优化&迁移
    查看>>
    MySql中 delimiter 详解
    查看>>
    MYSQL中 find_in_set() 函数用法详解
    查看>>