C++实现Prim算法
闲来无聊,前两天看到一篇关于算法实现的文章。里面又关于图的各种算法介绍,正好上学期还学过图论,现在还记得一点点,先来实现个prim算法:
表示图的文件的内容大体上是这样的:
2.0 1.0 1.0
3.0 1.0 1.0
4.0 1.0 1.0
5.0 1.0 1.0
6.0 1.0 1.0
7.0 1.0 1.0
8.0 1.0 1.0
9.0 1.0 1.0
11.0 1.0 1.0
12.0 1.0 1.0
13.0 1.0 1.0
14.0 1.0 1.0
18.0 1.0 1.0
20.0 1.0 1.0
22.0 1.0 1.0
32.0 1.0 1.0
34.0 10.0 1.0
34.014. 1.0
33.0 15.0 1.0
34.0 15.0 1.0
33.0 16.0 1.0
34.0 16.0 1.0
33.0 19.0 1.0
34.0 19.0 1.0
3.0 2.0 1.0
4.0 2.0 1.0
8.0 2.0 1.0
14.0 2.0 1.0
18.0 2.0 1.0
20.0 2.0 1.0
22.0 2.0 1.0
31.0 2.0 1.0
34.0 20.0 1.0
33.0 21.0 1.0
34.0 21.0 1.0
33.0 23.0 1.0
34.0 23.0 1.0
26.0 24.0 1.0
28.0 24.0 1.0
30.0 24.0 1.0
33.0 24.0 1.0
34.0 24.0 1.0
26.0 25.0 1.0
28.0 25.0 1.0
32.0 25.0 1.0
32.0 26.0 1.0
30.0 27.0 1.0
34.0 27.0 1.0
34.0 28.0 1.0
32.0 29.0 1.0
34.0 29.0 1.0
4.0 3.0 1.0
8.0 3.0 1.0
9.0 3.0 1.0
10.0 3.0 1.0
14.0 3.0 1.0
28.0 3.0 1.0
29.0 3.0 1.0
33.0 3.0 1.0
33.0 30.0 1.0
34.0 30.0 1.0
33.0 31.0 1.0
34.0 31.0 1.0
33.0 32.0 1.0
34.0 32.0 1.0
34.0 33.0 1.0
8.0 4.0 1.0
13.0 4.0 1.0
14.0 4.0 1.0
7.0 5.0 1.0
11.0 5.0 1.0
7.0 6.0 1.0
11.0 6.0 1.0
17.0 6.0 1.0
17.0 7.0 1.0
31.0 9.0 1.0
33.0 9.0 1.0
34.0 9.0 1.0
注意,从左到右分别是当前节点,连接的节点,边的权重,下面首先就是设计数据结构了:
class Pair { //pair代表了与某个点相连的一条边的权重
private: //,以及和这条变相连的另一个顶点是哪个
double edge_weight;
int adacent_vertex;
public:
Pair(int, double);
double weight() const;
int vertex() const;
};
上面的pair代表一个点相邻的边的权重以及这条边与哪一个顶点是相连的。
class Node { //代表了一个节点,其包含的信息有与其相连的
private: //某一条边的权重以及和这条边相连的另一个顶点。
Pair element;
Node *next_node;
public:
Node(Pair e, Node * = NULL);
Pair retrieve() const;
Node *next() const;
};
代表一个节点,注意这个节点的next_node的值与相邻节点没有任何关系,只是代表链表的下一个节点,下面介绍的是链表:
class List { //List中存放的是每个具体的节点,
private: //每个节点后面的链表代表的是与其相邻接的节点
Node *list_head;
public:
List();
// Accessors
bool empty() const;
Pair front() const;
Node *head() const;
void push_front(Pair);
Pair pop_front();
void print();
};
下面的cell实际上代表的就是一颗生成树了:
class Cell { //cell代表的就是一个具体的生成树了
private:
bool visited;
double distance;
int parent;
public:
Cell(bool = false, double = INFTY, int = );
bool isvisited() const;
double get_distance() const;
int get_parent() const;
};
-----------------------------------------------------------------------------------------------------------
下面是数据结构的具体定义了:
#include "structure.h" Pair::Pair(int e, double m) :
edge_weight(m),
adacent_vertex(e) {
// empty constructor
} double Pair::weight()const {
return edge_weight;
}
int Pair::vertex()const {
return adacent_vertex;
} Node::Node(Pair e, Node *n) :
element(e),
next_node(n) {
// empty constructor
} Pair Node::retrieve() const{
return element;
}
Node *Node::next() const {
return next_node;
} List::List() :list_head(NULL) {
// empty constructor
} bool List::empty() const {
if (list_head == NULL) {
return true;
}
else {
return false;
}
} Node *List::head() const {
return list_head; } Pair List::front() const { if (empty()) {
cout << "error! the list is empty";
}
return head()->retrieve();
} void List::push_front(Pair e) {
if (empty()) {
list_head = new Node(e, NULL);
}
else {
list_head = new Node(e, head());
} } Pair List::pop_front() {
if (empty()) {
cout << "error! the list is empty";
}
Pair e = front();
Node *ptr = list_head;
list_head = list_head->next();
delete ptr;
return e; } void List::print() {
if (empty()) {
cout << "empty" << endl;
}
else {
for (Node *ptr = head(); ptr != NULL; ptr = ptr->next())
{
cout << "<" << ptr->retrieve().vertex() << " " << ptr->retrieve().weight() << "> ";
}
cout << endl;
}
} Cell::Cell(bool v, double d, int p) :
visited(v),
distance(d),
parent(p) {
// empty constructor
} bool Cell::isvisited() const {
return visited;
} double Cell::get_distance()const {
return distance;
}
int Cell::get_parent()const {
return parent;
}
好了有了上面的数据结构,实现Prim算法就比较简单了:
Cell* Prim(List * graph, int n, int start) //传入一个邻接数组,以及数组的大小,
{ //以及邻接矩阵的起始点,求一个最小生成树
Cell* Table = new Cell[n + ]; //n+1的目的是节点是从1开始数的,所以要多添加一个
//Table[start]=Cell(false,0,0);//这里的false是否换成True会好一点?
Table[start] = Cell(true, , );
/* 实现prim算法*/
int currMinNode, currParent = ;
double currMin;
for (;;){
currMin = INFTY; //注意这个的类型是double类型
currMinNode = ;
currParent = ;
for (int i = ; i <= n; ++i){
if (Table[i].isvisited()){//已经被访问过了
Node * currNode = graph[i].head();
while (currNode != NULL){ //从该节点开始,然后访问其所有的邻接的节点
int tmpNode = currNode->retrieve().vertex();
double tmpWeight = currNode->retrieve().weight();
if (!Table[tmpNode].isvisited() && tmpWeight < currMin){
currMin = tmpWeight;
currMinNode = tmpNode;
currParent = i;
}
currNode = currNode->next(); //取下一个邻接的节点
}
}
else
continue; }
Table[currMinNode] = Cell(true, currMin, currParent);//找到下一个节点,将其置为True
if (currMinNode == ) //如果所有的节点都已经遍历完毕的话,就停止下一次的寻找
break; }
return Table;
}
顺手写个打印生成树的函数:
void PrintTable(Cell* Table, int n)
{
for (int i = ; i <= n; i++)
cout << Table[i].isvisited() << " " <<
Table[i].get_distance() << " " <<
Table[i].get_parent() << endl;
}
主函数如下所示:
#include "structure.h"
#include "Prim.h"
int main()
{
List * graph = new List[N];
char *inputfile = "primTest.txt";
ifstream fin; //输入文件 .join后结果
int n = ;
double x, y, w;
fin.open(inputfile);
while (!fin.eof())
{
fin >> x >> y >> w;
Pair a(y, w);
Pair b(x, w);
graph[int(x)].push_front(a);
graph[int(y)].push_front(b);
if (n <= x)
n = x;
if (n <= y)
n = y;
}
fin.close();
cout << "The total Node number is "
<< n << endl;
for (int i = ; i <= n; i++)
graph[i].print(); Cell* Table = Prim(graph, n, );
cout << "-----------------------\n";
PrintTable(Table, n); return ;
}
最后的结果如下所示:

写的有点乱,见谅见谅
其实这个也可以实现Dijkstra算法,那个好像没学过,看看以后有时间再来写。
C++实现Prim算法的更多相关文章
- 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用
图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...
- 最小生成树のprim算法
Problem A Time Limit : 1000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Sub ...
- 数据结构代码整理(线性表,栈,队列,串,二叉树,图的建立和遍历stl,最小生成树prim算法)。。持续更新中。。。
//归并排序递归方法实现 #include <iostream> #include <cstdio> using namespace std; #define maxn 100 ...
- 最小生成树——prim算法
prim算法是选取任意一个顶点作为树的一个节点,然后贪心的选取离这棵树最近的点,直到连上所有的点并且不够成环,它的时间复杂度为o(v^2) #include<iostream>#inclu ...
- 洛谷 P3366 【模板】最小生成树 prim算法思路 我自己的实现
网上有很多prim算法 用邻接矩阵 加什么lowcost数组 我觉得不靠谱 毕竟邻接矩阵本身就不是存图的好方法 所以自己写了一个邻接表(边信息表)版本的 注意我还是用了优先队列 每次新加入一个点 ...
- 最小生成树算法——prim算法
prim算法:从某一点开始,去遍历相邻的边,然后将权值最短的边加入集合,同时将新加入边集中的新点遍历相邻的边更新边值集合(边值集合用来找出新的最小权值边),注意每次更新都需将cost数组中的点对应的权 ...
- 贪心算法-最小生成树Kruskal算法和Prim算法
Kruskal算法: 不断地选择未被选中的边中权重最轻且不会形成环的一条. 简单的理解: 不停地循环,每一次都寻找两个顶点,这两个顶点不在同一个真子集里,且边上的权值最小. 把找到的这两个顶点联合起来 ...
- Prim算法(三)之 Java详解
前面分别通过C和C++实现了普里姆,本文介绍普里姆的Java实现. 目录 1. 普里姆算法介绍 2. 普里姆算法图解 3. 普里姆算法的代码说明 4. 普里姆算法的源码 转载请注明出处:http:// ...
- Prim算法(二)之 C++详解
本章是普里姆算法的C++实现. 目录 1. 普里姆算法介绍 2. 普里姆算法图解 3. 普里姆算法的代码说明 4. 普里姆算法的源码 转载请注明出处:http://www.cnblogs.com/sk ...
- Prim算法(一)之 C语言详解
本章介绍普里姆算法.和以往一样,本文会先对普里姆算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 普里姆算法介绍 2. 普里姆算法图解 3. 普里 ...
随机推荐
- Spring MVC 复习笔记02
1. 非注解的处理器映射器和适配器 1.1 非注解的处理器映射器 处理器映射器:org.springframework.web.servlet.handler.BeanNameUrlHandlerMa ...
- win764位英文版系统unicode编码问题
出现的编码现象: 1.以*.vga格式的课件文件,当作好可读html之后,仍然不能播放,此时为Unicode编码所致: 2.在编辑TXT文档时,内容凡有中文,在保存时,会提示不能识别,当确认后,中文字 ...
- v4l2的学习建议和流程解析
v4l2,一开始听到这个名词的时候,以为又是一个很难很难的模块,涉及到视频的处理,后来在网上各种找资料后,才发现其实v4l2已经分装好了驱动程序,只要我们根据需要调用相应的接口和函数,从而实现视频的获 ...
- Java 线程池Future和FutureTask
Future表示一个任务的周期,并提供了相应的方法来判断是否已经完成或者取消,以及获取任务的结果和取消任务. Future接口源码: public interface Future<V> ...
- Xcode Missing file的解决方案
因为没在工程里面删除文件,导致Xcode报了一大堆警告,都是Missing file的警告,研究了一下,下面是我的解决方案: Missing file出现的原因 原因就是你在文件里面删除了文件,但是在 ...
- Oracle SQL Developer 编辑区不能删除,后退,空格,复制粘贴等功能都失效的解决办法
Oracle SQL Developer 编辑区不能删除,后退,空格,复制粘贴等功能都失效的解决办法 解决: 打开菜单并选择Tools-prefrence-Accelerators-Load Pres ...
- 在Windows下使用Navicat连接Linux下的MySql
Linux下的Mysql安装可以参考菜鸟教程:https://www.runoob.com/mysql/mysql-install.html 安装完成后你会发现用Navicat链接MySql会失败,这 ...
- Nodejs V8引擎 fast property lookup
前言 之所以会研究这个东西,是我在网上找了一下各个语言的执行效率比较.好吧,我承认这是个无聊的东西,不过看看总是无妨,然而我惊讶的发现,有些测试声称Java,C,Nodejs是处在同一个效率级别参见链 ...
- 【cs231n】神经网络笔记笔记2
) # 对数据进行零中心化(重要) cov = np.dot(X.T, X) / X.shape[0] # 得到数据的协方差矩阵 数据协方差矩阵的第(i, j)个元素是数据第i个和第j个维度的协方差. ...
- 【转】jQuery的attr与prop
原文:<jQuery的attr与prop> jQuery1.6中新添加了一个prop方法,看起来和用起来都和attr方法一样,这两个方法有什么区别呢?这要从HTMl 的attribute与 ...