最小生成树概念及kruskal和prim算法的JAVA实现

本文详细介绍了图论中的最小生成树概念,包括Kruskal和Prim两种经典算法的原理与Java实现。最小生成树在构建成本最低的通信网络等问题中有广泛应用。Kruskal算法通过按权重排序边并逐步连接不在同一棵树上的顶点,Prim算法则从一个顶点开始逐步扩大生成树,每次添加与当前树连接的最小权重边。这两种算法各有优势,适用于不同的图结构。

最小生成树概念及kruskal和prim算法的JAVA实现

一. 图和树的基本概念

1.  **图的定义**:由顶点(vertex)和边(edge)组成。顶点就是代表对象,因为有时候题不会直接给顶点,而是某种对象,直接看成顶点即可。我们使用链接两顶点之间的线段来表示。顶点的集合V,边的集合是E,所以图记为G
    = (V,E), 连接两点u和v的边用e=(u,v)表示。

在这里插入图片描述

2.  **全连通图**:任意两点之间都有路径连接的图叫做连通图。

在这里插入图片描述

3.  **路径和圈**:两个顶点之间如果有边连接,那么就视为两个顶点相邻。相邻顶点的序列称为路径。起点和终点重合的路径叫做圈。

在这里插入图片描述
4. :树是一种特殊的无向连通图,即没有圈的无向连通图就是树,所以一棵树的边是顶点数-1。也就是说边数等于顶点数-1的无向连通图是树
在这里插入图片描述

注意:

  1. 森林:森林是一种特殊的非连通图,即没有圈非连通图就是森林,如下图:
    在这里插入图片描述

  2. DAG:没有圈的有向图,叫做DAG。对于每个顶点按照拓扑序列从左到右排列,那么所有的边都是从左指向右的。
    在这里插入图片描述
    二、 最小生成树的概念

    1. 生成树的理解:在给定一个无向连通图G=(V,E),通过不同方式删除多余的边(使得边数等于顶点数-1)可以得到不同的树,这些树都称为该无向连通图的生成树。生成树的任意两点都有路径连接

    2. 最小生成树的理解:一个给定的无向连通图,其所有和生成树中,所有边长权重之和为最小的生成树,该生成树称为最小生成树。(无向连通图的所有生成树中有一棵边的权值总和最小的生成树

    3. 学术定义:

在一给定的无向图G =
(V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v)
代表此的权重,若存在 T 为 E
子集(即)且为无圈图,使得的
w(T) 最小,则此 T 为 G 的最小生成树
在这里插入图片描述

最小生成树其实是最小权重生成树的简称。

三、 最小生成树的应用场景

  1. 成本最低问题

    1) 问题描述:假设要在n个城市之间建立通信联络网,则连通n个城市只需要n—1条线路。这时,自然会考虑这样一个问题,如何在最节省经费的前提下建立这个通信网。在每两个城市之间都可以设置一条线路,相应地都要付出一定的经济代价。n个城市之间,最多可能设置n(n-1)/2条线路,那么,如何在这些可能的线路中选择n-1条,以使总的耗费最少呢?
    2)问题分析(建立模型):可以用连通网来表示n个城市以及n个城市间可能设置的通信线路,其中网的顶点表示城市,边表示两城市之间的线路,赋于边的权值表示相应的代价。对于n个顶点的连通网可以建立许多不同生成树,每一棵生成树都可以是一个通信网。即无向连通图的生成树不是唯一的。连通图的一次遍历所经过的边的集合及图中所有顶点的集合就构成了该图的一棵生成树,对连通图的不同遍历,就可能得到不同的生成树。
    在这里插入图片描述
    可以证明,对于有n
    个顶点的无向连通图,无论其生成树的形态如何,所有生成树中都有且仅有n-1 条边

四、最小生成树的画法

对下面的图,通过画图的方式来求解最小生成树:
在这里插入图片描述

1)首先随便选择一个点,这里选择1点,以1为顶点画圈把1所涉及到的边全画上,可得三条边,权重分别为6、1、5,最小权重为1,如下图:
在这里插入图片描述

2)以1、3两个点为顶点画圈,把1、3两个点所涉及的边全圈上(除掉上面已经确定的权重为1的边),可得权重为6、5、6、4、5、5这6条边,权重最小的是4。如下图:
在这里插入图片描述
3)依此类推,以1、3、6三个点画圈,可知经过的权重为6、5、6、6、2、5、5,最小权重为2,连接圈6和圈4。
在这里插入图片描述
4)重复以上步骤,以步骤三得到的图为顶点继续画线,得到如下的图。
在这里插入图片描述

5)最终得到以下的图,就是最小生成树。
在这里插入图片描述五、最小生成树实现算法

(一)kruskal算法

1、实现原理:

假设全连通图的每个节点都是一棵树,共组成n棵树的森林,将每条边以权重从小到大排序,选取最小的边,如果两个顶点不在一棵树上(即两个节点的根不相同),则把他们关联起来(即将他们的根设置成相同)组成一个树,当这棵树的边长达到n-1时,将可得到该全连通图的最小生成树

2、实现伪代码:

  1. 将实际问题转换成以边的数据结构来存储,边的数据结构可以为(p1,p2,cost),并保存在数组或者队列

  2. 对边数组(队列)进行以升序进行排序:最优复杂度为O(logn)

  3. 构建一个各节点的根节点数组father[],初始一个值;

  4. 对排序好的数组进行遍历,动作如下:最优复杂度为O(n)

    1. 求出所选的边的两个节点的根节点

    2. 判断两个节点的根节点是否相等

      1. 如果相同,则不放弃这条边

      2. 如果不相同,则为被选中的边(根据实际问题进行代码处理),同时把两个节点的根设置成相等,且被选的边加1

    3. 选择下一条边

3、实现代码

方式一:

  1. 对边进行排序sort()
    在这里插入图片描述

  2. 初始化各节点的根节点编号不一样,默认等于节点索引号i
    在这里插入图片描述

  3. for函数遍历所有的边,通过find()函数判断该边上的两个节点的根节点编号是否相等;如果相等,意味着这条边为同根的节点,不处理;如果不相等,则表示这条边的节点被选中,同时通过uninon()函数设置这两个节点的根节点相同;
    在这里插入图片描述

  4. 判断两个节点的根节点是否相等
    在这里插入图片描述

  5. 设置两个节点的根相等
    在这里插入图片描述
    方案二:

  6. 排序sort()
    在这里插入图片描述

  7. 初始化各节点的根节点为-1
    在这里插入图片描述

  8. 主函数通过while()循环来实现 :

选出一条边,判断这条边的两个节点的根是否相同,如不相同,则这条边被选中,并设置根节点一致;如相同,则放弃这条边,重新选择一条边进行判断。依此类推,直至遍历完所有边或者被选中的边已经达到n-1;
在这里插入图片描述

  1. 查找每个节点的根节点函数find()
    在这里插入图片描述
    (二)普里母prim算法:有线到点,适合边稠密。时间复杂度O(N^2)

假设G=(V,E)为连通图,其中V 为网图中所有顶点的集合,E
为网图中所有带权边的集合。

设置两个新的集合U 和T,其中集合U(顶点集) 用于存放G 的最小生成树中的顶点,集合T
(边集合)存放G 的最小生成树中的边。

T ,U的初始状态:令集合U 的初值为U={u1}(假设构造最小生成树时,从顶点u1
出发),集合T 的初值为T={}。

  1. Prim 算法的思想是:

  2. 从所有u∈U,v∈V-U 的边中,选取具有最小权值的边(u,v)∈E

  3. 将顶点v 加入集合U 中,将边(u,v)加入集合T 中

  4. 如此不断重复,直到U=V 时,最小生成树构造完毕,这时集合T
    中包含了最小生成树的所有边。

2、Prim 算法伪代码:其中用wuv 表示顶点u 与顶点v 边上的权值。

(1)U={u1},T={};

(2)while (U≠V)do

(u,v)=min{wuv;u∈U,v∈V-U }

T=T+{(u,v)}

U=U+{v}

(3)结束。

  1. JAVA代码实现

  2. 代码说明
    在这里插入图片描述

  3. prim算法实现函数
    在这里插入图片描述
    在这里插入图片描述

  4. main主函数
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值