算法描述:
普利姆算法求最小生成樹時候,和邊數無關,只和定點的數量相關,所以適合求稠密網的最小生成樹,時間複雜度爲O(n*n)。
算法過程:
1.將一個圖的頂點分爲兩部分,一部分是最小生成樹中的結點(A集合),另一部分是未處理的結點(B集合)。
2.首先選擇一個結點,將這個結點加入A中,然後,對集合A中的頂點遍歷,找出A中頂點關聯的邊權值最小的那個(設爲v),將此頂點從B中刪除,加入集合A中。
3.遞歸重複步驟2,直到B集合中的結點爲空,結束此過程。
4.A集合中的結點就是由Prime算法得到的最小生成樹的結點,依照步驟2的結點連接這些頂點,得到的就是這個圖的最小生成樹。
以下的代碼是從一個輸入文件:名爲test.txt文件中讀出節點和節點間的權重,通過prime算法找到最小生成樹集合,輸出和輸入格式相同。
下面給出輸入範例:
第一行是節點數,從第二行開始是: 節點1 節點2 節點1和節點2直接的pathCost。
6
0 1 0.2
1 2 0.3
2 3 0.4
3 4 0.5
4 2 0.6
4 5 0.4
5 3 0.5
5 1 0.1
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <climits>
#include<cmath>
#include <ctime>
#include <fstream>
#include <vector>
#include <sys/stat.h>
#include<algorithm>
using namespace std;
#define MAX_SIZE 1000
float map[MAX_SIZE][MAX_SIZE], pathWeight[MAX_SIZE];
float sum;
bool visit[MAX_SIZE];
int nodeNum, edgeNum;
FILE *fp;
FILE *newfp;
string fileName, newFileName ;
int getNumberOfNodes()
{
int verticeNum;
fp=fopen(fileName.c_str(),"rt+");
if(fp==NULL) cout<<"no file "<<endl;
fscanf(fp,"%d\n",&verticeNum);
fclose(fp);
cout<<" the node number is "<<verticeNum<<endl;
return verticeNum;
}
int getNumberOfEdges()
{
char flag;
int edgeNum,count;
fp=fopen(fileName.c_str(),"rt+");
while(!feof(fp)){
flag=fgetc(fp);
if(flag=='\n') count++ ;
}
edgeNum=count;
fclose(fp);
cout<<" the edge number is "<<edgeNum<<endl;
return edgeNum;
}
void readFile()
{
fp=fopen(fileName.c_str(),"rt+");
fscanf(fp,"%d\n",&nodeNum);
//int nodeNum=getNumberOfNodes();
float weight;
int a,b;
for( int i=1;i<=edgeNum;i++)
{
fscanf(fp,"%d%d%f\n",&a,&b,&weight);
cout<<a<<" "<<b<<" "<<weight<<endl;
if(weight<map[a][b])
{
map[a][b]=map[b][a]=weight;
}
}
fclose(fp);
}
void initialMap()
{
for(int i=0;i<nodeNum;i++){
for(int j=0;j<nodeNum;j++){
map[i][j]=INT_MAX;
}
}
}
void prime()
{
newfp=fopen(newFileName.c_str(),"wt+");
int k;
float buffer;
sum=0;
//initial the original node collection
for(int i=0;i<nodeNum;i++){
visit[i]=false;
}
///////involve the 0 node into the MST collection ///////////////////
visit[0]=true;
///////////////find the path from 0 node to other nodes//////////////
for(int i=0;i<nodeNum;i++)
{
pathWeight[i]=map[0][i];
//cout<<"pathWeight"<<" "<< i <<" "<<pathWeight[i]<<endl;
}
for(int i=0;i<nodeNum;++i)
{
buffer=INT_MAX;//buffer is actually the key value of original nodes
for(int j=0;j<nodeNum;++j)
{
/////////////find the adjacent nodes of MST and update their key valves/////////////
if((!visit[j])&&(buffer>pathWeight[j]))
{
k=j;
//cout<<"pathweight k=j "<<pathWeight[k]<<endl;
buffer=pathWeight[k];
//cout<<"buffer is "<<buffer<<endl;
}
}
if(buffer==INT_MAX) break;
visit[k]=true;
sum+=buffer;
////////////////update the pathWeight[j]///////////////
for(int j=0;j<nodeNum;++j)
{
if((!visit[j])&&(pathWeight[j]>map[k][j]))
{
pathWeight[j]=map[k][j];
int tem;
if(k>j) {
tem=k;
k=j;
j=tem;
}
fprintf(newfp,"%d",k);
fputs(" ",newfp);
fprintf(newfp,"%d",j);
fputs(" ",newfp );
fprintf(newfp,"%f\n",map[k][j]);
cout<<"k "<<k<<" "<<"j "<<j<<endl;
cout<<"map[k][j] "<<map[k][j]<<endl;
}
}
}
fclose(newfp);
}
int main()
{
fileName="test.txt";
newFileName="result.txt";
cout<<"sum is "<<endl;
nodeNum=getNumberOfNodes();
edgeNum=getNumberOfEdges();
initialMap();
for(int i=0;i<10;i++){
cout<<map[i][2]<<endl;
}
readFile();
prime();
cout<<"sum is "<<sum<<endl;
}