MST implementation with Kruskal and Boruvka algorithm

用C++分别实现了Kruskal和Boruvka算法计算MST
其中Kruskal算法中对边的排序用的heapsort
</pre><pre name="code" class="cpp">#include <iostream>
#include <string>
#include <vector>

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<Edge> 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<Edge> &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<Edge> &arry)
{
	auto n = arry.size() - 1;
	for (auto i = n / 2; i >= 1; --i)
		max_heapfy(arry, i, n);
}

void heap_sort(vector<Edge> &arry)
{
	auto n = arry.size() - 1;
	build_heap(arry);
	for (vector<int>::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<subset> &subsets, int i)
{
	if (subsets[i].parent != i)
		find(subsets, subsets[i].parent);
	return subsets[i].parent;
}

void Union(vector<subset> &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<vector<int>> &graph, Graph &ret)
{
	ret.V = static_cast<int>(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<subset> 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<Edge> KruskalMST(vector<vector<int>> &matrix)
{
	vector<Edge> ret;
	Graph graph;
	buildGraph(matrix, graph);
	heap_sort(graph.edges);
	vector<subset> 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<Edge> BoruvkaMST(vector<vector<int>> &matrix)
{
	vector<Edge> ret;
	Graph graph;
	buildGraph(matrix, graph);
	vector<int> dist(graph.V, -1);		// minimum edge for every component, this stores edges's indexes

	vector<subset> 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<vector<int>> 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/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值