算法之prim算法
最小生成树是数据结构中图的一种重要应用,它的要求是从一个带权无向完全图中选择n-1条边并使这个图仍然连通(也即得到了一棵生成树),同时还要考虑使树的权最小。 prim算法就是一种最小生成树算法。
普里姆算法的基本思想:
从连通网N={V,E}中的某一顶点U0出发,选择与它关联的具有最小权值的边(U0,v),将其顶点加入到生成树的顶点集合U中。以后每一步从一个顶点在U中,而另一个顶点不在U中的各条边中选择权值最小的边(u,v),把它的顶点加入到集合U中。如此继续下去,直到网中的所有顶点都加入到生成树顶点集合U中为止。
下面举例说明下prim算法:
c语言实现如下:(使用邻接矩阵存储)
#include <stdio.h>
#include <malloc.h>
#define VERTEXNUM 6 void createGraph(int (*edge)[VERTEXNUM], int start, int end, int value);
void displayGraph(int (*edge)[VERTEXNUM]);
void prim(int (*edge)[VERTEXNUM], int (**tree)[VERTEXNUM], int startVertex, int* vertexStatusArr); int main(void){
//动态创建存放边的二维数组
int (*edge)[VERTEXNUM] = (int (*)[VERTEXNUM])malloc(sizeof(int)*VERTEXNUM*VERTEXNUM);
int i,j;
for(i=0;i<VERTEXNUM;i++){
for(j=0;j<VERTEXNUM;j++){
edge[i][j] = 0;
}
}
//存放顶点的遍历状态,0:未遍历,1:已遍历
int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);
for(i=0;i<VERTEXNUM;i++){
vertexStatusArr[i] = 0;
} printf("after init:\n");
displayGraph(edge);
//创建图
createGraph(edge,0,1,6);
createGraph(edge,0,3,5);
createGraph(edge,0,2,1);
createGraph(edge,1,2,5);
createGraph(edge,1,4,3);
createGraph(edge,2,4,6);
createGraph(edge,2,3,5);
createGraph(edge,2,5,4);
createGraph(edge,3,5,2);
createGraph(edge,4,5,6); printf("after create:\n");
displayGraph(edge);
//最小生成树
int (*tree)[VERTEXNUM] = NULL;
prim(edge, &tree, 0, vertexStatusArr);
printf("after generate tree:\n");
displayGraph(tree); free(edge);
free(tree);
return 0;
}
//创建图
void createGraph(int (*edge)[VERTEXNUM], int start, int end, int value){
edge[start][end] = value;
edge[end][start] = value;
}
//打印存储的图
void displayGraph(int (*edge)[VERTEXNUM]){
int i,j;
for(i=0;i<VERTEXNUM;i++){
for(j=0;j<VERTEXNUM;j++){
printf("%d ",edge[i][j]);
}
printf("\n");
}
} void prim(int (*edge)[VERTEXNUM], int (**tree)[VERTEXNUM], int startVertex, int* vertexStatusArr){
//申请存储树的内存
*tree = (int (*)[VERTEXNUM])malloc(sizeof(int)*VERTEXNUM*VERTEXNUM);
int i,j;
for(i=0;i<VERTEXNUM;i++){
for(j=0;j<VERTEXNUM;j++){
(*tree)[i][j] = 0;
}
}
//从顶点0开始,则顶点0就是已访问的
vertexStatusArr[0] = 1;
int least, start, end, vNum = 1;
//如果还顶点还没有访问完
while(vNum < VERTEXNUM){
least = 9999;
for(i=0;i<VERTEXNUM;i++){
//选择已经访问过的点
if(vertexStatusArr[i] == 1){
for(j=0;j<VERTEXNUM;j++){
//选择一个没有访问过的点
if(vertexStatusArr[j] == 0){
//选出一条value最小的边
if(edge[i][j] != 0 && edge[i][j] < least){
least = edge[i][j];
start = i;
end = j;
}
}
}
}
}
vNum++;
//将点设置为访问过
vertexStatusArr[end] = 1;
//将边加到树中
createGraph(*tree,start,end,least);
}
}
c语言实现如下:(使用邻接表存储)
#include <stdio.h>
#include <malloc.h>
#define VERTEXNUM 6
//存放顶点的邻接表元素
typedef struct edge{
int vertex;
int value;
struct edge* next;
}st_edge; void createGraph(st_edge** edge, int start, int end, int value);
void displayGraph(st_edge** edge);
void delGraph(st_edge** edge);
void prim(st_edge** edge, st_edge*** tree, int startVertex, int* vertexStatusArr); int main(void){
//动态创建存放边的指针数组
st_edge** edge = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);
int i;
for(i=0;i<VERTEXNUM;i++){
edge[i] = NULL;
}
//存放顶点的遍历状态,0:未遍历,1:已遍历
int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);
for(i=0;i<VERTEXNUM;i++){
vertexStatusArr[i] = 0;
} printf("after init:\n");
displayGraph(edge);
//创建图
//从顶点0到顶点1的边,值为6,一下类推
createGraph(edge,0,1,6);
createGraph(edge,0,3,5);
createGraph(edge,0,2,1);
createGraph(edge,1,2,5);
createGraph(edge,1,4,3);
createGraph(edge,2,4,6);
createGraph(edge,2,3,5);
createGraph(edge,2,5,4);
createGraph(edge,3,5,2);
createGraph(edge,4,5,6); printf("after create:\n");
displayGraph(edge); st_edge** tree = NULL;
//从edge从中生成最小树tree,从顶点0开始
prim(edge, &tree, 0, vertexStatusArr);
printf("after generate tree:\n");
displayGraph(tree); delGraph(edge);
edge = NULL; delGraph(tree);
tree = NULL; free(vertexStatusArr);
vertexStatusArr = NULL;
return 0;
}
//创建图
void createGraph(st_edge** edge, int start, int end, int value){
st_edge* newedge1 = (st_edge*)malloc(sizeof(st_edge));
newedge1->vertex = end;
newedge1->value = value;
newedge1->next = NULL;
st_edge** edge1 = edge + start;
while(*edge1 != NULL){
edge1 = &((*edge1)->next);
}
*edge1 = newedge1; st_edge* newedge2 = (st_edge*)malloc(sizeof(st_edge));
newedge2->vertex = start;
newedge2->value = value;
newedge2->next = NULL;
st_edge** edge2 = edge + end;
while(*edge2 != NULL){
edge2 = &((*edge2)->next);
}
*edge2 = newedge2;
}
//打印存储的图
void displayGraph(st_edge** edge){
int i;
st_edge* p;
for(i=0;i<VERTEXNUM;i++){
printf("%d:",i);
p = *(edge+i);
while(p != NULL){
printf("%d(%d) ",p->vertex,p->value);
p = p->next;
}
printf("\n");
}
}
//释放邻接表占用的内存
void delGraph(st_edge** edge){
int i;
st_edge* p;
st_edge* del;
for(i=0;i<VERTEXNUM;i++){
p = *(edge+i);
while(p != NULL){
del = p;
p = p->next;
free(del);
}
edge[i] = NULL;
}
free(edge);
}
//prim算法
void prim(st_edge** edge, st_edge*** tree, int startVertex, int* vertexStatusArr){
//为最小生成树申请内存
*tree = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);
int i,j;
for(i=0;i<VERTEXNUM;i++){
(*tree)[i] = NULL;
}
//从顶点0开始,则顶点0就是已访问的
vertexStatusArr[0] = 1;
st_edge* p;
int least, start, end, vNum = 1;
//如果还顶点还没有访问完
while(vNum < VERTEXNUM){
least = 9999;
for(i=0;i<VERTEXNUM;i++){
//选择已经访问过的点
if(vertexStatusArr[i] == 1){
for(j=0;j<VERTEXNUM;j++){
//选择一个没有访问过的点
if(vertexStatusArr[j] == 0){
p = *(edge+i);
//选出一条value最小的边
while(p != NULL){
if(p->value < least && p->vertex == j){
least = p->value;
start = i;
end = j;
}
p = p->next;
}
}
}
}
}
vNum++;
//将点设置为访问过
vertexStatusArr[end] = 1;
//将边加到树中
createGraph(*tree,start,end,least);
}
}
算法之prim算法的更多相关文章
- 最小生成树---普里姆算法(Prim算法)和克鲁斯卡尔算法(Kruskal算法)
普里姆算法(Prim算法) #include<bits/stdc++.h> using namespace std; #define MAXVEX 100 #define INF 6553 ...
- Dijkstra 算法、Kruskal 算法、Prim算法、floyd算法
1.dijkstra算法 算最短路径的,算法解决的是有向图中单个源点到其他顶点的最短路径问题. 初始化n*n的数组. 2.kruskal算法 算最小生成树的,按权值加入 3.Prim算法 类似dijk ...
- 最小生成树问题:Kruskal算法 AND Prim算法
Kruskal算法: void Kruskal ( ) { MST = { } ; //边的集合,最初为空集 while( Edge ...
- 最小生成树算法 1.Prim算法
最小生成树(MST):一个有N个点的图,边一定是大于等于N-1条边的.在这些边中选择N-1条出来,连接所有N个点.这N-1条边的边权之和是所有方案中最小的. Prim算法的时间复杂度时O(n^2)的, ...
- hdu 1162 Eddy's picture (Kruskal算法,prim算法,最小生成树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1162 [题目大意] 给你n个点的坐标,让你找到联通n个点的一种方法.保证联通的线路最短,典型的最小生成 ...
- 【算法】prim算法(最小生成树)(与Dijkstra算法的比较)
最小生成树: 生成树的定义:给定一个无向图,如果它的某个子图中任意两个顶点都互相连通并且是一棵树,那么这棵树就叫做生成树.(Spanning Tree) 最小生成树的定义:在生成树的基础上,如果边上有 ...
- 图-kruskal算法,prim算法
要求无向图 最小生成树: 连通性,累加和最小 并查集 结构 K算法 从最小的边开始,加上有没有形成环,没有就加,加上有环就不要 难点:如何判断加上一条边,有没有形成环. P算法 从点的角度开始
- 最小路径(prim)算法
#include <stdio.h>#include <stdlib.h>/* 最小路径算法 -->prim算法 */#define VNUM 9#define MV 6 ...
- prim算法
最小生成树 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边.最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法 ...
随机推荐
- NET中异常处理的最佳实践
NET中异常处理的最佳实践 本文翻译自CodeProject上的一篇文章,原文地址. 目录 介绍 做最坏的打算 提前检查 不要信任外部数据 可信任的设备:摄像头.鼠标以及键盘 “写操作”同样可能失效 ...
- java设计模式之九外观模式(Facade)
外观模式是为了解决类与类之家的依赖关系的,像spring一样,可以将类和类之间的关系配置到配置文件中,而外观模式就是将他们的关系放在一个Facade类中,降低了类类之间的耦合度,该模式中没有涉及到接口 ...
- 【UVA】10285-Longest Run on a Snowboard(动态规划)
这是一个简单的问题.你并不需要打印路径. 状态方程dp[i][j] = max(dp[i-1][j],dp[i][j-1],dp[i+1][j],dp[i][j+1]); 14003395 10285 ...
- 有趣的游戏:Google XSS Game
Google最近出了一XSS游戏: https://xss-game.appspot.com/ 我这个菜鸟看提示,花了两三个小时才全过了.. 这个游戏的规则是仅仅要在攻击网页上弹出alert窗体就能够 ...
- python基础课程_学习笔记20:标准库:有些收藏夹——os
标准库:有些收藏夹 os os模块为您提供访问多个操作系统服务特征. os和它的子模块os.path还包含一些用于检查.构造.删除文件夹和文件的函数,以及一些处理路径的函数. os模块中一些重要函数和 ...
- ASP.NET MVC进阶
ASP.NET MVC进阶 一.ASP.NET MVC中的AJAX应用 首先,在ASP.NET MVC中使用自带的ajax功能,必须要导入2个js文件(顺序不能颠倒): ASP.NET MVC提供了2 ...
- 基于C# 语言的两个html解析器
基于C# 语言的两个html解析器 1)Html Agility Pack http://nsoup.codeplex.com/ 代码段示例: HtmlDocument doc = new HtmlD ...
- mysql查询字段值为数字
原文:mysql查询字段值为数字 我想查询字段值为数字的sql如下:select * from tj_item_result where tj_value REGEXP '^[0-9]'
- 【转载】Android中ListView下拉刷新的实现
在网上看到一个下拉刷新的例子,很的很棒,转载和更多的人分享学习 原文:http://blog.csdn.net/loongggdroid/article/details/9385535 ListVie ...
- 对Extjs中store的多种操作
Store.getCount()返回的是store中的所有数据记录,然后使用for循环遍历整个store,从而得到每条记录. 除了使用getCount()的方法外,还可以使用each()函数,如下面的 ...