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
    评论
以下是使用MATLAB实现Kruskal算法的示例代码: ```matlab function [MST, totalCost] = kruskal_algorithm(adjMatrix) % KRUSKAL_ALGORITHM: Implements Kruskal's algorithm to find the minimum % spanning tree of a given undirected graph % % INPUTS: % adjMatrix - n x n adjacency matrix of the graph % % OUTPUTS: % MST - adjacency matrix of the minimum spanning tree % totalCost - total cost of the minimum spanning tree % % Example usage: % adjMatrix = [0 3 0 0 6; 3 0 1 0 0; 0 1 0 2 0; 0 0 2 0 4; 6 0 0 4 0]; % [MST, totalCost] = kruskal_algorithm(adjMatrix); [n, ~] = size(adjMatrix); % Create a list of edges with their weights edges = []; for i = 1:n for j = i:n if adjMatrix(i,j) > 0 edges = [edges; i j adjMatrix(i,j)]; end end end % Sort edges by their weights in ascending order edges = sortrows(edges, 3); % Initialize the minimum spanning tree MST = zeros(n); numEdges = 0; totalCost = 0; % Loop through each edge in the sorted list for i = 1:size(edges,1) % Check if adding the current edge creates a cycle in MST if ~createsCycle(MST, edges(i,1), edges(i,2)) % Add the current edge to MST MST(edges(i,1), edges(i,2)) = edges(i,3); MST(edges(i,2), edges(i,1)) = edges(i,3); numEdges = numEdges + 1; totalCost = totalCost + edges(i,3); end % Stop looping if all edges have been processed if numEdges == n-1 break end end end function cycle = createsCycle(MST, u, v) % Check if adding an edge between u and v creates a cycle in MST % Mark all vertices as unvisited visited = zeros(size(MST,1),1); % Traverse the graph from vertex u stack = u; visited(u) = 1; while ~isempty(stack) current = stack(end); stack(end) = []; neighbors = find(MST(current,:)>0); for i = 1:length(neighbors) if ~visited(neighbors(i)) visited(neighbors(i)) = 1; stack = [stack neighbors(i)]; end end end % Check if vertex v was visited if visited(v) cycle = true; else cycle = false; end end ``` 在上面的代码中,我们首先将图的边按权重升序排序,然后在循环中逐个添加边,同时检查添加边是否会在最小生成树中创建环。如果添加边不会创建环,则将其添加到最小生成树中。我们使用一个辅助函数`createsCycle`来检查是否添加了边会创建环。 下面是一个使用示例: ```matlab % Create an example adjacency matrix adjMatrix = [0 3 0 0 6; 3 0 1 0 0; 0 1 0 2 0; 0 0 2 0 4; 6 0 0 4 0]; % Run Kruskal's algorithm to find the minimum spanning tree [MST, totalCost] = kruskal_algorithm(adjMatrix); % Display the results disp('Minimum spanning tree:'); disp(MST); disp(['Total cost: ' num2str(totalCost)]); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值