声明:图片及内容基于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. SwiftUI error All In One

    SwiftUI error All In One Instance member xxx cannot be used on type yyy Instance member 'game' canno ...

  2. JavaScript code 性能优化

    1 1 1 JavaScript 性能优化 prototype 闭包 Closure 内存泄漏 event system 1 定义类方法以下是低效的,因为每次构建baz.Bar的实例时,都会为foo创 ...

  3. autocode & API

    autocode & API https://autocode.com/app/ https://autocode.com/lib/ api-service https://dashboard ...

  4. 智能货柜 & 技术原理 (动态视觉识别 + 重力感应)

    智能货柜 & 技术原理 (动态视觉识别 + 重力感应) 智能货柜 拥有智能化.精细化运营模式的智能货柜成为代替无人货架继前进的方式. 相比无人货架来说,智能货柜的技术门槛更高,拥有 RFID. ...

  5. Linux & terminal color & command line color

    Linux & terminal color & command line color how to change Linux terminal color https://askub ...

  6. 如何导出android内部存储的文件(不用root)

    这段时间公司项目,涉及到数据缓存,由于需要缓冲的数据太多.太大,通过网络请求,再缓存到本地sqlite数据库,太费时间,消耗流量.所以准备先在本地保存一个标准版sqlite数据库(包含数据),打包到a ...

  7. 币圈沸腾!SPC空投上线!不要错过!

    币圈最近处于沸腾的时刻,NGK侧链代币SPC已上线钱包,3.0公链NGK生态之SPC空投又来了,NGK的上一个项目BGV投资收益率最高破一千七百倍,NGK官方此次以算力持有者为中心,将发起第二轮福利- ...

  8. Docker使用指南

    上文简单介绍了docker,这边记录一下docker的使用. 一.Docker启停 1.启动docker systemctl start docker 2.关闭docker systemctl sto ...

  9. winform导入excel或者csv

    if (txt01.Text != "") { this.lbzhantie.Items.Clear(); this.dtzhuanhuo.Rows.Clear(); if (tx ...

  10. 顶级c程序员之路 基础篇 - 第一章 关键字的深度理解 number-1

    c语言有32个关键字,每个关键字你都理解吗? 今天出场的是: auto ,  register,  static,   extern 为什么他们会一起呢,说到这里不得不谈到c语言对变量的描述. c给每 ...