无向带权图的最小生成树算法——Prim及Kruskal算法思路

边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权。

最小生成树(MST):权值最小的生成树。

生成树和最小生成树的应用:要连通n个城市需要n-1条边线路。可以把边上的权值解释为线路的造价。则最小生成树表示使其造价最小的生成树。

构造网的最小生成树必须解决下面两个问题:

1、尽可能选取权值小的边,但不能构成回路;

2、选取n-1条恰当的边以连通n个顶点;

MST性质:假设G=(V,E)是一个连通网,U是顶点V的一个非空子集。若(u,v)是一条具有最小权值的边,其中u∈U,v∈V-U,则必存在一棵包含边(u,v)的最小生成树。

1.prim算法

基本思想:假设G=(V,E)是连通的,TE是G上最小生成树中边的集合。算法从U={u0}(u0∈V)、TE={}开始。重复执行下列操作:

在所有u∈U,v∈V-U的边(u,v)∈E中找一条权值最小的边(u0,v0)并入集合TE中,同时v0并入U,直到V=U为止。

此时,TE中必有n-1条边,T=(V,TE)为G的最小生成树。

Prim算法的核心:始终保持TE中的边集构成一棵生成树。

注意:prim算法适合稠密图,其时间复杂度为O(n^2),其时间复杂度与边得数目无关。

看了上面一大段文字是不是感觉有点晕啊,为了更好理解我在这里举一个例子,示例如下:

(1)图中有6个顶点v1-v6,每条边的边权值都在图上;在进行prim算法时,我先随意选择一个顶点作为起始点,当然我们一般选择v1作为起始点,好,现在我们设U集合为当前所找到最小生成树里面的顶点,TE集合为所找到的边,现在状态如下:

U={v1}; TE={};

(2)现在查找一个顶点在U集合中,另一个顶点在V-U集合中的最小权值,如下图,在红线相交的线上找最小值。

通过图中我们可以看到边v1-v3的权值最小为1,那么将v3加入到U集合,(v1,v3)加入到TE,状态如下:

U={v1,v3}; TE={(v1,v3)};

(3)继续寻找,现在状态为U={v1,v3}; TE={(v1,v3)};在与红线相交的边上查找最小值。

我们可以找到最小的权值为(v3,v6)=4,那么我们将v6加入到U集合,并将最小边加入到TE集合,那么加入后状态如下:

U={v1,v3,v6}; TE={(v1,v3),(v3,v6)}; 如此循环一下直到找到所有顶点为止。

(4)下图像我们展示了全部的查找过程:

克鲁斯卡尔(Kruskal)算法(只与边相关)

算法描述:克鲁斯卡尔算法需要对图的边进行访问,所以克鲁斯卡尔算法的时间复杂度只和边又关系,可以证明其时间复杂度为O(eloge)。

算法过程:

1.将图各边按照权值进行排序

2.将图遍历一次,找出权值最小的边,(条件:此次找出的边不能和已加入最小生成树集合的边构成环),若符合条件,则加入最小生成树的集合中。不符合条件则继续遍历图,寻找下一个最小权值的边。

3.递归重复步骤1,直到找出n-1条边为止(设图有n个结点,则最小生成树的边数应为n-1条),算法结束。得到的就是此图的最小生成树。

克鲁斯卡尔(Kruskal)算法因为只与边相关,则适合求稀疏图的最小生成树。而prime算法因为只与顶点有关,所以适合求稠密图的最小生成树。

而kruskal算法的时间复杂度为O(eloge)跟边的数目有关,适合稀疏图。

算法描述:克鲁斯卡尔算法需要对图的边进行访问,所以克鲁斯卡尔算法的时间复杂度只和边又关系,可以证明其时间复杂度为O(ElogE)。

算法过程:

1.将图各边按照权值进行排序

2.将图遍历一次,找出权值最小的边,(条件:此次找出的边不能和已加入最小生成树集合的边构成环),若符合条件,则加入最小生成树的集合中。不符合条件则继续遍历图,寻找下一个最小权值的边。

3.递归重复步骤1,直到找出n-1条边为止(设图有n个结点,则最小生成树的边数应为n-1条),算法结束。得到的就是此图的最小生成树。判断是否构成环:《算法导论》提供的一种方法是采用一种"不相交集合数据结构",也就是并查集了。核心内容就是如果某两个节点属于同一棵树,那么将它们合并后一定会形成回路。

克鲁斯卡尔(Kruskal)算法因为只与边相关,则适合求稀疏图的最小生成树。而prime算法因为只与顶点有关,所以适合求稠密图的最小生成树。

时间: 2024-10-09 07:14:32

无向带权图的最小生成树算法——Prim及Kruskal算法思路的相关文章

用无向带权图实现校园导航系统

学校数据结构的课程实验之一. 用到的数据结构:无向带权图 用到的算法:Floyd最短路径算法,深度优先搜索(递归实现) 需求分析: 设计一个校园导航程序,为访客提供各种信息查询服务: 1. 以图中各顶点表示校内各单位地点,存放单位名称,代号,简介等信息:以边表示路径,存放路径长度等相关信息. 2. 图中任意单位地点相关信息的查询. 3. 图中任意单位的问路查询,即查询任意两个单位之间的一条最短的路径. 2. 从图中任意单位地点出发的一条深度优先遍历路径. 主函数: 1 #include <ios

有向无环带权图的最短路径及长度

给定一个有向无环图的拓扑序列,获取这个序列从起点到序列最后一点的最短路径. 起点默认为0点(顶点为0,1,2...和数组索引对应),序列通过拓扑排序获取. 下面给出实现,首先是对一个有向无环图进行拓扑排序的类. package graphics.dag.topologicalsort; /** * 获取一个拓扑序列 * @author zhangxinren * */ public class TopologicalSort { // 每条边的入度 private static int[] in

图的最小生成树(一)—Kruskal算法

求下图的最小生成树: 数据给出如下: 第一行有两个数,n表示n个城市,m表示m条道路,接下来的m行,每行三个数a,b,c表示城市a到城市b的路程c. 现在需要解决的是,要求要最少的边让图连通(任意两点之间可以互相到达).要想让n个顶点的图连通,那么至少需要n-1条边.其实这里就是求一个图的最小生成树. 基本思路: 首先按照边的权值进行从小到大排序,每次从剩余的边中选择权值较小且边的两个顶点不在同一个集合内(将所有的顶点放入一个并查集中,判断两个顶点是否连通,只需判断两个顶点是否在同一个集合中,即

【图论】【最小生成树】Prim和Kruskal算法

在数据结构的教材上,讲到的图的最小生成树算法有两种,一种是Prim(普利姆)算法,一种是Kruskal(克鲁斯卡尔)算法. 两种算法的生成思路有所不同: Prim算法: 算法思想: 算法思想就是每次找到一个距离生成集合最近的点,加入,然后更新距离剩余点之间的距离,继续迭代. 算法步骤: 1.任意选择一个点作为起点,将该点标记为已加入最小生成树,使用一个数组表示该点已加入,join[i] = 1表示i点已加入集合: 2.将最小生成树集合作为整体,计算到其他未加入该集合的点(jion[i] == 0

算法10 之带权图

上一节我们已经看到了图的边可以有方向,这一节里,我们将探讨边的另一个特性:权值.例如,如果带权图的顶点代表城市,边的权可能代表城市之间的距离,或者城市之间的路费,或者之间的车流量等等. 带权图归根究底还是图,上一节那些图的基本操作,例如广度优先搜索和深度优先搜索等都是一样的,在这一节里,我们主要来探讨一下带权图的最小生成树最短路径问题. 最小生成树问题 首先探讨下最小生成树问题,它与上一节所提到的最小生成树不同.上一节的最小生成树是个特例,即所有边的权值都一样.那么算法如何设计呢?建议用优先级队

Java数据结构——带权图

带权图的最小生成树——Prim算法和Kruskal算法 带权图的最短路径算法——Dijkstra算法 package graph; // path.java // demonstrates shortest path with weighted, directed graphs 带权图的最短路径算法 // to run this program: C>java PathApp ////////////////////////////////////////////////////////////

带权图的最短路径算法(Dijkstra)实现

一,介绍 本文实现带权图的最短路径算法.给定图中一个顶点,求解该顶点到图中所有其他顶点的最短路径 以及 最短路径的长度.在决定写这篇文章之前,在网上找了很多关于Dijkstra算法实现,但大部分是不带权的.不带权的Dijkstra算法要简单得多(可参考我的另一篇:无向图的最短路径算法JAVA实现):而对于带权的Dijkstra算法,最关键的是如何“更新邻接点的权值”.本文采用最小堆主辅助,以重新构造堆的方式实现更新邻接点权值. 对于图而言,存在有向图和无向图.本算法只需要修改一行代码,即可同时实

邻接矩阵表示有向带权图

#include <stdio.h> #include <stdlib.h> #include <string.h> typedef char VertexType[5]; //存储顶点值 #define MaxSize 50 #define INIT 10000 typedef struct //邻接矩阵,存储弧的信息 {     int adj; }ArcNode,AdjMatrix[MaxSize][MaxSize]; typedef struct   //图的类

复制无向带环图

Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. OJ's undirected graph serialization: Nodes are labeled uniquely. We use # as a separator for each node, and , as a separator for node label and each neigh