普利姆(Prim)算法

1. 最小生成树(又名:最小权重生成树)

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

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

2. 普利姆算法介绍

利姆(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条边

3.图例描述

4.Prime代码

#include <stdio.h>
#include <stdlib.h>
#include<iostream>
using namespace std; #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;
cout<<"============================="<<endl;
cout<<"图中有"<<n<<"个顶点 "<<endl;
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; /*其他位置的值置初始化为一个最大整数*/
}
}
}
cout<<"请输入边的个数"<<endl;
cin>>arcnum;
cout<<"请输入边的信息,依照起点,终点,权值的形式输入:"<<endl;
for(k=1; k<=arcnum; k++) {
cin>>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)算法 最小生成树 概念:将给出的所有点连接起来(即从一个点可到任意一个点),且连接路径之和最小的图叫最小生成树.最小生成树属于一种树形结构(树形结构是一种特殊的图),或者 ...

  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. AQS学习(一)自旋锁原理介绍(为什么AQS底层使用自旋锁队列?)

    1.什么是自旋锁? 自旋锁作为锁的一种,和互斥锁一样也是为了在并发环境下保护共享资源的一种锁机制.在任意时刻,只有一个执行单元能够获得锁. 互斥锁通常利用操作系统提供的线程阻塞/唤醒机制实现,在争用锁 ...

  2. 『Java』List Set

    观前提醒:本文内容多为入门时的学习笔记,笔记内容有些混乱!!! | | | | | | | | | | | | 泛型只能是引用类型,不能是基本类型. 如果希望集合中存储的是基本类型数据,需要基本类型对 ...

  3. 线性代数期末大总结II

    向量组的线性相关性 向量组及其线性组合: n个有次序的数\(a_1,a_2,\cdots,a_n\)所组成的数组称为n维向量,这n个数称为该向量的n个分量,第i个数\(a_i\)称为第i个分量. 若干 ...

  4. 记录一次mysql的安装之旅

    mysql作为日常开发中常用到的数据库,对每个程序员来说至关重要,今天就跟着我来进行一次mysql的安装之旅吧. 一.安装 1.安装包的方式 1.1.获取安装包 对mysql有过接触的人来说,都知道m ...

  5. 十六进制转十进制 BASIC-12

    十六进制转十进制 代码 import java.math.BigInteger; import java.util.Scanner; /* * 从键盘输入一个不超过8位的正的十六进制数字符串, * 将 ...

  6. Windows内核基础知识-2-段描述符

    Windows内核基础知识-2-段描述符 比如: ES 002B 0(FFFFFFFF) 意思就是es段寄存器,段选择子/段选择符 为002B, 起始地址base为0, 限制范围Limit地址最大能寻 ...

  7. http扩展小插件

    支持.net framework4.5.1,.net core2.0及以上 应用层需要引用包Kogel.Net,Nuget上可以下载安装. 或者使用Nuget命令添加包 Install-Package ...

  8. WPF 饼状图,柱形图,折线图 (2 折线图)

    折线图在柱形图的基础上,做了一些修改.大概效果和用法如下. X轴和Y轴的刻度,使用用了Path的Figures属性,绘制多条Figure+LineSegment完成. 同时,由于折线图很可能会画多条线 ...

  9. 【转】springcloud底层原理

    本文为转载文章,作者:中华石杉,十余年BAT架构经验,倾囊相授.作者微信公众号:石杉的架构笔记(ID:shishan100) 概述 毫无疑问,Spring Cloud是目前微服务架构领域的翘楚,无数的 ...

  10. 我对数据库关系代数中减法sql实现的思考:mysql脚本

    一.创建数据库,创建表结构 CREATE DATABASE Test_sub DEFAULT CHARACTER SET utf8; USE Test_sub; CREATE TABLE studen ...