博客
关于我
最小生成树算法——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/

    你可能感兴趣的文章
    ms sql server 2008 sp2更新异常
    查看>>
    MS UC 2013-0-Prepare Tool
    查看>>
    MSBuild 教程(2)
    查看>>
    msbuild发布web应用程序
    查看>>
    MSB与LSB
    查看>>
    MSCRM调用外部JS文件
    查看>>
    MSCRM调用外部JS文件
    查看>>
    MSEdgeDriver (Chromium) 不适用于版本 >= 79.0.313 (Canary)
    查看>>
    MsEdgeTTS开源项目使用教程
    查看>>
    msf
    查看>>
    MSSQL数据库查询优化(一)
    查看>>
    MSSQL数据库迁移到Oracle(二)
    查看>>
    MSSQL日期格式转换函数(使用CONVERT)
    查看>>
    MSTP多生成树协议(第二课)
    查看>>
    MSTP是什么?有哪些专有名词?
    查看>>
    Mstsc 远程桌面链接 And 网络映射
    查看>>
    Myeclipse常用快捷键
    查看>>
    MyEclipse更改项目名web发布名字不改问题
    查看>>
    MyEclipse用(JDBC)连接SQL出现的问题~
    查看>>
    mt-datetime-picker type="date" 时间格式 bug
    查看>>