图——图的Kruskal法最小生成树实现
1,最小生成树的特征:

1,选取的边是图中权值较小的边;
2,所有边连接后不构成回路;
2,prim 算法是以顶点为核心的,最下生成树最大的特征是边,但 prim 算法非要以顶点为核心来进行,有些复杂和难以理解;
3,既然最小生成树关心的是如何选择 n - 1 条边,那么是否可以直接以边为核心进行算法设计?
4,简单尝试:

1,由 4 个顶点构成的图,选择 3 条权值最小的边;
2,还要设法避免回路;
5,需要解决的问题:

1,如何判断新选择的边与已选择的边是否构成回路?
6,技巧:前驱标记数组(避开新加入边造成回路问题)
1,定义数组:Array<int> p(vCount());
2,定义数组元素的意义:
1,p[n] 表示顶点 n 在边的连接通路上的另一端顶点;
3,前驱标记数组究竟是怎么来的?
7,最小生成树算法的核心步骤(Kruskal):
1,定义前驱标记数组:Array<int> p(vCount());
2,获取当前图中的所有边,并存储于 edges 数组中;
3,对数组 deges 按照权值进行排序;
4,利用 p 数组在 edges 数组中选择前 n - 1 不构成回路的边;
8,Kruskal 算法流程:

9,关键的 find 查找函数:

10,最小生成树算法 Kruskal (克鲁斯卡)实现:
/* 最小、大生成树的 kruskal 算法 */
SharedPointer< Array< Edge<E> > > kruskal(const bool MINMUM = true)
{
LinkQueue< Edge<E> > ret; // 返回的队列
SharedPointer< Array< Edge<E> > > edges = getUndirectedEdges(); // 将无相图中的所有边都拿到
DynamicArray<int> p(vCount()); // 前驱标记数组 /* 设置前驱标记值 */
for(int i=; i<p.length(); i++)
{
p[i] = -;
} /* 对边数组排序 */
Sort::Shell(*edges, MINMUM); // 第二个参数对边进行从大到小的次序排序,用来生成最大生成树 /* 进入循环,挑选边 */
for(int i=; (i<edges->length()) && (ret.length() < (vCount()-)); i++) // 最多循环边的个数次,且如果边很多但已经有 N - 1 条边被选择了,那么结束循环
{
int b = find(p, (*edges)[i].b); // 在前驱标记数组中查找挑选的边的两个顶点
int e = find(p, (*edges)[i].e); // 前驱标记数组用于判断新选择的边是否会造成回路 if( b != e) // 相等会构成回路
{
p[e] = b; // 修改前驱标记数组 ret.add((*edges)[i]); // 将这条边加入结果集合中去
}
} if( ret.length() != (vCount()-) ) // 判断边是否够,不够就不能构成最小生成树
{
THROW_EXCEPTION(InvalidOperationException, "No enough edges for Kruskal operation ...");
} return toArray(ret); // 将结果转换为数组
}
11,Kruskal 算法测试代码:
#include <iostream>
#include "MatrixGraph.h"
#include "ListGraph.h" using namespace std;
using namespace DTLib; template< typename V, typename E >
Graph<V, E>& GraphEasy()
{
static MatrixGraph<, V, E> g; g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , ); return g;
} template< typename V, typename E >
Graph<V, E>& GraphComplex()
{
static ListGraph<V, E> g(); g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , ); return g;
} int main()
{
Graph<int, int>& g = GraphEasy<int, int>();
SharedPointer< Array< Edge<int> > > sa = g.kruskal(); int w = ; for(int i=; i<sa->length(); i++)
{
w += (*sa)[i].data; cout << (*sa)[i].b << " " << (*sa)[i].e << " " << (*sa)[i].data << endl;
} cout << "Weight: " << w << endl; return ;
}
13,小结:
1,Prim 算法以顶点为核心寻找最小生成树,不够直接;
2,Kruskal 算法以边为核心寻找最小生成树,直观简单;
3,Kruskal 算法中的关键是前驱标记数组的使用;
4,前驱标记数组用于判断新选择的边是否会造成回路;
图——图的Kruskal法最小生成树实现的更多相关文章
- matlab学习——04图与网络(最短路,最小生成树,最大流)
04图与网络 1.最短路 (1) 自己写的dijstra算法 format compact; clc,clear all a=zeros(6); a(1,2)=50;a(1,4)=40;a(1,5)= ...
- c/c++ 图的创建及图的相关函数(链表法)
c/c++ 图的创建及图的相关函数(链表法) 图的概念 图由点和线组成 知道了图中有多少个点,和哪些点之间有线,就可以把一张图描绘出来 点之间的线,分有方向和无方向 创建图 创建图,实际就是创建出节点 ...
- 图——图的Prim法最小生成树实现
1,运营商的挑战: 1,在下图标出的城市间架设一条通信线路: 2,要求: 1,任意两个城市间都能够通信: 2,将架设成本降至最低: 2,问题抽象: 1,如何在图中选择 n - 1 条边使得 n 个顶点 ...
- 【算法导论】最小生成树之Kruskal法
在图论中,树是指无回路存在的连通图.一个连通图的生成树是指包含了所有顶点的树.如果把生成树的边的权值总和作为生成树的权,那么权值最小的生成树就称为最小生成树.因为最小生成树在实际中有很多应用,所以我们 ...
- 图的Prim,Kruskal,Dijkstra,Floyd算法
代码部分有点问题,具体算法没问题, 最近期末考,要过段时间才会修改 //邻接矩阵,具体情况看上一篇的图的实现template<class T>class MGraph {public: ...
- 图——图的Floyd法最短路径实现
1,Dijkstra 算法一次性求得起始顶点到所有其它顶点的最短路径,如果想要求解任意两个顶点之间的最短路径,可将图中顶点作为起始顶点执行 n 次 Dijkstra 算法就可以了: 2,可能解决方案: ...
- 图——图的Dijkstra法最短路径实现
1,最短路径的概念: 1,从有向图中某一顶点(起始顶点)到达另一顶点(终止顶点)的路径中,其权值之和最小的路径: 2,问题的提法: 1,给定一个带权有向图 G 与起始顶点 v,求从 v 到 G 中其它 ...
- #图# #最大生成树# #kruskal# ----- OpenJudge 799:Heavy Transportation
OpenJudge 799:Heavy Transportation 总时间限制: 3000ms 内存限制: 65536kB 描述BackgroundHugo Heavy is happy. Afte ...
- java用Kruskal实现最小生成树
今天更新这篇文章超级激动,因为我会最小生成树的算法了(其实昨天就开始研究了,只是昨天参加牛客网的算法比赛,结果又被虐了,好难过~) 最小生成树的算法,其实学了数据结构就会有一定的基础,Kruskal算 ...
随机推荐
- JAVA笔记28-正则表达式(补充、不重要)
一.Greedy(贪婪的)尽可能多的匹配,Reluctant(不情愿的)尽可能少的匹配.Possessive(独占的)不常用. Greedy 数量词 X? X,一次或一次也没有 X* X,零次或多次 ...
- GDOI2017总结
前言 大概在两个星期前,由于会有一堆人因为限人数的问题而被卡掉,当时那个人心惶惶啊,搞到我们心惊胆战,茶饭不安. 话说某日,jacky36当众表示,辣鸡余可灿,把我卡掉啦,B~(屏蔽不良言语).余可灿 ...
- 解决 Failed to start LSB: Bring up/down networking 问题
我用的是虚拟机,一换网络环境虚拟机的ip就没有了,重启网上就报Failed to start LSB: Bring up/down networking错误.网上查了一圈说什么HWADDR有问题,改了 ...
- 开发一个chrome插件:将百度搜索热点屏蔽掉!
每次百度搜索,搜索结果的右边总是出现些乱七八糟的搜索热点(推的都是些什么玩意,高校替课和我有毛关系,几个悲伤的热点我用星号顶掉了). 强迫症想把它隐藏掉,我用的是chrome浏览器,受adblock( ...
- IDEA mapping箭头要怎么样设置哈(Free MyBatis插件)
效果如下图: 当我们点击箭头的时候,会快速切换到我们相关联的类位置,就不用再像以前一样还要去找 而 Free MyBatis是一款让我们操作更加方便的插件,你值得拥有哦~~~ idea 选择 File ...
- msyql 优化之五不要
1.尽量不要有空判断的语句,因为空判断将导致全表扫描,而不是索引扫描. 对于空判断这种情况,可以考虑对这个列创建数据库默认值 //空判断将导致全表扫描 select small_id from sma ...
- linux system函数引发的错误
转: https://my.oschina.net/renhc/blog/54582 先看一下问题 简单封装了一下system()函数: int pox_system(const char *cm ...
- Codeforces 919E Congruence Equation ( 数论 && 费马小定理 )
题意 : 给出数 x (1 ≤ x ≤ 10^12 ),要求求出所有满足 1 ≤ n ≤ x 的 n 有多少个是满足 n*a^n = b ( mod p ) 分析 : 首先 x 的范围太大了,所以使 ...
- [CSP-S模拟测试]:最小距离(最短路)
题目传送门(内部题97) 输入格式 第一行三个整数$n,m,p$,第二行$p$个整数$x_1\sim x_p$表示特殊点的编号.接下来$m$行每行三个整数$u,v,w$表示一条连接$u$和$v$,长度 ...
- 二分类算法的评价指标:准确率、精准率、召回率、混淆矩阵、AUC
评价指标是针对同样的数据,输入不同的算法,或者输入相同的算法但参数不同而给出这个算法或者参数好坏的定量指标. 以下为了方便讲解,都以二分类问题为前提进行介绍,其实多分类问题下这些概念都可以得到推广. ...