我有兴趣学习如何在 C++ 中在 O(n log n) 上运行 Kruskal 算法。我已经使用在 O(n^2) 上运行的解决方案实现了该算法,其代码如下。
我知道应该可以在 O(n log n) 上运行 Kruskal,但我不知道如何做到这一点。我将不胜感激任何和所有提示。
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
//sort by weight
bool sorting (vector<int> i, vector<int> j) {return i[2]<j[2];}
class Submap {
private:
set<int> finder;
public:
Submap(int x) {finder.insert(x);}
Submap(set<int> x) {finder = x;}
set<int> pointreturn() {return finder;}
//function to add new set to current tree
void add(set<int> np) {
finder.insert(np.begin(), np.end());
}
void add(int n) {
finder.insert(n);
}
int size() {return int(finder.size());}
//find function returns true if the value is not found
bool find(int x) {
if (finder.find(x) == finder.end())
return true;
else
return false;
}
};
class Map {
private:
vector<Submap> submaps;
public:
int find(int x) {
int finder = -1;
for(int i = 0; i < int(submaps.size()); i++) {
if(!submaps[i].find(x)) {
finder = i;
break;
}
}
return finder;
}
void newsubmap(int a, int b) {
set<int> nextset;
nextset.insert(a);
nextset.insert(b);
submaps.push_back(Submap(nextset));
}
void addendum(int a, int index) {
submaps[index].add(a);
}
Submap subfind(int i) {return submaps[i];}
void fuse(int index1, int index2) {
submaps[index1].add(submaps[index2].pointreturn());
vector<Submap> nextmaps;
for(int i = 0; i < int(submaps.size()); i++) {
if (i != index2)
nextmaps.push_back(submaps[i]);
}
submaps = nextmaps;
}
int size() {return submaps[0].size();}
};
Map kruskal (vector<vector<int>> &graph, int weight, int junct) {
//sort the graph
sort(graph.begin(), graph.end(), sorting);
Map currmap;
int usedweight = 0;
for(int i=0; i<graph.size(); i++) {
int a = currmap.find(graph[i][0]);
int b = currmap.find(graph[i][1]);
//the boolean expression here is false if both points are already in the same submap
if(a != b || a == -1) {
usedweight += graph[i][2];
//if neither point is in the map so far
if(a == -1 && b == -1) {
currmap.newsubmap(graph[i][0], graph[i][1]);
}
//if one point is in the map so far
else if (a != -1 && b == -1) {
currmap.addendum(graph[i][1], a);
}
else if (a == -1 && b != -1) {
currmap.addendum(graph[i][0], b);
}
//if both points are in the map, but different submaps
else {
currmap.fuse(a, b);
}
}
//if the first set in the map is spanning, the algorithm is done
if(currmap.size() == junct)
break;
}
return (currmap);
}