最小生成树-普利姆(Prim)算法

最小生成树

概念:将给出的所有点连接起来(即从一个点可到任意一个点),且连接路径之和最小的图叫最小生成树。最小生成树属于一种树形结构(树形结构是一种特殊的图),或者说是直链型结构,因为当n个点相连,且路径和最短,那么将它们相连的路一定是n-1条。

可以利用参考一个问题理解最小生成树,有n个村庄,每个村庄之间距离不同,要求村庄之间修路,每一个村庄必须与任意一个村庄联通,如何修路最省钱(修的最短)

普利姆算法介绍

利姆(Prim)算法求最小生成树,也就是在包含n个顶点的连通图中,找出只有(n-1)条边包含所有n个顶点的连通子图,也就是所谓的极小连通子图

具体过程如下:

(1)设G=(V,E)是连通网,T=(U,D)是最小生成树,V,U是顶点集合,E,D是边的集合

(2)若从顶点u开始构造最小生成树,则从集合V中取出顶点u放入集合U中,标记顶点v的visited[u]=1

(3)若集合U中顶点ui与集合V-U中的顶点vj之间存在边,则寻找这些边中权值最小的边,但不能构成回路,将顶点vj加入集合U中,将边(ui,vj)加入集合D中,标记visited[vj]=1

(4)重复步骤②,直到U与V相等,即所有顶点都被标记为访问过,此时D中有n-1条边

代码实现

不同的题目有不同的细节实现方式,因此本代码仅供参考

#include <stdio.h>
#include <stdlib.h>
#define n 20
#define MaxNum 10000 /*定义一个最大整数*/ /*定义邻接矩阵类型*/
typedef int adjmatrix[n + 1][n + 1];
typedef struct {
int fromvex, tovex; //生成树的起点和终点
int weight; //边的权重
} Edge;
typedef Edge *EdgeNode; //定义生成树的别名
int arcnum; /*边的个数*/ /*建立图的邻接矩阵*/
void CreatMatrix(adjmatrix GA) {
int i, j, k, e;
printf("=============================\n");
printf("图中有%d个顶点\n", n);
for(i=1; i<=n; i++) {
for(j=1; j<=n; j++) {
if(i==j) {
GA[i][j]=0; /*对角线的值置为0*/
} else {
GA[i][j]=MaxNum; /*其他位置的值置初始化为一个最大整数*/
}
}
}
printf("请输入边的个数:\n");
scanf("%d", &arcnum);
printf("请输入边的信息,依照起点,终点,权值的形式输入:\n");
for(k=1; k<=arcnum; k++) {
scanf("%d,%d,%d",&i,&j,&e); /*读入边的信息*/
GA[i][j]=e;
GA[j][i]=e;
}
} /*初始化图的边集数组*/
void InitEdge(EdgeNode GE,int m) {
int i;
for(i=1; i<=m; i++) {
GE[i].weight=0;
}
} /*依据图的邻接矩阵生成图的边集数组*/
void GetEdgeSet(adjmatrix GA,EdgeNode GE) {
int i, j, k = 1;
for(i=1; i<=n; i++) {
for(j=i+1; j<=n; j++) {
if(GA[i][j] !=0 && GA[i][j] != MaxNum) {
GE[k].fromvex = i;
GE[k].tovex = j;
GE[k].weight = GA[i][j];
k++;
}
}
}
} /*按升序排列图的边集数组*/
void SortEdge(EdgeNode GE,int m) {
int i,j,k;
Edge temp;
for(i=1; i<m; i++) {
k=i;
for(j=i+1; j<=m; j++) {
if(GE[k].weight > GE[j].weight) {
k=j;
}
}
if(k!=i) {
temp = GE[i];
GE[i]=GE[k];
GE[k]=temp;
}
}
} /*利用普里姆算法从初始点v出发求邻接矩阵表示的图的最小生成树*/
void Prim(adjmatrix GA,EdgeNode T) {
int i,j,k,min,u,m,w;
Edge temp;
/*给T赋初值。相应为v1依次到其余各顶点的边*/
k=1;
for(i=1; i<=n; i++) {
if(i!=1) {
T[k].fromvex=1;
T[k].tovex=i;
T[k].weight=GA[1][i];
k++;
}
}
/*进行n-1次循环,每次求出最小生成树中的第k条边*/
for(k=1; k<n; k++) {
min=MaxNum;
m=k;
for(j=k; j<n; j++) {
if(T[j].weight<min) {
min=T[j].weight;
m=j;
}
}
/*把最短边对调到k-1下标位置*/ 可用swap替换
temp=T[k];
T[k]=T[m];
T[m]=temp;
/*把新增加最小生成树T中的顶点序号赋给j*/
j=T[k].tovex;
/*改动有关边,使T中到T外的每个顶点保持一条到眼下为止最短的边*/
for(i=k+1; i<n; i++) {
u=T[i].tovex;
w=GA[j][u];
if(w<T[i].weight) {
T[i].weight=w;
T[i].fromvex=j;
}
}
}
} /*输出边集数组的每条边*/
void OutEdge(EdgeNode GE,int e) {
int i;
printf("依照起点,终点。权值的形式输出的最小生成树为:\n");
for(i=1; i<=e; i++) {
printf("%d,%d,%d\n",GE[i].fromvex,GE[i].tovex,GE[i].weight);
}
printf("=============================\n");
} int main() {
adjmatrix GA;
Edge GE[n*(n-1)/2], T[n];
CreatMatrix(GA);
InitEdge(GE,arcnum);
GetEdgeSet(GA,GE);
SortEdge(GE,arcnum);
Prim(GA,T);
printf("\n");
OutEdge(T,n-1);
return 0;
}

最小生成树-普利姆(Prim)算法的更多相关文章

  1. 图论---最小生成树----普利姆(Prim)算法

    普利姆(Prim)算法 1. 最小生成树(又名:最小权重生成树) 概念:将给出的所有点连接起来(即从一个点可到任意一个点),且连接路径之和最小的图叫最小生成树.最小生成树属于一种树形结构(树形结构是一 ...

  2. 图解最小生成树 - 普里姆(Prim)算法

    我们在图的定义中说过,带有权值的图就是网结构.一个连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边.所谓的最小成本,就是n个顶点,用n-1条边把一个连通图连接 ...

  3. 普里姆Prim算法介绍

    普里姆(Prim)算法,和克鲁斯卡尔算法一样,是用来求加权连通图的最小生成树的算法. 基本思想 对于图G而言,V是所有顶点的集合:现在,设置两个新的集合U和T,其中U用于存放G的最小生成树中的顶点,T ...

  4. 最小生成树-普利姆算法lazy实现

    算法描述 lazy普利姆算法的步骤: 1.从源点s出发,遍历它的邻接表s.Adj,将所有邻接的边(crossing edges)加入优先队列Q: 2.从Q出队最轻边,将此边加入MST. 3.考察此边的 ...

  5. JS实现最小生成树之普里姆(Prim)算法

    最小生成树: 我们把构造连通网的最小代价生成树称为最小生成树.经典的算法有两种,普利姆算法和克鲁斯卡尔算法. 普里姆算法打印最小生成树: 先选择一个点,把该顶点的边加入数组,再按照权值最小的原则选边, ...

  6. 最小生成树-普利姆算法eager实现

    算法描述 在普利姆算法的lazy实现中,参考:普利姆算法的lazy实现 我们现在来考虑这样一个问题: 我们将所有的边都加入了优先队列,但事实上,我们真的需要所有的边吗? 我们再回到普利姆算法的lazy ...

  7. POJ-2421-Constructing Roads(最小生成树 普利姆)

    Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 26694   Accepted: 11720 Description The ...

  8. 最小生成树——Prim(普利姆)算法

    [0]README 0.1) 本文总结于 数据结构与算法分析, 源代码均为原创, 旨在 理解Prim算法的idea 并用 源代码加以实现: 0.2)最小生成树的基础知识,参见 http://blog. ...

  9. 图的普里姆(Prim)算法求最小生成树

    关于图的最小生成树算法------普里姆算法 首先我们先初始化一张图: 设置两个数据结构来分别代表我们需要存储的数据: lowcost[i]:表示以i为终点的边的最小权值,当lowcost[i]=0说 ...

随机推荐

  1. Visio操作【未完】

    Visio 1.如何操作文档 新建基本框图和空白框图 单击基本框图打开后有模具 空白框图打开之后并没有形状 左下角发现有 更改纸张方向大小 自动调整大小: 如果我们选择形状进入到我们的页面,如果放到边 ...

  2. const变量通过指针修改问题

    const的变量在特定情况下可以通过指针修改,但是在另一些情况下是不能通过指针修改. 以下是VC6下才测试. 1. 不能修改的情况 #include int const a = 10; void ma ...

  3. 【Java】jeesite初始配置以及代码生成工具的使用

    jeesite简单使用 首先去技术服务与支持.版本区别一览表 - JeeSite 4.x找到源码下载的部分 JeeSite 源码下载:https://gitee.com/thinkgem/jeesit ...

  4. anaconda的报错:Anaconda:There is an instance of anaconda navigator already running error

    anaconda的报错:Anaconda:There is an instance of anaconda navigator already running error 出现这个问题的时候人蒙了,主 ...

  5. 🏆【Java技术专区】「开发实战专题」Lombok插件开发实践必知必会操作!

    前言 在目前众多编程语言中,Java 语言的表现还是抢眼,不论是企业级服务端开发,还是 Andorid 客户端开发,都是作为开发语言的首选,甚至在大数据开发领域,Java 语言也能占有一席之地,如Ha ...

  6. 深入理解-dl_runtime_resolve

    深入理解-dl_runtime_resolve 概要 目前大部分漏洞利用常包含两个阶段: 首先通过信息泄露获取程序内存布局 第二步才进行实际的漏洞利用 然而信息泄露的方法并不总是可行的,且获取的内存信 ...

  7. Mybatis映射器(二)

    上一篇文章返回是resultType,但其无法定义多的属性,比如typeHandler,级联等.为了支持复杂映射,可以用resultMap属性,先定义resultmap属性: <mapper n ...

  8. Flink 保证ExactlyOnce

    Flink 保证 ExactlyOnce 1.使用执行ExactlyOnce 的数据源,比如 kafka 2.使用FlinkConsumer,开启CheckPointing,偏移量会保存通过Check ...

  9. Windows10下MySQL的安装

    简单介绍一下MySQL的安装 官方网址:https://www.mysql.com/downloads/ 1.找到MySQL Community Edition (GPL) (注:GPL版本为开源,非 ...

  10. mysql各个版本驱动jar包下载 mysql/mysql-connector-java/5.1.22

    想下个jar csdn上全是要积分下载,这里记录下 下载地址,免得到时又要找 http://central.maven.org/maven2/mysql/mysql-connector-java/