【1】什么是最小生成树?

对于连通的带权图(连通网)G,其生成树也是带权的。

生成树T各边的权值总和称为该树的权。

权最小的生成树称为G的最小生成树(Minimum SpannirngTree)。简记为MST。

注意:最小是指权值最小

一个连通图的生成树是一个极小的连通子图,它包含全部的顶点,但只有足以构成一棵树的n-1条边。

求最小生成树有两种算法:普里姆算法和克鲁斯卡尔算法

不好理解?看不懂?能通俗点不?看个实例哈:

假设你是电信实施工程师,需要为一个镇的九个村庄架设通信网络做设计。

村庄位置大致如下图,之间连线的数字表示村与村间的可通达直线距离。

你们领导要求你必须用最小的成本完成这次任务。你说怎么办?

好,这就是很现实的一个最小生成树案例。且听下面详解。

【2】普里姆算法

利用 普里姆算法 要解决如上问题,首先我们构造图的邻接矩阵。如下图所示:

注意:实际中我们用65535来代表无穷大。

关于普里姆算法以及讲解如下图:

针对上面我们遇到的实际案例,普里姆算法执行循环过程如下图:

每次所选最小边分别如 图1-图8 所示:

最后用所有边把各个顶点连通也就是所谓的最小生成树。

【3】普里姆算法的实现

实现代码如下:

  1 #include <iostream>
  2 #include "SeqList.h"
  3 #include <iomanip>
  4 using namespace std;
  5
  6 #define  INFINITY  65535
  7
  8 template<class NameType, class DistType>
  9 class Graph
 10 {
 11 private:
 12     SeqList<NameType> Vertices;
 13     DistType **Edges;
 14     int nVer, nEdges;
 15
 16 public:
 17     Graph()
 18         : Edges(NULL)
 19         , nEdges(0)
 20         , nVer(0)
 21     {}
 22     ~Graph()
 23     {}
 24
 25 public:
 26
 27     istream & operator>>(istream &in)
 28     {
 29         int v, u, value;
 30         int i, j;
 31         NameType item;
 32         cout << "请输入顶点的个数: " << endl;
 33         in >> nVer;
 34         cout << "请输入顶点的数据信息: " << endl;
 35         for (i = 0; i < nVer; ++i)
 36         {
 37             in >> item;
 38             Vertices.push_back(item);    // 保存全部顶点
 39         }
 40         /////二维数组的创建并初始化
 41         Edges = new DistType*[nVer]; // DistType *ar[10];
 42         for (i = 0; i < nVer; ++i)
 43         {
 44             Edges[i] = new DistType[nVer];
 45             for (j = 0; j < nVer; ++j)
 46             {
 47                 Edges[i][j] = 0;
 48             }
 49         }
 50         cout << "请输入边的个数: " << endl;
 51         in >> nEdges;
 52         cout << "请输入边的信息:" << endl;
 53         for (i = 0; i < nEdges; ++i)
 54         {
 55             in >> v >> u >> value;
 56             Edges[v][u] = value;
 57             Edges[u][v] = value;
 58         }
 59         return in;
 60     }
 61     ostream & operator<<(ostream &out) const
 62     {
 63         int i, j;
 64         out << "顶点信息 " << endl;
 65         for (i = 1; i <= nVer; ++i)
 66         {
 67             out << Vertices[i] << setw(5);
 68         }
 69         out << endl;
 70         out << "矩阵信息:" << endl;
 71         out << setw(10);
 72         for (i = 1; i <= nVer; ++i)
 73         {
 74             out << Vertices[i] << setw(5);
 75         }
 76         out << endl;
 77         for (i = 0; i < nVer; ++i)
 78         {
 79             out << Vertices[i+1] << setw(5);
 80             for (j = 0; j < nVer; ++j)
 81             {
 82                 if (0 == Edges[i][j] && i != j)
 83                     Edges[i][j] = INFINITY;
 84                 cout << Edges[i][j] << setw(5);
 85             }
 86             out << endl;
 87         }
 88         out << endl;
 89
 90         return out;
 91     }
 92     //  图采用邻接矩阵存储  最小生成树 普里姆算法
 93     void MiniSpanTree()
 94     {
 95         int min = 0, i = 0, j = 0, k = 0;
 96         int* adjvex = new  int[nVer];    // 保存相关顶点下标
 97         int* lowcost = new int[nVer];    // 保存相关顶点间边的权值
 98         lowcost[0] = 0;         // 初始化第一个权值为0,即V0已加入生成树
 99         //lowcost的值为0,在这里就是此下标的顶点已经加入生成树
100         adjvex[0] = 0;          // 初始化第一个顶点下标为0
101
102         for (i = 1; i < nVer; ++i)  //循环除过下标为0外的全部顶点
103         {
104             lowcost[i] = Edges[0][i];  // 将v0顶点与之有边的权值存入数组
105             adjvex[i] = 0;             // 并初始化都为v0的下标
106         }
107
108         for (i = 1; i < nVer; ++i)
109         {
110             min = INFINITY;  // 初始化最小权值为常数,通常设置为不可能到达的数值
111             k = 0;    // 复位
112
113             for (j = 1; j < nVer; ++j)
114             {
115                 // 如果两个顶点之间存在边有权值,不为0并且小于min
116                 if (lowcost[j] != 0 && lowcost[j] < min)
117                 {
118                     min = lowcost[j];  // 缓存最小值
119                     k = j;    // 将当前最小值的下标缓存入k
120                 }
121             }
122             cout << "("<< adjvex[k] << "," << k << ")" << endl;   //打印当前顶点边中权值最小的边
123             lowcost[k] = 0;                     // 将当前顶点的权值设为0,表示此顶点已经完成任务
124
125             for (j = 1; j < nVer; ++j)  // 循环所有节点
126             {
127                 if (lowcost[j] != 0 && Edges[k][j] < lowcost[j])
128                 {  // 若下标为k顶点各边权值小于此前这些顶点未被加入生成树权值
129                     lowcost[j] = Edges[k][j]; // 用较小者替换
130                     adjvex[j] = k;  // 将下标为k的顶点存入adjvex
131                 }
132             }
133         }
134
135         delete []adjvex;
136         delete []lowcost;
137         adjvex = NULL;
138         lowcost = NULL;
139     }
140 };
141
142 template<class NameType, class DistType>
143 istream & operator>>(istream &in, Graph<NameType,DistType> &g)
144 {
145     g >> in;
146     return in;
147 }
148
149 template<class NameType, class DistType>
150 ostream & operator<<(ostream &out, const Graph<NameType,DistType> &g)
151 {
152     g << out;
153     return out;
154 }
155
156 void main()
157 {
158     Graph<char, int> myg;
159     cin >> myg;
160     cout << "打印所有输入信息:" << endl;
161     cout << myg << endl;
162     cout << "最小生成树边信息如下:" << endl;
163     myg.MiniSpanTree();
164     cout << endl;
165 }

View Code

代码中所引用是头文件SeqList.h从随笔《顺序表》拷贝即可,也可以自己另行处理。

Good  Good  Study,  Day  Day  Up.

顺序   选择   循环   总结

转载于:https://www.cnblogs.com/Braveliu/p/3457262.html

数据结构图之二(最小生成树--普里姆算法)相关推荐

  1. 最小生成树(普里姆算法【Prim】与克鲁斯卡尔算法【Kruskal】)

    写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站.博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事 ...

  2. 最小生成树——普里姆算法和克鲁斯卡尔算法

    最小生成树 用来解决工程中的代价问题. 一:普里姆算法 具体代码用C语言实现如下: typedef int VRType;typedef char InfoType;#define MAX_NAME ...

  3. 学懂最小生成树(普里姆算法)

    最小生成树,初学者可能会学的感觉云里雾里,不要怕,小编带大家搞懂它! 目录 一.概念介绍 二.实现原理 三.代码实现 一.概念介绍 最小生成树就是在一个图中找到能过一次性穿过所有顶点的最小路径. 上图 ...

  4. 最小生成树普里姆算法c语言代码,普里姆算法生成最小生成树-C语言描述.doc

    PAGE JIN JINGCHU UNIVERSITY OF TECHNOLOGY <数据结构(C语言描述)> 课程设计 学 院 计算机工程学院 班 级 12级软件技术1班 学 号 201 ...

  5. 最小生成树 普里姆算法

    题目来源  POJ2349 在介绍什么是最小生成树之前先介绍什么是加权图 在之前已经默认了解了无向图(并查集)以及有向无环图(拓扑排序),那么最小生成树可以理解是一个加权的无向图,那么我们要坐的就是在 ...

  6. (数据结构)图的最小生成树 普里姆算法(Prim)

    假设要在n个城市之间建立通信联络网,每两个城市之间建立线路都需要花费不同大小的经费,则连通n个城市只需要n-1个条线路,最小生成树解决的问题就是:如何在最节省经费的前提下建立这个通信网 也可以理解为: ...

  7. USACO 3.1 Agri-Net 最短网络 (最小生成树)(普里姆算法)

    题意 农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当然,他需要你的帮助.约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场.为了用最 ...

  8. 最小生成树普里姆算法Prim

    目录 前言 一.Prim算法的基本思路 二.代码实现 总结 前言   无论是什么程序都要和数据打交道,一个好的程序员会选择更优的数据结构来更好的解决问题,因此数据结构的重要性不言而喻.数据结构的学习本 ...

  9. prim算法(普里姆算法)详解

    prim算法(普里姆算法)详解 了解了什么是最小生成树后,本节为您讲解如何用普里姆(prim)算法查找连通网(带权的连通图)中的最小生成树. 普里姆算法查找最小生成树的过程,采用了贪心算法的思想.对于 ...

  10. 644-最小生成树Prim普里姆算法

    最小生成树Prim普里姆算法理论 最小生成树的应用场景:顶点代表城市的话,比如说修路,架设电线,网络,怎么让这几个城市连起来,而且花费是最小的,成本最低,权值是最小的,但是不允许形成环路. 第一步的U ...

最新文章

  1. Docker4Dev #7 新瓶装老酒 – 使用 Windows Container运行ASP.NET MVC 2 + SQLExpress 应用
  2. 创新工场董事长兼首席执行官 李开复 发 言 稿
  3. Team Foundation Server的回滚操作
  4. C语言fread和fwrite的用法详解
  5. php5.5 反序列化利用工具_Yii框架反序列化RCE利用链2
  6. 简练软考知识点整理-建设项目团队
  7. jQuery学习笔记03
  8. Spring Cloud微服务分布式云架构源码结构
  9. 20190618每日一句
  10. CSDN如何获得积分?
  11. 根据日期获取周数的计算
  12. 关于计算机论文摘要和引言,论文摘要和背景的区别_论文前言与摘要的区别_引言和摘要有什么区别...
  13. 手把手教你搭建DHCP服务器
  14. 片段音乐歌词生成工具
  15. 丐帮 beggar gangs
  16. 录音笔新燃点:AI+创新 实现应用场景再迭代
  17. iOS微信网页长按图片问题解决
  18. ES中如何实现随机抽样查询
  19. mo-quarter-picker:基于 Vue2 和 ElementUI 的季度范围选择器
  20. 最简单易用且强大的交易策略生成工具

热门文章

  1. 马尾物联网企业主导或参与制定修订各级标准达60项
  2. python 的for与while 的i改变
  3. Silverlight 简介 Part.1(理解 Siverlight)
  4. [Publish AAR To Maven] 使用 Gradle 发布 AAR 到 Maven 仓库
  5. Stylus Loader has been initialized using an options object that does not match the API schema.
  6. 对Object.prototype.toString.call(obj)的理解
  7. vue学习笔记-10-常用特性之表单操作
  8. MongoDB学习(黑马教程)-4-数据库MongoDB的更新(修改)文档操作
  9. js高级学习笔记(b站尚硅谷)-6-IIFE
  10. python监控钉钉群消息_使用python对mysql主从进行监控,并调用钉钉发送报警信息...