#include<iostream>
#include<string>
#include<vector>
#include<math.h>
using namespace std;
//设为最大值的一半向下取整的值,使得两个最大值相加不会溢出
#define HALF_MAX floor(DBL_MAX/2)
void Prim(vector<bool>& visit, vector<double>& lowcost,
vector<int>& closest, vector<vector<double>>& c, int n) {
//设置vector容器大小
visit.resize(n + 1);
lowcost.resize(n + 1);
closest.resize(n + 1);
//初始化,S中只有第一个点
for (int i = 1; i <= n; ++i) {
//最短距离设为其它点到第一个点的距离(不相邻则为无穷大)
lowcost[i] = c[1][i];
closest[i] = 1;//初始情况下所有点的临界点均为第一个点
visit[i] = false;//所有点均未访问过
}
visit[1] = true;//访问第一个点
//访问除第1个点外的其它点,访问顺序跟序号无关
//访问第1个点的处理在初始化中已完成
for (int i = 2; i <= n; ++i) {
int j = 1;
//在未访问的点中,找出到达S距离最短的点
for (int k = 1; k <= n; ++k) {
//若k未被访问,且到达S的距离小于j,更新
if ((!visit[k]) && (lowcost[k] < lowcost[j]))
j = k;
}
visit[j] = true;//将j添加到S中
//更新添加j之后的lowcost[]和closest[]的值
for (int k = 1; k <= n; ++k) {
//若k未被访问,且 j到k的距离 小于 添加j之前k到S的距离,更新
if ((!visit[k]) && (c[j][k] < lowcost[k])) {
lowcost[k] = c[j][k];//更新最短距离
closest[k] = j;//更新k在S中的最近邻点
}
}
}
}
int main(void) {
//所有序号从1开始
int n = 4;//基站个数,在使用Prim函数之前已经传入数据
vector<vector<double>> c;//矩阵,在使用Prim函数之前已经传入数据
//每个点到达自己的距离设为无穷大(或者任意大于最大距离的值)
//否则会影响Prim()中访问点的选取
//每个点到达不相邻点的距离设为无穷大
vector<double> lowcost;//记录S外的点到S的最短距离
vector<int> closest;//记录S外的点在S中的距离最短的点
vector<bool> visit;//标记节点是否被访问
vector<int> ID;//基站ID
/*调试数据*/
double a[4][4] = { {HALF_MAX,2,HALF_MAX,HALF_MAX},{2,HALF_MAX,2,4},
{HALF_MAX,2,HALF_MAX,3},{HALF_MAX,4,3,HALF_MAX} };
c.resize(n + 1, (vector<double>)(n + 1));
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
c[i][j] = a[i-1][j-1];
}
}
Prim(visit, lowcost, closest, c, n);
int lowest_cost = 0;//最小生成树的代价
//由于S的初始化点(第一个点)到达自己的距离为无穷大,去掉这个数据,j从2开始
for (int j = 2; j < lowcost.size(); ++j) {
lowest_cost += lowcost[j];
}
cout << "最小生成树的代价为:" << lowest_cost << endl;
cout << "最小生成树的边为:" << endl;
//同理,去掉第一个点的数据,n个点,n-1条边
for (int j = 2; j <= n; ++j) {
cout << "\tV" << j << " ---- V" << closest[j] << endl;
}
return 0;
}
【C++】Prim算法代码(注释详细,已调试)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.