声明:图片及内容基于https://www.bilibili.com/video/BV1yp4y1Q74o?from=articleDetail

最小生成树原理

普利姆(Prim)算法

原理

Prim算法的实现

核心代码

void MGraph::Prim(int start){
shortEdge shortEdge; //建立shortEdge数组
for(int i=0;i<vertexNum;i++){
shortEdge[i].lowcost=arc[start][i]; // 数组初始化,lowcost为邻接矩阵第i行的权值
shortEdge[i].adjvex=start; //adjvex初始化为起始值
}
shortEdge[start].lowcost=0;; //lowcost为0,把start放入集合 for(int i=0;i<vertexNum;i++){
int k=minEdge(shortEdge,vertexNum); //求出最小权值下标
if(k==-1) return ; //shortEdge的lowcost都为0,及所有结点都在集合中,算法结束
outputSMT(k,shortEdge[k]);
shortEdge[k].lowcost=0; //k放入集合
for(int j=0;j<vertexNum;j++){ //更新shortEdge数组,当前集合和刚进入集合的结点的权值比较
if(arc[k][j]<shortEdge[j].lowcost){
shortEdge[j].lowcost=arc[k][j];
shortEdge[j].adjvex=k;
}
}
}
}
int minEdge(shortEdge shortEdge,int vertexNum){  //求shortEdge数组中最小权值的下标
Edge e; //e是个临时变量用来记录当前小权值的下标和权值
e.lowcost=INFINIT;
e.adjvex=-1;
int i;
for(i=0;i<vertexNum;i++){ //权值不为0(已经在集合中),不为无穷 (无路径)
if(shortEdge[i].lowcost!=0&&shortEdge[i].lowcost!=INFINIT&&e.lowcost>shortEdge[i].lowcost){
e.lowcost=shortEdge[i].lowcost;
e.adjvex=i;
} }
return e.adjvex;
}
void outputSMT(int k,Edge Edge){            //打印路径和权值
cout<<"("<<Edge.adjvex<<","<<k<<") "<<Edge.lowcost<<endl;
}

完整代码

#include<iostream>
#define MAXVEX 100
using namespace std;
const int INFINIT=65535;
int visit[MAXVEX];
typedef struct Edge{
int lowcost;
int adjvex;
}Edge,shortEdge[MAXVEX]; class MGraph {
private:
int *vertex; //顶点信息
int **arc; //邻接矩阵
int vertexNum,arcNum; //顶点数,边数
public:
MGraph(int v[],int n,int e);
~MGraph();
void display();
void Prim(int start);
}; MGraph::MGraph(int v[],int n,int e) { //n是顶点数,e是边数
vertexNum=n;
arcNum=e;
vertex = new int[vertexNum]; //建立顶点信息
arc = new int*[vertexNum]; //建立邻接表
for(int i=0; i<vertexNum; i++)
arc[i]=new int[vertexNum]; for(int i=0; i<vertexNum; i++) { //初始化顶点信息
vertex[i]=v[i];
}
for(int i=0;i<vertexNum;i++) //初始化邻接表
for(int j=0;j<vertexNum;j++){
if(i==j) arc[i][j]=0;
else arc[i][j]=INFINIT;
} int vi,vj,w;
for(int i=0;i<arcNum;i++){
cout<<"请输入边的两个顶点和这条边的权值"<<endl;
cin>>vi>>vj>>w; //输入边依附的两个顶点的编号 和权值
arc[vi][vj]=w; //有边标志
arc[vj][vi]=w;
}
} void MGraph::display(){
for(int i=0;i<vertexNum;i++){
for(int j=0;j<vertexNum;j++){
if(arc[i][j]==INFINIT)
cout<<"∞"<<"\t";
else cout<<arc[i][j]<<"\t";
}
cout<<endl;
}
cout<<endl; for(int i=0;i<vertexNum;i++){
cout<<vertex[i]<<" ";
}
cout<<endl;
} MGraph::~MGraph(){
delete []vertex;
for(int i=0;i<vertexNum;i++)
delete [] arc[i];
delete [] arc;
}
int minEdge(shortEdge shortEdge,int vertexNum){ //求shortEdge数组中最小权值的下标
Edge e; //e是个临时变量用来记录当前小权值的下标和权值
e.lowcost=INFINIT;
e.adjvex=-1;
int i;
for(i=0;i<vertexNum;i++){ //权值不为0(已经在集合中),不为无穷 (无路径)
if(shortEdge[i].lowcost!=0&&shortEdge[i].lowcost!=INFINIT&&e.lowcost>shortEdge[i].lowcost){
e.lowcost=shortEdge[i].lowcost;
e.adjvex=i;
} }
return e.adjvex;
}
void outputSMT(int k,Edge Edge){ //打印路径和权值
cout<<"("<<Edge.adjvex<<","<<k<<") "<<Edge.lowcost<<endl;
}
void MGraph::Prim(int start){
shortEdge shortEdge; //建立shortEdge数组
for(int i=0;i<vertexNum;i++){
shortEdge[i].lowcost=arc[start][i]; // 数组初始化,lowcost为邻接矩阵第i行的权值
shortEdge[i].adjvex=start; //adjvex初始化为起始值
}
shortEdge[start].lowcost=0;; //lowcost为0,把start放入集合 for(int i=0;i<vertexNum;i++){
int k=minEdge(shortEdge,vertexNum); //求出最小权值下标
if(k==-1) return ; //shortEdge的lowcost都为0,及所有结点都在集合中,算法结束
outputSMT(k,shortEdge[k]);
shortEdge[k].lowcost=0; //k放入集合
for(int j=0;j<vertexNum;j++){ //更新shortEdge数组,当前集合和刚进入集合的结点的权值比较
if(arc[k][j]<shortEdge[j].lowcost){
shortEdge[j].lowcost=arc[k][j];
shortEdge[j].adjvex=k;
}
}
}
} int main(){
int v[6]={0,1,2,3,4,5};
cout<<"请输入顶点个数和边的个数"<<endl;
int m,n;
cin>>m>>n;
cout<<"请输入prim算法的起点"<<endl;
int k;
cin>>k; MGraph mgraph(v,m,n);
cout<<"输出邻接矩阵信息和边数组信息:"<<endl;
mgraph.display();
cout<<"输出起点从"<<k<<"开始的最小生成树:" <<endl;
mgraph.Prim(k);
return 0;
}

输入:

6 9

3

0 1 34
0 2 46
0 5 19
1 4 12
2 3 17
2 5 25
3 5 25
3 4 38
4 5 26

输出:

输出邻接矩阵信息和边数组信息:
0  34  46  ∞  ∞  19
34 0   ∞   ∞  12  ∞
46 ∞   0   17 ∞  25
∞  ∞   17  0  38 25
∞  12  ∞  38  0  26
19 ∞   25 25 26  0

0 1 2 3 4 5
输出起点从3开始的最小生成树:
(3,2) 17
(3,5) 25
(5,0) 19
(5,4) 26
(4,1) 12

最小生成树(Prim算法,Kruskal算法 )的更多相关文章

  1. 无向带权图的最小生成树算法——Prim及Kruskal算法思路

    边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...

  2. [数据结构]最小生成树算法Prim和Kruskal算法

    最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树.  例如,对于如上图G4所示的连通网可以有多棵权值总 ...

  3. 图的最小生成树的理解和实现:Prim和Kruskal算法

    最小生成树 一个连通图的生成树是一个极小的连通子图,它含有图中所有的顶点,但只有足以构成一棵树的n-1条边.我们将构造连通网的最小代价生成树称为最小生成树(Minimum Cost Spanning ...

  4. 最小生成树(Prim算法+Kruskal算法)

    什么是最小生成树(MST)? 给定一个带权的无向连通图,选取一棵生成树(原图的极小连通子图),使生成树上所有边上权的总和为最小,称为该图的最小生成树. 求解最小生成树的算法一般有这两种:Prim算法和 ...

  5. hdu 1233 还是畅通工程 最小生成树(prim算法 + kruskal算法)

    还是畅通工程                                                                            Time Limit: 4000/2 ...

  6. 最小生成树 Prim算法 Kruskal算法实现

    最小生成树定义 最小生成树是一副连通加权无向图中一棵权值最小的生成树. 在一给定的无向图 G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即,而 w(u, v) 代表此边的 ...

  7. 最小生成树Prim算法 Kruskal算法

    Prim算法(贪心策略)N^2 选定图中任意定点v0,从v0开始生成最小生成树 树中节点Va,树外节点Vb 最开始选一个点为Va,其余Vb, 之后不断加Vb到Va最短距离的点 1.初始化d[v0]=0 ...

  8. 算法(图论)——最小生成树及其题目应用(prim和Kruskal算法实现)

    题目 n个村庄间架设通信线路,每个村庄间的距离不同,如何架设最节省开销? Kruskal算法 特点 适用于稀疏图,时间复杂度 是nlogn的. 核心思想 从小到大选取不会产生环的边. 代码实现 代码中 ...

  9. 【431】Prim 算法 & Kruskal 算法

    Prim 算法: Minimum Spanning Tree(MST):最小生成树,就是连接所有节点的最小权值 mst集合与rest集合 mst集合中顶点,找到一条最小权值的边 然后把边相关的顶点,选 ...

  10. 最小生成树之算法记录【prime算法+Kruskal算法】【模板】

    首先说一下什么是树: 1.只含一个根节点 2.任意两个节点之间只能有一条或者没有线相连 3.任意两个节点之间都可以通过别的节点间接相连 4.除了根节点没一个节点都只有唯一的一个父节点 5.也有可能是空 ...

随机推荐

  1. CSS ::marker All In One

    CSS ::marker All In One CSS pseudo element / CSS 伪元素 /* user agent stylesheet */ ::marker { unicode- ...

  2. React & react-native & vue & cli & environment information & report bugs

    React & react-native & vue & cli & environment information & report bugs cli che ...

  3. JPG学习笔记4(附完整代码)

    #topics h2 { background: rgba(43, 102, 149, 1); border-radius: 6px; box-shadow: 0 0 1px rgba(95, 90, ...

  4. C/C++子函数参数传递,堆栈帧、堆栈参数详解

    本文转载自C/C++子函数参数传递,堆栈帧.堆栈参数详解 导语 因为参数传递和汇编语言有很大联系,之后会出现较多x86汇编代码. 该文会先讲一下x86的堆栈参数传递过程,然后再分析C/C++子函数是怎 ...

  5. java的read方法

    public class RandomAccessDemo6 { public static void main(String[] args) throws IOException { RandomA ...

  6. dotnet core TargetFramework 解析顺序测试

    dotnet core TargetFramework 解析顺序测试 Intro 现在 dotnet 的 TargetFramework 越来越多,抛开 .NET Framework 不谈,如果一个类 ...

  7. ajax缺点

    ajax请求在SEO中效率低,SEO就是关键字搜索的匹配度. 比如在百度搜索Java,一般来说内容中出现Java的次数越多排名越靠前,当使用ajax时,它的异步刷新导致必须是页面刷新出来才去刷新数据, ...

  8. Linux系统管理--part(1)

    Linux系统管理--part(1) Linux系统安装完毕,需要对Linux系统进行管理和维护,让Linux服务器能够真正英语于企业中 Linux运维的三个步骤安装.调试.启动 通过本篇文章,将学习 ...

  9. SpringCloud(一):微服务架构概述

    1-1.  系统进化理论概述 在系统架构与设计的实践中,经历了两个阶段,一个阶段是早些年常见的集中式系统,一个阶段是近年来流行的分布式系统: 集中式系统: 集中式系统也叫单体应用,就是把所有的程序.功 ...

  10. 如何读写拥有命名空间xmlns 属性的Xml文件(C#实现)

    我们在进行C#项目Xml读写开发时经常遇到一些读写问题,今天我要介绍的是遇到多个命名空间xmlns属性时如何读写此类文件. 比如下面这个Xml文件: <?xml version="1. ...