review kruskal: some refactoring + todos
This commit is contained in:
parent
10ae6db373
commit
79c7bfeb0d
2 changed files with 44 additions and 42 deletions
|
@ -2,16 +2,12 @@
|
||||||
// Authors: Georǵi Kocharyan
|
// Authors: Georǵi Kocharyan
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdio>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
|
||||||
#include <queue>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
|
||||||
#include <functional>
|
|
||||||
#include "../../weighted_graph.h"
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "../../weighted_graph.h"
|
||||||
|
|
||||||
|
|
||||||
struct key_compare
|
struct key_compare
|
||||||
{
|
{
|
||||||
|
@ -21,9 +17,18 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void next_edge(WeightedGraph const & G, std::vector<std::list<int>> & elements, std::vector<int> component) {
|
|
||||||
|
|
||||||
|
struct Edge
|
||||||
|
{
|
||||||
|
// todo: use type alias
|
||||||
|
int from;
|
||||||
|
int to;
|
||||||
|
double weight;
|
||||||
|
|
||||||
|
bool operator<(Edge const & other) const {
|
||||||
|
return weight < other.weight;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void kruskal(WeightedGraph const & G) {
|
void kruskal(WeightedGraph const & G) {
|
||||||
// preprocessing: remove all double edges except the minimal ones
|
// preprocessing: remove all double edges except the minimal ones
|
||||||
|
@ -33,7 +38,7 @@ void kruskal(WeightedGraph const & G) {
|
||||||
|
|
||||||
// preprocessing: create a vector of lists tracking the elements of the components
|
// preprocessing: create a vector of lists tracking the elements of the components
|
||||||
|
|
||||||
std::vector<std::list<int>> elements;
|
std::vector<std::vector<int>> elements;
|
||||||
elements.resize(H.num_nodes());
|
elements.resize(H.num_nodes());
|
||||||
for (int i = 0; i < H.num_nodes(); i++)
|
for (int i = 0; i < H.num_nodes(); i++)
|
||||||
{
|
{
|
||||||
|
@ -52,15 +57,14 @@ void kruskal(WeightedGraph const & G) {
|
||||||
// preprocessing: create a vector containing all edges in O(m)
|
// preprocessing: create a vector containing all edges in O(m)
|
||||||
// then sort them according to their weight
|
// then sort them according to their weight
|
||||||
|
|
||||||
|
// todo: use std::vector<Edge>
|
||||||
std::vector<std::tuple<int, int, double>> edges;
|
std::vector<std::tuple<int, int, double>> edges;
|
||||||
edges.resize(H.num_edges());
|
edges.reserve(H.num_edges());
|
||||||
int count = 0;
|
|
||||||
for (int i = 0; i < H.num_nodes(); i++)
|
for (int i = 0; i < H.num_nodes(); i++)
|
||||||
{
|
{
|
||||||
for (const auto& j : H.adjList(i))
|
for (const auto& j : H.adjList(i))
|
||||||
{
|
{
|
||||||
edges[count] = std::make_tuple(i,j.first,j.second);
|
edges.emplace_back(i,j.first,j.second);
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::sort(edges.begin(), edges.end(), key_compare());
|
std::sort(edges.begin(), edges.end(), key_compare());
|
||||||
|
@ -68,30 +72,28 @@ void kruskal(WeightedGraph const & G) {
|
||||||
for (const auto& edge : edges)
|
for (const auto& edge : edges)
|
||||||
{
|
{
|
||||||
// check if edge connects two of the same component
|
// check if edge connects two of the same component
|
||||||
if (!(component[std::get<0>(edge)]==component[std::get<1>(edge)]))
|
if (component[std::get<0>(edge)] != component[std::get<1>(edge)])
|
||||||
{
|
{
|
||||||
// output edge
|
// output edge
|
||||||
std::cout << std::get<0>(edge) << "-" << std::get<1>(edge) << "\t" << std::get<2>(edge) << std::endl;
|
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);
|
total_weight += std::get<2>(edge);
|
||||||
// make the components of each node the same
|
// make the components of each node the same
|
||||||
// the larger component absorbs the second to guarantee O(mlogn) runtime
|
// the larger component absorbs the second to guarantee O(mlogn) runtime
|
||||||
|
// todo: avoid code duplication by moving out stuff from if-else
|
||||||
|
int moved;
|
||||||
|
int movedto;
|
||||||
if (elements[component[std::get<0>(edge)]].size() >= elements[component[std::get<1>(edge)]].size())
|
if (elements[component[std::get<0>(edge)]].size() >= elements[component[std::get<1>(edge)]].size())
|
||||||
{
|
{
|
||||||
// move all elements of second component to first
|
// move all elements of second component to first
|
||||||
int moved = component[std::get<1>(edge)];
|
moved = component[std::get<1>(edge)];
|
||||||
int movedto = component[std::get<0>(edge)];
|
movedto = component[std::get<0>(edge)];
|
||||||
for (const auto& node : (elements[moved]))
|
|
||||||
{
|
|
||||||
elements[movedto].push_back(node);
|
|
||||||
component[node] = movedto;
|
|
||||||
}
|
|
||||||
elements[moved].clear();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// move all elements of first component to second
|
// move all elements of first component to second
|
||||||
int moved = component[std::get<0>(edge)];
|
moved = component[std::get<0>(edge)];
|
||||||
int movedto = component[std::get<1>(edge)];
|
movedto = component[std::get<1>(edge)];
|
||||||
|
}
|
||||||
for (const auto& node : (elements[moved]))
|
for (const auto& node : (elements[moved]))
|
||||||
{
|
{
|
||||||
elements[movedto].push_back(node);
|
elements[movedto].push_back(node);
|
||||||
|
@ -99,7 +101,6 @@ void kruskal(WeightedGraph const & G) {
|
||||||
}
|
}
|
||||||
elements[moved].clear();
|
elements[moved].clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
std::cout << "The total weight of the MST is " << total_weight << std::endl;
|
std::cout << "The total weight of the MST is " << total_weight << std::endl;
|
||||||
|
|
|
@ -7,23 +7,24 @@
|
||||||
|
|
||||||
|
|
||||||
struct Node {
|
struct Node {
|
||||||
|
// todo: introduce neighbor struct and use it instead of std::pair
|
||||||
std::list<std::pair<int, double>> neighbours;
|
std::list<std::pair<int, double>> neighbours;
|
||||||
Node() = default;
|
Node() = default;
|
||||||
Node(std::list<std::pair<int, double>> neighbours);
|
explicit Node(std::list<std::pair<int, double>> neighbours);
|
||||||
void add_edge(int node_id, double weight);
|
void add_edge(int node_id, double weight);
|
||||||
int deg() const;
|
[[nodiscard]] int deg() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WeightedGraph {
|
class WeightedGraph {
|
||||||
public:
|
public:
|
||||||
WeightedGraph(size_t num_nodes);
|
explicit WeightedGraph(size_t num_nodes);
|
||||||
void add_edge(int from, int to, double weight);
|
void add_edge(int from, int to, double weight);
|
||||||
std::list<std::pair<int, double>> adjList(int node_id) const;
|
[[nodiscard]] std::list<std::pair<int, double>> adjList(int node_id) const;
|
||||||
size_t num_nodes() const;
|
[[nodiscard]] size_t num_nodes() const;
|
||||||
int num_edges() const;
|
[[nodiscard]] int num_edges() const;
|
||||||
int deg(int v) const;
|
[[nodiscard]] int deg(int v) const;
|
||||||
std::pair<int,double> min_neighbour(int node_id) const;
|
[[nodiscard]] std::pair<int,double> min_neighbour(int node_id) const;
|
||||||
WeightedGraph remove_parallel() const;
|
[[nodiscard]] WeightedGraph remove_parallel() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Node> nodes;
|
std::vector<Node> nodes;
|
||||||
|
|
Loading…
Reference in a new issue