博客
关于我
最小生成树算法——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
    查看>>
    MTK Android 如何获取系统权限
    查看>>
    MySQL - 4种基本索引、聚簇索引和非聚索引、索引失效情况、SQL 优化
    查看>>
    MySQL - ERROR 1406
    查看>>
    mysql - 视图
    查看>>
    MySQL - 解读MySQL事务与锁机制
    查看>>
    MTTR、MTBF、MTTF的大白话理解
    查看>>
    mt_rand
    查看>>
    mysql -存储过程
    查看>>
    mysql /*! 50100 ... */ 条件编译
    查看>>
    mudbox卸载/完美解决安装失败/如何彻底卸载清除干净mudbox各种残留注册表和文件的方法...
    查看>>
    mysql 1264_关于mysql 出现 1264 Out of range value for column 错误的解决办法
    查看>>
    mysql 1593_Linux高可用(HA)之MySQL主从复制中出现1593错误码的低级错误
    查看>>
    mysql 5.6 修改端口_mysql5.6.24怎么修改端口号
    查看>>
    MySQL 8.0 恢复孤立文件每表ibd文件
    查看>>
    MySQL 8.0开始Group by不再排序
    查看>>
    mysql ansi nulls_SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON 什么意思
    查看>>
    multi swiper bug solution
    查看>>
    MySQL Binlog 日志监听与 Spring 集成实战
    查看>>