数据结构与算法 -- 图的应用之最小生成树问题

前言

  前面对 图的存储 和 **图的遍历(广度优先/深度优先)**做了简单的学习和了解,本篇文章,学习一下最小生成树的问题,以及对应解决这个问题的两种算法 普里姆算法克鲁斯卡尔算法

1.最小生成树问题

首先看下面一道面试题:

假设目前有N个顶点,每个顶点连接的路径不一样,设计一个算法,快速查找出能覆盖所有顶点的路径。

其实这个问题并不是求解两点之间的最短路径,而是设计一个路线,能覆盖所有的顶点。

如下连通图:

那么覆盖所有顶点的路径有一下几种

  • 方法一

    V0 ——> V5 ——> V4 --> V3 --> V2 -->V1 -->V8 --> V6 -->V7

    权重:11 + 26 + 20 + 22 + 18 + 21 + 24 + 19 = 161

  • 方案二

    V2 ——> V8 ——> V1 --> V0 --> V5 -->V6 -->V7 --> V3 -->V4
    权重:8 + 12 + 10 + 11 + 17 + 19 + 16 + 7 = 100

  • 方案三

    权重:8 + 12 + 10 + 11 + 16 + 19 + 16 + 7 = 99

由此可以看出,方法三是最优的方案,这就是最小生成树。

最小生成树:把构成连通网的最小代价的生成树称之为最小生成树。即假设有N个顶点,用N-1条边,连接所有顶点,而且权重的和最小的路径。

2.最小生成树求解(普里姆(Prim)算法)

普里姆算法思路:

1. 定义两个数组,adjvew 用来保存相关顶点下标,lowcost 保存顶点之间的权值。
2. 初始化两个数组,将与 V0 相关的 V1-V8 的所有顶点的权值赋值给 lowcost
    adjvew[1-8],都赋值为 0,表示都是与 V0 相关的顶点(后面循环修改)
3. 循环 lowcost 数组,根据权值,找到权值最新的顶点的下标 k
4. 更新 lowcost 数组
5. 循环所有顶点,找到与下标为 k 的顶点,有关系的顶点,并更新 lowcost  数组和 adjvew 数组


注意:
更新 lowcost 数组的条件
1. 与下标为 k 的顶点之间有连接
2. 当前下标为 j 的顶点是否加入最小生成树
3. 下标为 k 的顶点与下标为 j 的顶点的权值比较,小于,则更新,
    简单说就是要比较之前存储的权值,小于,则更新。

接下来,我们详细的解析一下上面的思路:

  • 初始化 lowcostadjvew

lowcost 数组(将与 V0 相关的 V1-V8 的所有顶点的权值赋值给 lowcost

0 1 2 3 4 5 6 7 8
0 10 11

默认将V0加入到最小生成树中,lowcost[0] = 01011 表示顶点V0 连接顶点V1V5的权值。

adjvew 数组(都赋值为 0,表示都是与 V0 相关的顶点)

0 1 2 3 4 5 6 7 8
0 0 0 0 0 0 0 0 0

然后开始循环(从 i = 1 开始,默认第一个已经加入最小树)

  • 第一次循环 i = 1

    由上面的表格看出,10 是最小的权值,

    此时,k = 1,在lowcost数组中10最小。且满足更新 lowcost 数组的三个条件,

    所以,lowcost[1] = 0, 表示 V1 已经加入最小生成树,并打印信息

    lowcost 数组

    0 1 2 3 4 5 6 7 8
    0 0 11

    然后,循环所有顶点,找到下标为k顶点各边权值小于此前这些顶点未被加入生成树权值,然后更新lowcost 数组和adjvew 数组

      V2 未加入最小生成树,且权值 18 < ∞,lowcost【2】= 18,adjvew【2】= 1
      V8 未加入最小生成树,且权值 12 < ∞,lowcost【8】= 12,adjvew【8】= 1
      V6 未加入最小生成树,且权值 16 < ∞,lowcost【6】= 16,adjvew【6】= 1
    

    lowcost 数组

    0 1 2 3 4 5 6 7 8
    0 0 18 11 16 12

    adjvew 数组(都赋值为 0,表示都是与 V0 相关的顶点)

    0 1 2 3 4 5 6 7 8
    0 0 1 0 0 0 1 0 1

    18,16,12对应V2、V6、V8,是针对V1相关的顶点,

    1 是因为 k = 1,表示与V1相连的顶点是V2、V6、V8

  • 第二次循环 i = 2

    lowcost 中找到 权值最小 11j = 5,便是 k = 5

    所以,lowcost[5] = 0,加入到最小生成树中,并打印信息

    然后,循环所有顶点,找到下标为k = 5顶点各边权值小于此前这些顶点未被加入生成树权值,然后更新lowcost 数组和adjvew 数组

      V6 未加入最小生成树,且权值 17 > 16,不更新
      V4 未加入最小生成树,且权值 26 < ∞,lowcost【4】= 26,adjvew【4】= 5
      V3 未加入最小生成树,且权值 ∞  < ∞,不更新
    

    此时,lowcost 数组

    0 1 2 3 4 5 6 7 8
    0 0 18 26 0 16 12

    adjvew 数组(都赋值为 0,表示都是与 V0 相关的顶点)

    0 1 2 3 4 5 6 7 8
    0 0 1 0 5 0 1 0 1

    1 ,表示与V1相连的顶点V2、V6、V8

    5 是因为 k = 5,表示与V5相连的顶点是V4

  • 第三次循环 i = 3

    lowcost 中找到 权值最小12j = 8,便是 k = 8

    所以,lowcost[8] = 0,加入到最小生成树中,并打印信息

    然后,循环所有顶点,找到下标为k = 8顶点各边权值小于此前这些顶点未被加入生成树权值,然后更新lowcost 数组和adjvew 数组

      V2 未加入最小生成树,且权值 8 < 18,lowcost【2】= 8,adjvew【2】= 8
      V3
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值