博客
关于我
最小生成树算法——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中interactive_timeout和wait_timeout的区别
    查看>>
    mysql中int、bigint、smallint 和 tinyint的区别、char和varchar的区别详细介绍
    查看>>
    mysql中json_extract的使用方法
    查看>>
    mysql中json_extract的使用方法
    查看>>
    mysql中kill掉所有锁表的进程
    查看>>
    mysql中like % %模糊查询
    查看>>
    MySql中mvcc学习记录
    查看>>
    mysql中null和空字符串的区别与问题!
    查看>>
    MySQL中ON DUPLICATE KEY UPDATE的介绍与使用、批量更新、存在即更新不存在则插入
    查看>>
    MYSQL中TINYINT的取值范围
    查看>>
    MySQL中UPDATE语句的神奇技巧,让你操作数据库如虎添翼!
    查看>>
    Mysql中varchar类型数字排序不对踩坑记录
    查看>>
    MySQL中一条SQL语句到底是如何执行的呢?
    查看>>
    MySQL中你必须知道的10件事,1.5万字!
    查看>>
    MySQL中使用IN()查询到底走不走索引?
    查看>>
    Mysql中使用存储过程插入decimal和时间数据递增的模拟数据
    查看>>
    MySql中关于geometry类型的数据_空的时候如何插入处理_需用null_空字符串插入会报错_Cannot get geometry object from dat---MySql工作笔记003
    查看>>
    mysql中出现Incorrect DECIMAL value: '0' for column '' at row -1错误解决方案
    查看>>
    mysql中出现Unit mysql.service could not be found 的解决方法
    查看>>
    mysql中出现update-alternatives: 错误: 候选项路径 /etc/mysql/mysql.cnf 不存在 dpkg: 处理软件包 mysql-server-8.0的解决方法(全)
    查看>>