#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算法代碼(註釋詳細,已調試)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.