最小生成树之Kruskal算法和Prim算法
依据图的深度优先遍历和广度优先遍历,能够用最少的边连接全部的顶点,并且不会形成回路。
这样的连接全部顶点并且路径唯一的树型结构称为生成树或扩展树。实际中。希望产生的生成树的全部边的权值和最小,称之为最小生成树。
常见的最小生成树算法有Kruskal算法和Prim算法。
Kruskal算法每次选取权值最小的边。然后检查是否增加后形成回路,假设形成回路则须要放弃。终于构成最小生成树。n个顶点的图最小生成树过程例如以下:
边的权值升序排序。
选取全部未遍历的边中权值最小的边,推断增加后是否形成回路,若形成回路,放弃之。又一次从未被遍历的边中选择。
反复上述步骤,直到选中n-1条边。
/*****************Kruskal算法********************/
struct Edge
{
int v1,v2;//顶点
int w;//边v1--v2权值
struct Edge *next;//指向下一条边
}
//h为按边的权值升序排序的单链表
int Kruskal(Edge *h, int *visited)
{
int edgenum = 0;//记录生成树中边的个数
int weight = 0;//权值和
Edge *p = h;
printf("最小生成树:(顶点1,顶点2,权值)\n"); while(edgenum != maximum)//maximum=顶点数,当边数=顶点数-1时结束
{
if(visited[p->v1] == 0 ||visited[p->v2]==0)
//新增边至少有一个顶点没有被訪问过
{
printf("(%d,%d,%d)->",p->v1,p->v2,p->w);
weight = weight + p->w; //权值和累加
visited[p->v1] = 1;
visited[p->v2] = 1;
edgenum++;//边数+1
}
p = p->next;
if(p==NULL)//无边可增加
{
printf("spanning tree fail\n");
break;
}
}
return weight;
}
Prim算法
相比于Kruskal选边生成,Prim算法选择顶点生成最小生成树。
从某个顶点v開始,列出顶点 v 全部邻接点的边 选择权值最小的边(vi-->vj)增加到最小生成树中,并标记该边已被訪问过。
再从vj開始 列出顶点vj全部邻接点的边,从中选择全部未被訪问过的边中权值最小的边 vj-->vk 增加到最小生成树中,并标记该边已被訪问过。
反复上述操作。直到找到n-1条边为止。
以下直接贴代码:
/*******************Prims算法******************/
struct Edge
{
int v1,v2;//顶点
int w;//边v1--v2权值
int marked;//标识该边是否已经被加入到最小生成树中
struct Edge *next;
}
//h为边节点构成的链表,index表示開始顶点
void Prim(Edge *h,int * visited, int index)
{
Edge *p,*min;//min每次指向剩余边中中权值最小且 与上一个边共享顶点v1
int i;
int edgenum =0;//已连接边数
int weight =0;//权值
int vertex;
min = (Edge*)malloc(sizeof(Edge));
/***加入第一条边*******/
min->w = h->w;//最小边权值初值(可随意指定但小于全部边的权值,当然比越大越好)
p = h;
while(p!=NULL)
{
if(p->v1 ==index && (p->w < min->w))
min = p; //找到以index开头 且权值最小的边结点
p = p->next;
}
min->marked = 1;//该边已被訪问
visited[min->v1] = 1;
visited[min->v2] = 1; //该边两个顶点被訪问过
edgenum++;
weight = min->w;
printf("(%d,%d,%d)->",min->v1,min->v2,min->w);//输出选中边
/***加入其余边*******/
while(edgenum != maximum)
{
min->w = h->w;
p = h;
while(p != NULL)
{
if(p->marked==0 && visited[p->v1]+visited[p->v2]==1)//边没有被訪问过 且有且仅仅有一个顶点被訪问,还有一顶点没有被訪问过
if(p->w < min->w)
min = p; //找到权值最小的边
p = p->next;
}
min->marked = 1;
visited[min->v1] =1;
visited[min->v2] =1;
edgenum++;
weight += min->w;
printf("(%d,%d,%d)->",min->v1,min->v2,min->w);
}
printf("\n总权值为:%d",weight);
}
最小生成树之Kruskal算法和Prim算法的更多相关文章
- Algorithm --> Kruskal算法和Prim算法
最小生成树之Kruskal算法和Prim算法 Kruskal多用于稀疏图,prim多用于稠密图. 根据图的深度优先遍历和广度优先遍历,可以用最少的边连接所有的顶点,而且不会形成回路.这种连接所有顶点并 ...
- 求最小生成树——Kruskal算法和Prim算法
给定一个带权值的无向图,要求权值之和最小的生成树,常用的算法有Kruskal算法和Prim算法.这两个算法其实都是贪心思想的使用,但又能求出最优解.(代码借鉴http://blog.csdn.net/ ...
- 最小生成数kruskal算法和prim算法
定义 连通图:在无向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该无向图为连通图. 强连通图:在有向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该有向图为强连通图. 连通网:在 ...
- 贪心算法-最小生成树Kruskal算法和Prim算法
Kruskal算法: 不断地选择未被选中的边中权重最轻且不会形成环的一条. 简单的理解: 不停地循环,每一次都寻找两个顶点,这两个顶点不在同一个真子集里,且边上的权值最小. 把找到的这两个顶点联合起来 ...
- 最小生成树的两种方法(Kruskal算法和Prim算法)
关于图的几个概念定义: 连通图:在无向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该无向图为连通图. 强连通图:在有向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该有向图为强连 ...
- 最小生成树(次小生成树)(最小生成树不唯一) 模板:Kruskal算法和 Prim算法
Kruskal模板:按照边权排序,开始从最小边生成树 #include<algorithm> #include<stdio.h> #include<string.h> ...
- Prim算法和Dijkstra算法的异同
Prim算法和Dijkstra算法的异同 之前一直觉得Prim和Dijkstra很相似,但是没有仔细对比: 今天看了下,主要有以下几点: 1: Prim是计算最小生成树的算法,比如为N个村庄修路,怎么 ...
- mahout中kmeans算法和Canopy算法实现原理
本文讲一下mahout中kmeans算法和Canopy算法实现原理. 一. Kmeans是一个很经典的聚类算法,我想大家都非常熟悉.虽然算法较为简单,在实际应用中却可以有不错的效果:其算法原理也决定了 ...
- 使用Apriori算法和FP-growth算法进行关联分析
系列文章:<机器学习实战>学习笔记 最近看了<机器学习实战>中的第11章(使用Apriori算法进行关联分析)和第12章(使用FP-growth算法来高效发现频繁项集).正如章 ...
随机推荐
- centos中pyenv安装
1.先安装git yum install git -y 2.克隆pyenv到本地 git clone git://github.com/yyuu/pyenv.git .pyenv 或自动安装 curl ...
- 素数路(prime) (BFS)
问题 C: 素数路(prime) 时间限制: 1 Sec 内存限制: 64 MB提交: 8 解决: 5[提交][状态][讨论版] 题目描述 已知一个四位的素数,要求每次修改其中的一位,并且要保证修 ...
- 微信小程序开发教程(三)项目目录及文件构成
第二章我们已经创建了一个Hello WXapplet示例小程序.我们从文件目录结构来了解Hello WXapplet项目的构成. 目录结构显示,在小程序项目的根目录下面包含3个app开头的文件(app ...
- CodeForces - 981G Magic multisets
假设我们可以对每个位置快速维护一个数组,记录每个位置有哪些值是已经出现了的,哪些值是没有出现的,这样就可以决定修改的时候到底是 *2 还是 +1了. 但是很可惜,并不存在功能这么强大的数组,所以只能另 ...
- POJ 2345 Central heating(高斯消元)
[题目链接] http://poj.org/problem?id=2345 [题目大意] 给出n个开关和n个人,每个人可以控制一些开关,现在所有的开关都是关着的 一个指令可以让一个人掰动所有属于他控制 ...
- 【分块】bzoj2724 [Violet 6]蒲公英
分块,离散化,预处理出: ①前i块中x出现的次数(差分): ②第i块到第j块中的众数是谁,出现了多少次. 询问的时候,对于整块的部分直接获得答案:对于零散的部分,暴力统计每个数出现的次数,加上差分的结 ...
- 【暴力】bzoj3713 [PA2014]Iloczyn
没什么好说的. #include<cstdio> using namespace std; typedef long long ll; ]; int main() { scanf(]=; ...
- python3 开发面试题(%s和format的区别)5.31
在格式化字符串中有两种方法: 1.%s 2.format 大家常用的是哪一种方法?为什么要用你选的这种方法? 我们先看一个例子: 首先我们定义一个我军需要击杀的恐怖分子的地理坐标为 c=(128,12 ...
- 在energia中添加新的库
很多时候energia提供的库不能够满足我们的需要,这个时候我们就要自己添加库到energia中.方法如下: 在energia目录下找到hardware目录 选择对应的单片机型号文件夹进入 进入lib ...
- UML及其StarUML介绍
http://blog.csdn.net/monkey_d_meng/article/details/6005764 http://www.uml.org.cn/oobject/200901203.a ...