//实现文件
#include <queue>
#include <vector>
#include <list>
#include <cassert>
#include <iostream>
using namespace std;
//用STL中的优先队列实现
namespace prim_priority
{
const static int MAX_VERTEX_NUM = 100;
const static int INVALID_VNAME = -1;
const static double INVALID_LENGTH = 10000.0;
typedef struct _Node
{
int vname;
int vname_pre;
double len;
_Node(void)
{
vname = INVALID_VNAME;
vname_pre = INVALID_VNAME;
len = INVALID_LENGTH;
}
_Node(int v, int v_pre, double l):vname(v),vname_pre(v_pre),len(l){}
}Node, *pNode;
class Cmp
{
public:
bool operator()(const Node &l, const Node &r)
{
return l.len > r.len;
}
};
vector< list<Node> > vGraph; //graph
vector<Node> vPath;
double iMinPathLen; //min tree path length
int iVertexNum;
double Prim(void)
{
iVertexNum = vGraph.size()-1;
assert(iVertexNum<MAX_VERTEX_NUM);
vPath.clear();
iMinPathLen = 0;
priority_queue< Node, vector<Node>, Cmp > pq;
bool used[MAX_VERTEX_NUM];
memset(used, false, sizeof(used));
int iUsedNum(0), iCurVertex(1);
Node tmp;
iUsedNum = 1;
used[iCurVertex] = true;
while ( iUsedNum<iVertexNum )
{
for ( list<Node>::iterator it=vGraph[iCurVertex].begin();
it!=vGraph[iCurVertex].end(); ++it)
{
if ( !used[it->vname])
pq.push(*it);
}
while (!pq.empty() && !(used[(Node(pq.top())).vname_pre] && !used[(Node(pq.top())).vname]) )
pq.pop();
if (pq.empty())
break;
tmp = pq.top();
pq.pop();
vPath.push_back(tmp);
iMinPathLen += tmp.len;
used[tmp.vname] = true;
iCurVertex = tmp.vname;
++iUsedNum;
}
return iMinPathLen;
}
void PrintMinPath(void)
{
cout << "minpath: " << iMinPathLen << endl;
}
void PrintPath(void)
{
cout << "path selection process" << endl;
for ( unsigned int i=0; i<vPath.size(); ++i )
cout << vPath[i].vname_pre << "-->" << vPath[i].vname
<< "("<< vPath[i].len <<")" << endl;
}
void PrintResult(void)
{
PrintPath();
PrintMinPath();
}
void PrintGraph(void)
{
cout << "graph:" << endl;
int i(1);
vector<list<Node> >::iterator it=vGraph.begin();
for ( ++it; it!=vGraph.end(); ++it)
{
cout << i << ": ";
for ( list<Node>::iterator l=(*it).begin();l!=(*it).end(); ++l)
cout << l->vname << "("<< l->len << ") ";
cout << endl;
++i;
}
}
};
//普通实现方式
namespace prim_simple
{
const static int MAX_VERTEX_NUM = 100;
const static int INVALID_VERTEX = -1;
const static double INVALID_WEIGHT = 100000.0;
typedef struct _TreeEdge
{
int v1;
int v2;
double w;
_TreeEdge(int _v1, int _v2, double _w):v1(_v1), v2(_v2), w(_w){}
_TreeEdge(void)
{
v1 = v2 = INVALID_VERTEX;
w = INVALID_WEIGHT;
}
}TreeEdge;
typedef struct _ChosenEdge
{
int v2;
double w;
_ChosenEdge(void)
{
v2 = INVALID_VERTEX;
w = INVALID_WEIGHT;
}
}ChosenEdge;
double vGraph[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
TreeEdge vMSTree[MAX_VERTEX_NUM];
ChosenEdge vCEdge[MAX_VERTEX_NUM];
bool vbInTree[MAX_VERTEX_NUM];
int iVertexNum;
double dMinWPath;
double Prim(void)
{
//init
memset( vbInTree, false, sizeof(vbInTree));
dMinWPath = 0.0;
assert(iVertexNum>0 && iVertexNum<MAX_VERTEX_NUM);
int i(1);
for ( ;i<iVertexNum; ++i )
{
vCEdge[i].v2 = 1;
vCEdge[i].w = vGraph[i][1];
}
vMSTree[1].v1 = 1;
vMSTree[1].v2 = 0;
vMSTree[1].w = -1.0;
vbInTree[1] = true;
//calc
int j(0), k(0);
for ( i=2; i<=iVertexNum; ++i)
{
for ( k=1; k<=iVertexNum && vbInTree[k]; ++k);
if ( k>iVertexNum )
break;
for ( j=k; j<=iVertexNum; ++j)
{
if ( !vbInTree[j] && vCEdge[k].w>vCEdge[j].w )
k = j;
}
//add
vMSTree[i].v1 = k;
vMSTree[i].v2 = vCEdge[k].v2;
vMSTree[i].w = vCEdge[k].w;
dMinWPath += vCEdge[k].w;
vbInTree[k] = true;
//adjust
for ( j=1; j<=iVertexNum; ++j )
{
if ( !vbInTree[j] && vCEdge[j].w>vGraph[j][k])
{
vCEdge[j].w = vGraph[j][k];
vCEdge[j].v2 = k;
}
}
}
return dMinWPath;
}
void PrintMinPath(void)
{
cout << "minpath: " << dMinWPath << endl;
}
void PrintPath(void)
{
cout << "path selection process" << endl;
for ( int i=1; i<=iVertexNum; ++i )
{
cout << vMSTree[i].v2 << "-->" << vMSTree[i].v1
<< "("<< vMSTree[i].w <<")" << endl;
}
}
void PrintResult(void)
{
PrintPath();
PrintMinPath();
}
void PrintGraph(void)
{
cout << "graph:" << endl;
for (int i=1; i<=iVertexNum; ++i)
{
cout << i <<": ";
for ( int j=1; j<=iVertexNum; ++j)
{
if ( vGraph[j][i]<INVALID_WEIGHT )
{
cout<< j <<"(" << vGraph[j][i] << ") ";
}
}
cout << endl;
}
}
void PrintAll(void)
{
PrintGraph();
PrintResult();
}
};
//测试文件
#include <iostream>
#include <cstdlib>
#include "Prim.h"
using namespace std;
int main()
{
//测试优先队列实现的Prim算法
{
using namespace prim_priority;
cout << "prim_priority" << endl;
list<Node> l;
//v0
l.push_back(Node(-1, 0, -1));
vGraph.push_back(l);
//v1
l.clear();
l.push_back(Node(2, 1, 2));
l.push_back(Node(3,1, 4));
l.push_back(Node(4,1, 1));
vGraph.push_back(l);
//v2
l.clear();
l.push_back(Node(1,2, 2));
l.push_back(Node(4,2, 3));
l.push_back(Node(5,2, 10));
vGraph.push_back(l);
//v3
l.clear();
l.push_back(Node(1,3, 4));
l.push_back(Node(4, 3,2));
l.push_back(Node(6,3, 5));
vGraph.push_back(l);
//v4
l.clear();
l.push_back(Node(1, 4,1));
l.push_back(Node(2, 4,3));
l.push_back(Node(3, 4,2));
l.push_back(Node(5,4, 7));
l.push_back(Node(6, 4,8));
l.push_back(Node(7, 4,4));
vGraph.push_back(l);
//v5
l.clear();
l.push_back(Node(2, 5,10));
l.push_back(Node(4, 5,7));
l.push_back(Node(7, 5,6));
vGraph.push_back(l);
//v6
l.clear();
l.push_back(Node(3, 6,5));
l.push_back(Node(4, 6,8));
l.push_back(Node(7, 6,1));
vGraph.push_back(l);
//v7
l.clear();
l.push_back(Node(4, 7,4));
l.push_back(Node(5, 7,6));
l.push_back(Node(6, 7,1));
vGraph.push_back(l);
Prim();
PrintGraph();
PrintResult();
}
cout << endl;
//测试普通方式实现的Prim算法
{
using namespace prim_simple;
cout << "prim_simple" << endl;
iVertexNum = 7;
for ( int i=0; i<MAX_VERTEX_NUM*MAX_VERTEX_NUM; ++i)
vGraph[i/MAX_VERTEX_NUM][i%MAX_VERTEX_NUM] = INVALID_WEIGHT;
//v1
vGraph[2][1] = 2;
vGraph[3][1] = 4;
vGraph[4][1] = 1;
//v2
vGraph[1][2] = 2;
vGraph[4][2] = 3;
vGraph[5][2] = 10;
//v3
vGraph[1][3] = 4;
vGraph[4][3] = 2;
vGraph[6][3] = 5;
//v4
vGraph[1][4] = 1;
vGraph[2][4] = 3;
vGraph[3][4] = 2;
vGraph[5][4] = 7;
vGraph[6][4] = 8;
vGraph[7][4] = 4;
//v5
vGraph[2][5] = 10;
vGraph[4][5] = 7;
vGraph[7][5] = 6;
//v6
vGraph[3][6] = 5;
vGraph[4][6] = 8;
vGraph[7][6] = 1;
//v7
vGraph[4][7] = 4;
vGraph[5][7] = 6;
vGraph[6][7] = 1;
Prim();
PrintAll();
}
system("pause");
return 0;
}