Kruskal算法计算最小生成树 C++实现
用Kruskal算法计算最小生成树时,将结点分成不同的集合,一开始所有的结点都在不同的集合
将所有的边排序后(按照权值进行从小到大排序) 然后看每边的两个结点是否属于不同集合,
如果不是,则可以将这条表加到最小生成树中,并把这两个结点放到同一个集合中,然后如此类推,
直到最小生成树中有了n-1条边
测试用例:
上面说的那个集合,我用两个map来实现,好久没敲C++的代码,写的不好请见谅
Edge.h
#ifndef GUARD_Edge_h
#define GUARD_Edge_h
#include <string>
using std::string;
class Edge
{
public:
Edge() {}
Edge(const string& StartNode,const string& EndNode, double weight):
StartNodeID(StartNode),EndNodeID(EndNode),Weight(weight) {}
string StartNodeID;
string EndNodeID;
double Weight;
};
bool Compare(const Edge& e1,const Edge& e2);
#endif
Node.h
#ifndef GUARD_Node_h
#define GUARD_Node_h
#include <string>
#include <vector>
#include "Edge.h"
using std::string;
using std::vector;
//结点以及这个结点所有的出边
class Node
{
public:
Node(const string& ID,const vector<Edge>& edgeList) :
_ID(ID),_edgeList(edgeList) {}
Node(const string& ID):_ID(ID) {}
string GetID()
{
return _ID;
}
vector<Edge> GetEdgeList()
{
return _edgeList;
}
void AddEdge(const Edge& edge)
{
_edgeList.push_back(edge);
}
private:
string _ID;
vector<Edge> _edgeList;
};
#endif
Graph.h
#ifndef GRUAD_Graph_h
#define GRUAD_Graph_h
#include <string>
#include <map>
#include <vector>
#include "Node.h"
#include "MSTree.h"
using std::string;
using std::map;
using std::vector;
class Graph
{
typedef map<string,double> Path;
typedef map<string,Path> G;
public:
Graph(const vector<Node>& nodeList):
_nodeList(nodeList) {};
MSTree GetMST();
private:
G graph;
vector<Node> _nodeList;
};
#endif
Graph.cpp
#include "Graph.h"
#include <iostream>
#include <algorithm>
using namespace std;
MSTree Graph::GetMST()
{
G s;//集合s
vector<Node>::size_type i;
vector<Node>::size_type j;
//储存所有边的容器
vector<Edge> edgeList;
//初始化s集合,使每个顶点分属于不同的集合
for (i=0;i<_nodeList.size();i++)
{
string NodeID=_nodeList[i].GetID();
s[NodeID][NodeID]=1;
for (j=0;j<_nodeList[i].GetEdgeList().size();j++)
edgeList.push_back((_nodeList[i].GetEdgeList())[j]);
}
//把边按照权值进行从小到大排序
sort(edgeList.begin(),edgeList.end(),Compare);
/*for (vector<Edge>::size_type ii=0;ii<edgeList.size();ii++)
{
cout<<edgeList[ii].StartNodeID<<"->"<<edgeList[ii].EndNodeID
<<" "<<edgeList[ii].Weight<<endl;
}*/
vector<Node>::size_type k=1; //计数
vector<Edge>::size_type d=0;
string m1,m2; //记录一条边的两个顶点分别在哪个集合
j=0;
vector<Edge> Tree; //储存最小生成树的边
double weight=0; //以及总权值
while(k<_nodeList.size())
{
for (i=0;i<_nodeList.size();i++)
{
string curNodeID=_nodeList[i].GetID();
if (s[curNodeID][edgeList[d].StartNodeID]==1)
m1=curNodeID;
if(s[curNodeID][edgeList[d].EndNodeID]==1)
m2=curNodeID;
}
//如果一条边的两个顶点属于不同的集合
//就把这条边加到树中
if (m1!=m2)
{
//cout<<m1<<" "<<m2<<endl;
Tree.push_back(edgeList[d]);
weight+=edgeList[d].Weight;
k++;
for (j=0;j<_nodeList.size();j++)
{
// 合并两个集合
s[m1][_nodeList[j].GetID()]=s[m1][_nodeList[j].GetID()]
||s[m2][_nodeList[j].GetID()];
// 将另一个集合置空
s[m2][_nodeList[j].GetID()]=0;
}
}
d++;
}
MSTree msTree(Tree,weight);
return msTree;
}
MSTree.h
#ifndef GUARD_MSTree_h
#define GUARD_MSTree_h
#include <vector>
#include "Edge.h"
using std::vector;
//最小生成树,含有n-1条边以及
//所有边的总权值
class MSTree
{
public:
MSTree(const vector<Edge>& edgeList,double weight):
_msTree(edgeList),_weight(weight){}
vector<Edge> GetEdgeList() {return _msTree;}
double GetWeight() {return _weight;}
private:
vector<Edge> _msTree;
double _weight;
};
#endif
main.cpp
#include <iostream>
#include "Graph.h"
#include <map>
#include <vector>
using namespace std;
vector<Node> Init()
{
Edge edge;
Node A("A");
edge.StartNodeID="A";
edge.EndNodeID="B";
edge.Weight=8;
A.AddEdge(edge);
edge.StartNodeID="A";
edge.EndNodeID="D";
edge.Weight=5;
A.AddEdge(edge);
Node B("B");
edge.StartNodeID="B";
edge.EndNodeID="D";
edge.Weight=3;
B.AddEdge(edge);
edge.StartNodeID="B";
edge.EndNodeID="E";
edge.Weight=10;
B.AddEdge(edge);
edge.StartNodeID="B";
edge.EndNodeID="C";
edge.Weight=12;
B.AddEdge(edge);
Node C("C");
edge.StartNodeID="C";
edge.EndNodeID="E";
edge.Weight=6;
C.AddEdge(edge);
edge.StartNodeID="C";
edge.EndNodeID="F";
edge.Weight=2;
C.AddEdge(edge);
Node D("D");
edge.StartNodeID="D";
edge.EndNodeID="F";
edge.Weight=7;
D.AddEdge(edge);
edge.StartNodeID="D";
edge.EndNodeID="G";
edge.Weight=15;
D.AddEdge(edge);
Node E("E");
edge.StartNodeID="E";
edge.EndNodeID="F";
edge.Weight=9;
E.AddEdge(edge);
Node F("F");
Node G("G");
vector<Node> nodeList;
nodeList.push_back(A);
nodeList.push_back(B);
nodeList.push_back(C);
nodeList.push_back(D);
nodeList.push_back(E);
nodeList.push_back(F);
nodeList.push_back(G);
return nodeList;
}
int main()
{
vector<Node> nodeList=Init();
Graph graph(nodeList);
MSTree msTree=graph.GetMST();
//得到计算结果
vector<Edge> edgeList=msTree.GetEdgeList();
cout<<"Minimum Spanning Tree: "<<endl;
for (vector<Edge>::size_type i=0;i<edgeList.size();i++)
{
cout<<edgeList[i].StartNodeID<<"->"<<edgeList[i].EndNodeID
<<" "<<edgeList[i].Weight<<endl;
}
cout<<"Total weight: "<<msTree.GetWeight()<<endl;
return 0;
}
结果:
于是我们得到的最小生成树为: