博客
关于我
最小生成树算法——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 优化 or
    查看>>
    mysql 优化器 key_mysql – 选择*和查询优化器
    查看>>
    MySQL 优化:Explain 执行计划详解
    查看>>
    Mysql 会导致锁表的语法
    查看>>
    mysql 使用sql文件恢复数据库
    查看>>
    mysql 修改默认字符集为utf8
    查看>>
    Mysql 共享锁
    查看>>
    MySQL 内核深度优化
    查看>>
    mysql 内连接、自然连接、外连接的区别
    查看>>
    mysql 写入慢优化
    查看>>
    mysql 分组统计SQL语句
    查看>>
    Mysql 分页
    查看>>
    Mysql 分页语句 Limit原理
    查看>>
    MySql 创建函数 Error Code : 1418
    查看>>
    MySQL 创建新用户及授予权限的完整流程
    查看>>
    mysql 创建表,不能包含关键字values 以及 表id自增问题
    查看>>
    mysql 删除日志文件详解
    查看>>
    mysql 判断表字段是否存在,然后修改
    查看>>