1. 程式人生 > >鄰接矩陣基礎的Prime演算法(最小生成矩陣)

鄰接矩陣基礎的Prime演算法(最小生成矩陣)

演算法描述:

普利姆演算法求最小生成樹時候,和邊數無關,只和定點的數量相關,所以適合求稠密網的最小生成樹,時間複雜度為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;


}