鄰接矩陣基礎的Prime演算法(最小生成矩陣)
阿新 • • 發佈:2019-02-01
演算法描述:
普利姆演算法求最小生成樹時候,和邊數無關,只和定點的數量相關,所以適合求稠密網的最小生成樹,時間複雜度為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; }