MST implementation with Kruskal and Boruvka algorithm

用C++分别实现了Kruskal和Boruvka算法计算MST
其中Kruskal算法中对边的排序用的heapsort
#include 
#include 
#include 

using namespace std;



struct Edge
{
	int src;
	int dest;
	int weight;
	Edge() = default;
	Edge(int s, int d, int w) : src(s), dest(d), weight(w) {};
};

struct Graph
{
	int V;      // number of vertices
	int E;      // number of edges
	vector edges;		// edges start from index 1
};

struct subset
{
	int parent;
	int rank;
};

bool operator<(const Edge &lhs, const Edge &rhs)
{
	return lhs.weight < rhs.weight;
}

bool operator<=(const Edge &lhs, const Edge &rhs)
{
	return lhs.weight <= rhs.weight;
}

void max_heapfy(vector &arry, size_t pos, size_t n)
{
	auto child = pos * 2;
	while (child <= n)
	{
		if (child < n && arry[child] < arry[child + 1])
			++child;
		if (arry[pos] <= arry[child])
		{
			swap(arry[pos], arry[child]);
			pos = child;
		}
		else
			break;
		child = pos * 2;
	}
}

void build_heap(vector &arry)
{
	auto n = arry.size() - 1;
	for (auto i = n / 2; i >= 1; --i)
		max_heapfy(arry, i, n);
}

void heap_sort(vector &arry)
{
	auto n = arry.size() - 1;
	build_heap(arry);
	for (vector::size_type i = n; i >= 2; --i)
	{
		swap(arry[1], arry[i]);
		max_heapfy(arry, 1, i - 1);
	}
}


// union-find data structure
// use path compression techinique

int find(vector &subsets, int i)
{
	if (subsets[i].parent != i)
		find(subsets, subsets[i].parent);
	return subsets[i].parent;
}

void Union(vector &subsets, int i, int j)
{
	int iroot = find(subsets, i);
	int jroot = find(subsets, j);

	// union by rank;
	if (subsets[iroot].rank < subsets[jroot].rank)
		subsets[iroot].parent = jroot;
	if (subsets[iroot].rank > subsets[jroot].rank)
		subsets[jroot].parent = iroot;
	if (subsets[iroot].rank == subsets[jroot].rank)
	{
		++subsets[iroot].rank;
		subsets[jroot].parent = iroot;
	}
}

// build graph from matrix to Graph
void buildGraph(vector> &graph, Graph &ret)
{
	ret.V = static_cast(graph.size());
	ret.E = 0;
	ret.edges.push_back(Edge(INT_MAX, INT_MAX, INT_MAX));
	// edge index starts from 1
	for (int i = 0; i < ret.V; ++i)
	{
		for (int j = 0; j < ret.V; ++j)
		{
			if (graph[i][j] > 0)
			{
				++ret.E;
				ret.edges.push_back(Edge(i, j, graph[i][j]));
				graph[j][i] = 0;
			}
		}
	}

}

// judge whether exists cycle
bool isCycle(Graph &graph)
{
	int V = graph.V; int E = graph.E;
	vector subsets(V);
	for (int i = 0; i < V; ++i)
	{
		subsets[i].parent = i;
		subsets[i].rank = 0;
	}

	for (int i = 1; i <= E; ++i)
	{
		int src_root = find(subsets, graph.edges[i].src);
		int dest_root = find(subsets, graph.edges[i].dest);

		if (src_root == dest_root)
			return true;

		Union(subsets, src_root, dest_root);
	}
	return false;
}

// kruskal algorithm
vector KruskalMST(vector> &matrix)
{
	vector ret;
	Graph graph;
	buildGraph(matrix, graph);
	heap_sort(graph.edges);
	vector subsets(graph.V);
	for (int i = 0; i < graph.V; ++i)
	{
		subsets[i].parent = i;
		subsets[i].rank = 0;
	}

	for (int i = 1; i < graph.edges.size(); ++i)
	{
		int src = graph.edges[i].src;
		int dest = graph.edges[i].dest;

		if (find(subsets, src) != find(subsets, dest))
		{
			ret.push_back(graph.edges[i]);
			Union(subsets, src, dest);
		}
	}

	return ret;
}

vector BoruvkaMST(vector> &matrix)
{
	vector ret;
	Graph graph;
	buildGraph(matrix, graph);
	vector dist(graph.V, -1);		// minimum edge for every component, this stores edges's indexes

	vector subsets(graph.V);
	for (int i = 0; i < graph.V; ++i)
	{
		subsets[i].parent = i;
		subsets[i].rank = 0;
	}
	int v = graph.V;

	while (v > 1)
	{
		for (int i = 1; i < graph.edges.size(); ++i)
		{
			int set1 = find(subsets, graph.edges[i].src);
			int set2 = find(subsets, graph.edges[i].dest);

			if (set1 == set2) 
				continue;
			if (dist[set1] == -1 || graph.edges[dist[set1]].weight > graph.edges[i].weight)		// check set1's minimum edge with i th edge
				dist[set1] = i;
			if (dist[set2] == -1 || graph.edges[dist[set2]].weight > graph.edges[i].weight)		// check set2's minimum edge with i th edge
				dist[set2] = i;
		}
		for (int i = 0; i < dist.size(); ++i)
		{
			if (dist[i] != -1)
			{
				int set1 = find(subsets, graph.edges[dist[i]].src);
				int set2 = find(subsets, graph.edges[dist[i]].dest);

				if (set1 == set2)
					continue;
				ret.push_back(graph.edges[dist[i]]);
				Union(subsets, set1, set2);
				--v;
			}
		}
	}
	return ret;
}

int main(int argc, const char * argv[]) {
	vector> g = { { 0, 2, 0, 6, 0 },{ 2, 0, 3, 8, 5 },{ 0, 3, 0, 0, 7 },{ 6, 8, 0, 0, 9 },{ 0, 5, 7, 9, 0 } };
	auto ret = BoruvkaMST(g);
	for (auto a : ret)
		cout << a.src << " to " << a.dest << endl;

	cout << "-------------------------------" << endl;

	auto ret2 = KruskalMST(g);
	for (auto a : ret2)
		cout << a.src << " to " << a.dest << endl;

	system("PAUSE");
	return 0;
}

Reference:

http://www.cs.princeton.edu/~wayne/kleinberg-tardos/pdf/04GreedyAlgorithmsII.pdf

http://www.geeksforgeeks.org/greedy-algorithms-set-9-boruvkas-algorithm/


你可能感兴趣的:(算法)