数据结构(C实现)------- 最小生成树之Prim算法
[本文是自己学习所做笔记。欢迎转载。但请注明出处:http://blog.csdn.net/jesson20121020]
算法描写叙述
假设连通图是一个网,则称该网中全部生成树中权值总和最小的生成树为最小生成树,也称最小代价生成树。利用Prim算法构造的最小生成树方法思想:
如果G=(V,E)是一个具有n个顶点的连通网,顶点集V={v1,v2,...,vn}.设所求的最小生成树T=(U,TE),当中U是T的顶点集。TE是T的边集。U和TE初值均为空集。
Prim算法的基本思想例如以下:首先从V中任取一个顶点(假定取v1),将生成树T置为仅有一个结点v1的树。即U={v1};然后仅仅要U是V的真子集,就在全部那些一个端点在T中。还有一个端点在T外的边中。找一条最短(即权值最小 )的边。假定符合条件的最短边为(vi,vj),则把该条边和其不在T中的顶点vj,分别并入T的边集TE和顶点集U。
如此进行下去,每次往生成树里并入一个顶点和一条边,直到把全部顶点都包含进生成树T为止。
此时。必有U=V,TE中有n-1条边。则T=(U,TE)是G的一棵最小生成树。
算法实现
设一个edge数组。记录从顶点U集到V-U的代价最小的边。每条边的信息包含边的始点和,终点和权值。
从顶点u出发,利用prim算法求最小生成树过程例如以下:
(1) 初始化edge数组。记录顶点u到图中其余结点的代价最小的n-1的边。
(2) 将顶点u增加U中。
(3) 当U不等于V时,做例如以下处理。
1) 从edge数组中选一条代价最小的边。
2) 将该边的终点增加U中。
3) 调整edges数组,使它始终记录顶点U到V-U的代价最小的边。
算法代码
// 定义边结构体
typedef struct{
int start;
int end;
int cost;
}Edge; /*
*Prim算法求最小生成树
* */
void Prim_MG(MGraph MG,char vs){
Edge edge[MAX_VEX_NUM];
int i,j,k,v,min;
int s = getIndexOfVexs(vs,&MG);
//初始化边
for(i = 1;i <= MG.vexnum;i++){
if(s != i){
edge[i].start = s;
edge[i].end = i;
edge[i].cost = MG.arcs[s][i]; }
}
//首先将s增加生成树集合中
edge[s].cost = 0;
for(i = 2;i <= MG.vexnum;i++){
min = 1000;
for(j = 1;j<= MG.vexnum;j++){
if(edge[j].cost != 0 && edge[j].cost < min ){
min = edge[j].cost;
k = j;
}
}
v = edge[k].end;
edge[v].cost = 0; // 增加新节点 //输出生成树中的边
printf("%c %c %d\n",MG.vexs[edge[v].start],MG.vexs[edge[v].end],MG.arcs[edge[v].start][edge[v].end]); //又一次调整数组
for(j = 1;j <= MG.vexnum;j++){
if(edge[j].cost != 0 && MG.arcs[v][j] != 0 && MG.arcs[v][j] < edge[j].cost){
edge[j].start = k;
edge[j].end = j;
edge[j].cost = MG.arcs[v][j];
}
}
} }
算法说明
如果图中有n个顶点,则第一个进行初始化的循环语句的频度为n,第二个循环语句频度为n-1。当中有两个内循环;其一是在edge数组中找权值最小的边。其频度为n-1,其二是又一次调整edge数组的边,频度为n,所以Prim算法的时间复杂度为O(n^2),而与图中的边数无关,因此适用于求稠密的最小生成树。
完整代码
/*
* =====================================================================================
*
* Filename: Prim.c
*
* Description: 最小生成树算法之Prim算法
*
* Version: 1.0
* Created: 2015年03月11日 15时27分19秒
* Revision: none
* Compiler: gcc
*
* Author: jesson20121020 (), 997287955@qq.com
* Organization:
*
* =====================================================================================
*/ #include <stdio.h>
#include <stdlib.h>
#define MAX_VEX_NUM 50
#define UN_REACH 1000 typedef char VertexType;
typedef enum {
DG, UDG
} GraphType;
typedef struct {
VertexType vexs[MAX_VEX_NUM];
int arcs[MAX_VEX_NUM][MAX_VEX_NUM];
int vexnum, arcnum;
GraphType type;
} MGraph; /**
* 依据名称得到指定顶点在顶点集合中的下标
* vex 顶点
* return 假设找到,则返回下标,否则,返回0
*/
int getIndexOfVexs(char vex, MGraph *MG) {
int i;
for (i = 1; i <= MG->vexnum; i++) {
if (MG->vexs[i] == vex) {
return i;
}
}
return 0;
} /**
* 创建邻接矩阵
*/
void create_MG(MGraph *MG) {
int i, j, k,weight;
int v1, v2, type;
char c1, c2;
printf("Please input graph type DG(0) or UDG(1) :");
scanf("%d", &type);
if (type == 0)
MG->type = DG;
else if (type == 1)
MG->type = UDG;
else {
printf("Please input correct graph type DG(0) or UDG(1)!");
return;
} printf("Please input vexmun : ");
scanf("%d", &MG->vexnum);
printf("Please input arcnum : ");
scanf("%d", &MG->arcnum);
getchar();
for (i = 1; i <= MG->vexnum; i++) {
printf("Please input %dth vex(char):", i);
scanf("%c", &MG->vexs[i]);
getchar();
} //初始化邻接矩阵
for (i = 1; i <= MG->vexnum; i++) {
for (j = 1; j <= MG->vexnum; j++) {
if(i == j)
MG->arcs[i][j] = 0;
else
MG->arcs[i][j] = UN_REACH;
}
} //输入边的信息,建立邻接矩阵
for (k = 1; k <= MG->arcnum; k++) {
printf("Please input %dth arc v1(char) v2(char) weight(int): ", k); scanf("%c %c %d", &c1, &c2,&weight);
v1 = getIndexOfVexs(c1, MG);
v2 = getIndexOfVexs(c2, MG);
if (MG->type == 1)
MG->arcs[v1][v2] = MG->arcs[v2][v1] = weight;
else
MG->arcs[v1][v2] = weight;
getchar();
} }
/**
* 打印邻接矩阵和顶点信息
*/
void print_MG(MGraph MG) {
int i, j;
if(MG.type == DG){
printf("Graph type: Direct graph\n");
}
else{
printf("Graph type: Undirect graph\n");
} printf("Graph vertex number: %d\n",MG.vexnum);
printf("Graph arc number: %d\n",MG.arcnum); printf("Vertex set:\n ");
for (i = 1; i <= MG.vexnum; i++)
printf("%c\t", MG.vexs[i]);
printf("\nAdjacency Matrix:\n"); for (i = 1; i <= MG.vexnum; i++) {
j = 1;
for (; j < MG.vexnum; j++) {
printf("%d\t", MG.arcs[i][j]);
}
printf("%d\n", MG.arcs[i][j]);
}
} // 定义边结构体
typedef struct{
int start;
int end;
int cost;
}Edge; /*
*Prim算法求最小生成树
* */
void Prim_MG(MGraph MG,char vs){
Edge edge[MAX_VEX_NUM];
int i,j,k,v,min;
int s = getIndexOfVexs(vs,&MG);
//初始化边
for(i = 1;i <= MG.vexnum;i++){
if(s != i){
edge[i].start = s;
edge[i].end = i;
edge[i].cost = MG.arcs[s][i]; }
}
//首先将s增加生成树集合中
edge[s].cost = 0;
for(i = 2;i <= MG.vexnum;i++){
min = 1000;
for(j = 1;j<= MG.vexnum;j++){
if(edge[j].cost != 0 && edge[j].cost < min ){
min = edge[j].cost;
k = j;
}
}
v = edge[k].end;
edge[v].cost = 0; // 增加新节点 //输出生成树中的边
printf("%c %c %d\n",MG.vexs[edge[v].start],MG.vexs[edge[v].end],MG.arcs[edge[v].start][edge[v].end]); //又一次调整数组
for(j = 1;j <= MG.vexnum;j++){
if(edge[j].cost != 0 && MG.arcs[v][j] != 0 && MG.arcs[v][j] < edge[j].cost){
edge[j].start = k;
edge[j].end = j;
edge[j].cost = MG.arcs[v][j];
}
}
} } /**
* 主函数
*/
int main(void) {
MGraph MG;
char startVex;
create_MG(&MG);
print_MG(MG); printf("\nPlease input the start vex(char):");
scanf("%c",&startVex);
printf("\nThe result of Prim:\n");
Prim_MG(MG,startVex); return EXIT_SUCCESS;
}
执行演示
jesson@jesson-HP:~/develop/workspace/c_learning/csdn/Prim$ gcc -o Prim Prim.c
jesson@jesson-HP:~/develop/workspace/c_learning/csdn/Prim$ ./Prim
Please input graph type DG(0) or UDG(1) :1
Please input vexmun : 4
Please input arcnum : 5
Please input 1th vex(char):a
Please input 2th vex(char):b
Please input 3th vex(char):c
Please input 4th vex(char):d
Please input 1th arc v1(char) v2(char) weight(int): a b 1
Please input 2th arc v1(char) v2(char) weight(int): a c 3
Please input 3th arc v1(char) v2(char) weight(int): a d 4
Please input 4th arc v1(char) v2(char) weight(int): b c 2
Please input 5th arc v1(char) v2(char) weight(int): c d 3 Please input the start vex(char):a The result of Prim:
a b 1
b c 2
c d 3
数据结构(C实现)------- 最小生成树之Prim算法的更多相关文章
- 数据结构与算法--最小生成树之Prim算法
数据结构与算法--最小生成树之Prim算法 加权图是一种为每条边关联一个权值或称为成本的图模型.所谓生成树,是某图的一棵含有全部n个顶点的无环连通子图,它有n - 1条边.最小生成树(MST)是加权图 ...
- C++编程练习(10)----“图的最小生成树“(Prim算法、Kruskal算法)
1.Prim 算法 以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树. 2.Kruskal 算法 直接寻找最小权值的边来构建最小生成树. 比较: Kruskal 算法主要是针对边来展开,边数 ...
- 最小生成树一·Prim算法
描述 最近,小Hi很喜欢玩的一款游戏模拟城市开放出了新Mod,在这个Mod中,玩家可以拥有不止一个城市了! 但是,问题也接踵而来——小Hi现在手上拥有N座城市,且已知这N座城市中任意两座城市之间建造道 ...
- 24最小生成树之Prim算法
最小生成树的Prim算法 思想:采用子树延伸法 将顶点分成两类: 生长点——已经在生成树上的顶点 非生长点——未长到生成树上的顶点 使用待选边表: 每个非生长点在待选边表中有一条待选边,一端连着非生长 ...
- 最小生成树的Prim算法
构造最小生成树的Prim算法 假设G=(V,E)为一连通网,其中V为网中所有顶点的集合,E为网中所有带权边的集合.设置两个新的集合U和T,其中集合U用于存放G的最小生成树的顶点,集合T用于 ...
- hihocoder 1097 最小生成树一·Prim算法
#1097 : 最小生成树一·Prim算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 最近,小Hi很喜欢玩的一款游戏模拟城市开放出了新Mod,在这个Mod中,玩家可 ...
- 算法学习记录-图——最小生成树之prim算法
一个连通图的生成树是一个极小的连通子图,它包含图中全部的顶点(n个顶点),但只有n-1条边. 最小生成树:构造连通网的最小代价(最小权值)生成树. prim算法在严蔚敏树上有解释,但是都是数学语言,很 ...
- Hihocoder 之 #1097 : 最小生成树一·Prim算法 (用vector二维 模拟邻接表,进行prim()生成树算法, *【模板】)
#1097 : 最小生成树一·Prim算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 最近,小Hi很喜欢玩的一款游戏模拟城市开放出了新Mod,在这个Mod中,玩家可 ...
- hihocoder hiho一下 第二十六周 最小生成树一·(Prim算法)
题目1 : 最小生成树一·Prim算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 最近,小Hi很喜欢玩的一款游戏模拟城市开放出了新Mod,在这个Mod中,玩家可以拥 ...
- 数据结构与算法系列----最小生成树(Prim算法&Kruskal算法)
一:Prim算法 1.概览 普里姆算法(Prim算法).图论中的一种算法.可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中.不但包含了连通图里的全部顶点(英语:Ve ...
随机推荐
- 基于JQuery EasyUI的WebMVC控件封装(含源码)
JQuery EasyUI类库,大家不会陌生,出来已经有很多年了.个人感觉还是很好用的,作者更新频率也很快,bug也及时修复. 最近在整理以前的代码,找到了这个组件,它是将EasyUI组件封装成MVC ...
- css 行内元素设置宽高
有2中实现方法: 1.设置display:block inline-block,使其width属性生效 2.如果设置float:left | right, 使其width属性生效. (浮动)使得指 ...
- Git Submodules are not SVN Externals
一直在寻找Git跟TFS里面类似SVN Externals的替代方案, 今天终于找到了GIT里面的替代方案,在此做个备注 http://alexking.org/blog/2012/03/05/git ...
- js实现小球的弹性碰撞。
前 言 MYBG 小编最近在做自己的个人网站,其中就用到了一个小球碰撞检测的功能,想自己写,无奈本人能力不足啊(毕竟还是一个菜鸟)!!就想着找个插件用一下也好,可是找了好久也没有找到一个比较好用 ...
- 14.javaweb AJAX技术详解
一.简介 1, ajax:在不重新加载网页的前提下,与服务器交换数据并更新部分网页的技巧,但其本身并不是一种新技术 2, 核心:XMLHttpRequest对象.AJAX技术主要是通过此对象完成的 ...
- java非阻塞IO(NIO)流程
单线程 多线程(Netty/Mina)
- 使用springboot完成密码的加密解密
现今对于大多数公司来说,信息安全工作尤为重要,就像京东,阿里巴巴这样的大公司来说,信息安全是最为重要的一个话题,举个简单的例子: 就像这样的密码公开化,很容易造成一定的信息的泄露.所以今天我们要讲的就 ...
- Hibernate框架学习之注解配置关系映射
上篇文章我们通过注解对映射了单个实体类,但是具体项目中往往实体类之间又是相互关联的,本篇文章就是从实体类之间存在的不同关联角度,具体学习下如何映射他们之间的关联,主要涉及内容如下: 单向的一 ...
- android wear开发之:创建可穿戴设备应用 - Creating Wearable Apps
注:本文内容来自:https://developer.android.com/training/wearables/apps/index.html 翻译水平有限,如有疏漏,欢迎批评指教. 译:山人 创 ...
- YII2调试 通过日志记录将变量保存到文件
$log = new \yii\log\FileTarget(); $content=var_export($menu,"true");//将数组或对象转换字符串格式 $con ...