From 5f71dd5d45dc14bac5a0edb8b3111ec328c75502 Mon Sep 17 00:00:00 2001 From: GregorSamsa42 Date: Wed, 31 Jul 2024 13:05:10 +0200 Subject: [PATCH] added Kruskal's algorithm --- min_spanning_tree/kruskal/CMakeLists.txt | 7 ++ min_spanning_tree/kruskal/kruskal.cpp | 132 +++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 min_spanning_tree/kruskal/CMakeLists.txt create mode 100644 min_spanning_tree/kruskal/kruskal.cpp diff --git a/min_spanning_tree/kruskal/CMakeLists.txt b/min_spanning_tree/kruskal/CMakeLists.txt new file mode 100644 index 0000000..8e1e87b --- /dev/null +++ b/min_spanning_tree/kruskal/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.10) +set(CMAKE_BUILD_TYPE Debug) +project(kruskal) +add_executable(kruskal + ../../weighted_graph.cpp + ../../weighted_graph.h + kruskal.cpp) diff --git a/min_spanning_tree/kruskal/kruskal.cpp b/min_spanning_tree/kruskal/kruskal.cpp new file mode 100644 index 0000000..14fc65d --- /dev/null +++ b/min_spanning_tree/kruskal/kruskal.cpp @@ -0,0 +1,132 @@ +// Algorithm generating a minimum spanning tree using Kruskal's algorithm +// Authors: GeorĒµi Kocharyan + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../weighted_graph.h" +#include + + + struct key_compare + { + bool operator()(const std::tuple& l, const std::tuple& r) + { + return std::get<2>(l) < std::get<2>(r); + } + }; + +void next_edge(WeightedGraph const & G, std::vector> & elements, std::vector component) { + +} + +void kruskal(WeightedGraph const & G) { + // preprocessing: remove all double edges except the minimal ones + + WeightedGraph H = G.remove_parallel(); + double total_weight = 0; + + // preprocessing: create a vector of lists tracking the elements of the components + + std::vector> elements; + elements.resize(H.num_nodes()); + for (int i = 0; i < H.num_nodes(); i++) + { + elements[i].push_back(i); + } + + // preprocessing: create a vector tracking which component each element belongs to + + std::vector component; + component.resize(H.num_nodes()); + for (int i = 0; i < H.num_nodes(); i++) + { + component[i] = i; + } + + // preprocessing: create a vector containing all edges in O(m) + // then sort them according to their weight + + std::vector> edges; + edges.resize(H.num_edges()); + int count = 0; + for (int i = 0; i < H.num_nodes(); i++) + { + for (const auto& j : H.adjList(i)) + { + edges[count] = std::make_tuple(i,j.first,j.second); + count++; + } + } + std::sort(edges.begin(), edges.end(),key_compare()); + + for (const auto& edge : edges) + { + // check if edge connects two of the same component + if (!(component[std::get<0>(edge)]==component[std::get<1>(edge)])) + { + // output edge + std::cout << std::get<0>(edge) << "-" << std::get<1>(edge) << "\t" << std::get<2>(edge) << std::endl; + total_weight = total_weight + std::get<2>(edge); + // make the components of each node the same + // the larger component absorbs the second to guarantee O(mlogn) runtime + if (elements[component[std::get<0>(edge)]].size() >= elements[component[std::get<1>(edge)]].size()) + { + // move all elements of second component to first + int moved = component[std::get<1>(edge)]; + int movedto = component[std::get<0>(edge)]; + for (const auto& node : (elements[moved])) + { + elements[movedto].push_back(node); + component[node] = movedto; + } + elements[moved].clear(); + } + else + { + // move all elements of first component to second + int moved = component[std::get<0>(edge)]; + int movedto = component[std::get<1>(edge)]; + for (const auto& node : (elements[moved])) + { + elements[movedto].push_back(node); + component[node] = movedto; + } + elements[moved].clear(); + } + } + + } + std::cout << "The total weight of the MST is " << total_weight << std::endl; +} + +// example of a CONNECTED input graph + +int main() { + + int size = 8; + WeightedGraph G(size); + G.add_edge(3,4,2); + G.add_edge(4,3,3); + G.add_edge(5,6,6); + G.add_edge(6,7,1); + G.add_edge(1,2,3); + G.add_edge(2,3,8); + G.add_edge(7,5,0.2); + G.add_edge(7,3,9); + G.add_edge(0,3,1); + G.add_edge(3,0,5); + G.add_edge(4,6,3); + G.add_edge(0,7,0.5); + G.add_edge(4,2,1); + + kruskal(G); + + return 0; + +} \ No newline at end of file