1.首先将G的n个顶点看成n个孤立的连通分支(n个孤立点)并将所有的边按权从小大排序
2.裁取权值最小的边,如果加入此边后存在圈则这条边不加入,重复这个操作,直到加入n-1条边
#include <stdio.h>
#include <iostream>
#include <list>
#include <vector>
#include <queue>
#include <string>
using std::list;
using std::vector;
using std::queue;
using std::priority_queue;
using std::string;
using std::cout;
using std::endl;
class Edge
{
public:
Edge(int u, int v, double w)
{
if (u >= 0 && v >= 0)
{
this->u = u;
this->v = v;
this->weight = w;
}
}
double getWeight() { return weight; }
int either() { return u; }
int other(int p)
{
if (p == u)
return v;
else if (p == v)
return u;
}
string toString()
{
string str;
char result[64] = "";
sprintf(result, "%d -- %d : %8.3f\n", u, v, weight);
str = result;
return str;
}
private:
int u;
int v;
double weight;
};
class EdgeCmp
{
public:
bool operator() (Edge *p, Edge *q)
{
return p->getWeight() > q->getWeight();
}
};
class EdgeWeightedGraph
{
public:
EdgeWeightedGraph(int nVertex, int nEdge, int arr[][2], double weight[]);
~EdgeWeightedGraph();
int getV() { return V; }
list<Edge *> edges();
list<Edge *> getAdj(int v);
private:
int V;
int E;
list<Edge *> *adj;
};
EdgeWeightedGraph::EdgeWeightedGraph(int nVertex, int nEdge, int arr[][2], double weight[])
{
V = nVertex;
E = nEdge;
adj = new list<Edge *>[nVertex];
for (int i = 0; i < E; ++i)
{
Edge *e = new Edge(arr[i][0], arr[i][1], weight[i]);
adj[arr[i][0]].push_back(e);
adj[arr[i][1]].push_back(e);
}
}
EdgeWeightedGraph::~EdgeWeightedGraph()
{
list<Edge *> ls = edges();
for (list<Edge *>::iterator it = ls.begin(); it != ls.end(); ++it)
{
delete *it;
*it = NULL;
}
delete []adj;
adj = NULL;
}
list<Edge *> EdgeWeightedGraph::getAdj(int v)
{
if (v >= 0 && v < V)
return adj[v];
}
list<Edge *> EdgeWeightedGraph::edges()
{
list<Edge *> ls;
for (int i = 0; i < V; ++i)
{
int selfLoops = 0;
list<Edge *> tmpList = getAdj(i);
for (list<Edge *>::iterator it = tmpList.begin(); it != tmpList.end(); ++it)
{
if ((*it)->other(i) > i)
ls.push_back(*it);
else if ((*it)->other(i) == i)//only add one copy of each self loop
{
if (0 == selfLoops%2)
ls.push_back(*it);
++selfLoops;
}
}
}
return ls;
}
class UF
{
public:
UF(int n);
~UF();
int find(int p);
bool connected(int p, int q);
void unite(int p, int q);
private:
int *id; // id[i]=parent of i
int *rank; // rank[i]=rank of subtree rooted at i
int num; // number of vertex
int count; // number of components
};
UF::UF(int n)
{
if (n > 0)
{
count = n;
num = n;
id = new int[n];
rank = new int[n];
for (int i = 0; i < n; ++i)
{
id[i] = i;
rank[i] = 0;
}
}
}
UF::~UF()
{
if (NULL != id)
{
delete []id;
id = NULL;
}
if (NULL != rank)
{
delete []rank;
rank = NULL;
}
}
int UF::find(int p)
{
if (p >=0 && p <num)
{
while (p != id[p])
p = id[p];
}
return p;
}
bool UF::connected(int p, int q)
{
return find(p) == find(q);
}
void UF::unite(int p, int q)
{
int i = find(p);
int j = find(q);
if (i == j)
return ;
// make root of smaller rank point to root of larger rank
if (rank[i] < rank[j])
id[i] = j;
else if (rank[i] > rank[j])
id[j] = i;
else
{
id[i] = j;
++rank[j];
}
--count;
}
class KruskalMST
{
public:
KruskalMST(EdgeWeightedGraph *g);
queue<Edge *> edges() { return mst; }
double getWeight() { return weight; }
private:
double weight; //weight of mst
queue<Edge *> mst;//edges in mst
};
KruskalMST::KruskalMST(EdgeWeightedGraph *g)
{
weight = 0;
priority_queue<Edge *, vector<Edge *>, EdgeCmp> pq;
list<Edge *> ls = g->edges();
for (list<Edge *>::iterator it = ls.begin(); it != ls.end(); ++it)
pq.push(*it);
int v = g->getV();
UF uf(v);
while(!pq.empty() && mst.size() < (v-1))
{
Edge *e = pq.top();
int u = e->either();
int v = e->other(u);
if (!uf.connected(u, v))
{
uf.unite(u, v);
mst.push(e);
weight += e->getWeight();
}
pq.pop();
}
}
int main()
{
int arr[][2] = { {0, 7}, {2, 3}, {1, 7}, {0, 2},
{5, 7}, {1, 3}, {1, 5}, {2, 7},
{4, 5}, {1, 2}, {4, 7}, {0, 4},
{6, 2}, {3, 6}, {6, 0}, {6, 4}
};
double wgt[] = {0.16, 0.17, 0.19, 0.26, 0.28, 0.29, 0.32, 0.34,
0.35, 0.36, 0.37, 0.38, 0.40, 0.52, 0.58, 0.93};
EdgeWeightedGraph graph(8, 16, arr, wgt);
KruskalMST kmst(&graph);
queue<Edge *> edge = kmst.edges();
while (!edge.empty())
{
cout << edge.front()->toString();
edge.pop();
}
cout << "weight: " << kmst.getWeight() << endl;
return 0;
}
0 -- 7 : 0.160
2 -- 3 : 0.170
1 -- 7 : 0.190
0 -- 2 : 0.260
5 -- 7 : 0.280
4 -- 5 : 0.350
6 -- 2 : 0.400
weight: 1.81