Refactor: Replace std::map and std::set with unordered versions
This commit is contained in:
@@ -14,24 +14,24 @@ class BreadthFirstSearch {
|
|||||||
public:
|
public:
|
||||||
BreadthFirstSearch() = default;
|
BreadthFirstSearch() = default;
|
||||||
|
|
||||||
BreadthFirstSearch(std::map<T, std::set<T>> adjList)
|
BreadthFirstSearch(std::unordered_map<T, std::unordered_set<T>> adjList)
|
||||||
: adjList(adjList) {}
|
: adjList(adjList) {}
|
||||||
|
|
||||||
// Traverse whole graph using the BFS search, and save the tree graph
|
// Traverse whole graph using the BFS search, and save the tree graph
|
||||||
// which is created when visiting new vertices (Breadth First Tree)
|
// which is created when visiting new vertices (Breadth First Tree)
|
||||||
std::map<T, std::set<T>> execute(const T& root);
|
std::unordered_map<T, std::unordered_set<T>> execute(const T& root);
|
||||||
|
|
||||||
// Search if target vertex exists in graph
|
// Search if target vertex exists in graph
|
||||||
bool query(const T& root, const T& target);
|
bool query(const T& root, const T& target);
|
||||||
private:
|
private:
|
||||||
// Represents the graph on which the algorithm will be executed
|
// Represents the graph on which the algorithm will be executed
|
||||||
std::map<T, std::set<T>> adjList;
|
std::unordered_map<T, std::unordered_set<T>> adjList;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::map<T, std::set<T>> BreadthFirstSearch<T>::execute(const T& root) {
|
std::unordered_map<T, std::unordered_set<T>> BreadthFirstSearch<T>::execute(const T& root) {
|
||||||
std::map<T, std::set<T>> tree;
|
std::unordered_map<T, std::unordered_set<T>> tree;
|
||||||
std::map<T, bool> visited;
|
std::unordered_map<T, bool> visited;
|
||||||
std::queue<T> Q;
|
std::queue<T> Q;
|
||||||
Q.push(root);
|
Q.push(root);
|
||||||
visited[root] = true;
|
visited[root] = true;
|
||||||
@@ -54,7 +54,7 @@ std::map<T, std::set<T>> BreadthFirstSearch<T>::execute(const T& root) {
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool BreadthFirstSearch<T>::query(const T& root, const T& target) {
|
bool BreadthFirstSearch<T>::query(const T& root, const T& target) {
|
||||||
std::map<T, bool> visited;
|
std::unordered_map<T, bool> visited;
|
||||||
std::queue<T> Q;
|
std::queue<T> Q;
|
||||||
Q.push(root);
|
Q.push(root);
|
||||||
visited[root] = true;
|
visited[root] = true;
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ public:
|
|||||||
void remove(const std::vector<std::pair<T, T>>& edges);
|
void remove(const std::vector<std::pair<T, T>>& edges);
|
||||||
private:
|
private:
|
||||||
// Transitive closure matrix, used to answer reachability queries in O(1)
|
// Transitive closure matrix, used to answer reachability queries in O(1)
|
||||||
std::map<T, std::map<T, bool>> TC;
|
std::unordered_map<T, std::unordered_map<T, bool>> TC;
|
||||||
|
|
||||||
// For each SCC, store a reachability tree created as a BFS tree
|
// For each SCC, store a reachability tree created as a BFS tree
|
||||||
std::map<T, BreadthFirstTree<T>> RT;
|
std::unordered_map<T, BreadthFirstTree<T>> RT;
|
||||||
|
|
||||||
// For each SCC, store collections of incoming, outgoing and internal edges
|
// For each SCC, store collections of incoming, outgoing and internal edges
|
||||||
struct Edges {
|
struct Edges {
|
||||||
@@ -42,7 +42,7 @@ private:
|
|||||||
std::set<std::pair<T, T>> inc;
|
std::set<std::pair<T, T>> inc;
|
||||||
std::set<std::pair<T, T>> out;
|
std::set<std::pair<T, T>> out;
|
||||||
};
|
};
|
||||||
std::map<T, Edges> E;
|
std::unordered_map<T, Edges> E;
|
||||||
|
|
||||||
// Decremental maintenance of strongly connected components
|
// Decremental maintenance of strongly connected components
|
||||||
RodittyZwick<T> rodittyZwick;
|
RodittyZwick<T> rodittyZwick;
|
||||||
@@ -101,7 +101,7 @@ void Frigioni<T>::remove(const std::vector<std::pair<T, T>>& edges) {
|
|||||||
Eext.push_back({ u, v });
|
Eext.push_back({ u, v });
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<T, std::stack<T>> H;
|
std::unordered_map<T, std::stack<T>> H;
|
||||||
for (const auto& [u, v] : Eint) {
|
for (const auto& [u, v] : Eint) {
|
||||||
this->G.remove(u, v);
|
this->G.remove(u, v);
|
||||||
rodittyZwick.remove(u, v);
|
rodittyZwick.remove(u, v);
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ private:
|
|||||||
std::set<T> S;
|
std::set<T> S;
|
||||||
|
|
||||||
// Maintain in-out bfs trees
|
// Maintain in-out bfs trees
|
||||||
std::map<T, BreadthFirstTree<T>> In;
|
std::unordered_map<T, BreadthFirstTree<T>> In;
|
||||||
std::map<T, BreadthFirstTree<T>> Out;
|
std::unordered_map<T, BreadthFirstTree<T>> Out;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|||||||
@@ -28,20 +28,20 @@ public:
|
|||||||
void remove(const T& u, const T& v) override;
|
void remove(const T& u, const T& v) override;
|
||||||
private:
|
private:
|
||||||
// Transitive closure matrix
|
// Transitive closure matrix
|
||||||
std::map<T, std::map<T, bool>> TC;
|
std::unordered_map<T, std::unordered_map<T, bool>> TC;
|
||||||
|
|
||||||
// For each vertex, store a reachability tree created as a BFS tree
|
// For each vertex, store a reachability tree created as a BFS tree
|
||||||
std::map<T, BreadthFirstTree<T>> RT;
|
std::unordered_map<T, BreadthFirstTree<T>> RT;
|
||||||
|
|
||||||
// For each vertex, store collections of its incoming and outgoing edges
|
// For each vertex, store collections of its incoming and outgoing edges
|
||||||
struct Edges {
|
struct Edges {
|
||||||
std::set<T> inc;
|
std::set<T> inc;
|
||||||
std::set<T> out;
|
std::set<T> out;
|
||||||
};
|
};
|
||||||
std::map<T, Edges> E;
|
std::unordered_map<T, Edges> E;
|
||||||
|
|
||||||
// Repair reachability trees after edge deletions
|
// Repair reachability trees after edge deletions
|
||||||
void repairTrees(std::map<T, std::stack<T>>& H);
|
void repairTrees(std::unordered_map<T, std::stack<T>>& H);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -68,7 +68,7 @@ template<typename T>
|
|||||||
void Italiano<T>::remove(const T& u, const T& v) {
|
void Italiano<T>::remove(const T& u, const T& v) {
|
||||||
if (!this->G.adjList[u].contains(v)) return;
|
if (!this->G.adjList[u].contains(v)) return;
|
||||||
|
|
||||||
std::map<T, std::stack<T>> H;
|
std::unordered_map<T, std::stack<T>> H;
|
||||||
for (const auto& w : this->G.vertices()) {
|
for (const auto& w : this->G.vertices()) {
|
||||||
if (RT[w].contains(u, v)) {
|
if (RT[w].contains(u, v)) {
|
||||||
if (E[v].inc.size() > 1)
|
if (E[v].inc.size() > 1)
|
||||||
@@ -89,7 +89,7 @@ void Italiano<T>::remove(const T& u, const T& v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Italiano<T>::repairTrees(std::map<T, std::stack<T>>& H) {
|
void Italiano<T>::repairTrees(std::unordered_map<T, std::stack<T>>& H) {
|
||||||
for (const auto& z : this->G.vertices()) {
|
for (const auto& z : this->G.vertices()) {
|
||||||
while (H[z].size() > 0) {
|
while (H[z].size() > 0) {
|
||||||
const auto& h = H[z].top();
|
const auto& h = H[z].top();
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ public:
|
|||||||
void insert(const T& u, const T& v) override;
|
void insert(const T& u, const T& v) override;
|
||||||
private:
|
private:
|
||||||
// Connect each reachabiliy tree with decremental maintenance data structure
|
// Connect each reachabiliy tree with decremental maintenance data structure
|
||||||
std::map<T, Italiano<T>> In;
|
std::unordered_map<T, Italiano<T>> In;
|
||||||
std::map<T, Italiano<T>> Out;
|
std::unordered_map<T, Italiano<T>> Out;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|||||||
@@ -28,17 +28,17 @@ public:
|
|||||||
// Remove edge (u,v) and update A accordingly for fast checking query
|
// Remove edge (u,v) and update A accordingly for fast checking query
|
||||||
void remove(const T& u, const T& v) override;
|
void remove(const T& u, const T& v) override;
|
||||||
|
|
||||||
std::map<T, SCC<T>> getSCCs() { return C; }
|
std::unordered_map<T, SCC<T>> getSCCs() { return C; }
|
||||||
private:
|
private:
|
||||||
// Array used to answer strong connectivity queries in O(1) time
|
// Array used to answer strong connectivity queries in O(1) time
|
||||||
std::map<T, T> A;
|
std::unordered_map<T, T> A;
|
||||||
|
|
||||||
// Connect each representative with its SCC
|
// Connect each representative with its SCC
|
||||||
std::map<T, SCC<T>> C;
|
std::unordered_map<T, SCC<T>> C;
|
||||||
|
|
||||||
// Maintain in-out bfs trees
|
// Maintain in-out bfs trees
|
||||||
std::map<T, BreadthFirstTree<T>> In;
|
std::unordered_map<T, BreadthFirstTree<T>> In;
|
||||||
std::map<T, BreadthFirstTree<T>> Out;
|
std::unordered_map<T, BreadthFirstTree<T>> Out;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class Tarjan {
|
|||||||
public:
|
public:
|
||||||
Tarjan() = default;
|
Tarjan() = default;
|
||||||
|
|
||||||
Tarjan(std::map<T, std::set<T>> adjList) : adjList(adjList) {}
|
Tarjan(std::unordered_map<T, std::unordered_set<T>> adjList) : adjList(adjList) {}
|
||||||
|
|
||||||
//
|
//
|
||||||
auto execute();
|
auto execute();
|
||||||
@@ -24,7 +24,7 @@ public:
|
|||||||
//
|
//
|
||||||
void strongConnect(const T& u);
|
void strongConnect(const T& u);
|
||||||
private:
|
private:
|
||||||
std::map<T, std::set<T>> adjList;
|
std::unordered_map<T, std::unordered_set<T>> adjList;
|
||||||
std::stack<T> S;
|
std::stack<T> S;
|
||||||
std::int16_t index = 0;
|
std::int16_t index = 0;
|
||||||
std::vector<SCC<T>> SCCs;
|
std::vector<SCC<T>> SCCs;
|
||||||
@@ -35,7 +35,7 @@ private:
|
|||||||
int lowlink = -1;
|
int lowlink = -1;
|
||||||
bool onStack = false;
|
bool onStack = false;
|
||||||
};
|
};
|
||||||
std::map<T, Vertex> vmap;
|
std::unordered_map<T, Vertex> vmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -55,7 +55,7 @@ void Tarjan<T>::strongConnect(const T& u) {
|
|||||||
|
|
||||||
// If u is a root node, pop the stack and generate an SCC
|
// If u is a root node, pop the stack and generate an SCC
|
||||||
if (vmap[u].lowlink == vmap[u].index) {
|
if (vmap[u].lowlink == vmap[u].index) {
|
||||||
std::map<T, std::set<T>> scc;
|
std::unordered_map<T, std::unordered_set<T>> scc;
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
cid = S.top();
|
cid = S.top();
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class BreadthFirstTree : public Digraph<T> {
|
|||||||
public:
|
public:
|
||||||
BreadthFirstTree() = default;
|
BreadthFirstTree() = default;
|
||||||
|
|
||||||
BreadthFirstTree(std::map<T, std::set<T>> G, T root)
|
BreadthFirstTree(std::unordered_map<T, std::unordered_set<T>> G, T root)
|
||||||
: BreadthFirstTree<T>(Digraph<T>(G), root) {}
|
: BreadthFirstTree<T>(Digraph<T>(G), root) {}
|
||||||
|
|
||||||
BreadthFirstTree(Digraph<T> G, T root);
|
BreadthFirstTree(Digraph<T> G, T root);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class Digraph : public Graph<T> {
|
|||||||
public:
|
public:
|
||||||
Digraph() = default;
|
Digraph() = default;
|
||||||
|
|
||||||
Digraph(std::map<T, std::set<T>> G);
|
Digraph(std::unordered_map<T, std::unordered_set<T>> G);
|
||||||
|
|
||||||
// Return true if there is a path from u to v
|
// Return true if there is a path from u to v
|
||||||
bool contains(const T& u, const T& v);
|
bool contains(const T& u, const T& v);
|
||||||
@@ -27,7 +27,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Digraph<T>::Digraph(std::map<T, std::set<T>> G) {
|
Digraph<T>::Digraph(std::unordered_map<T, std::unordered_set<T>> G) {
|
||||||
this->adjList = G;
|
this->adjList = G;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ void Digraph<T>::remove(const T& u, const T& v) {
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto Digraph<T>::reverse() {
|
auto Digraph<T>::reverse() {
|
||||||
std::map<T, std::set<T>> revMatrix;
|
std::unordered_map<T, std::unordered_set<T>> revMatrix;
|
||||||
|
|
||||||
for (const auto& u : this->vertices()) {
|
for (const auto& u : this->vertices()) {
|
||||||
for (const auto& v : this->adjList[u]) {
|
for (const auto& v : this->adjList[u]) {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#ifndef GRAPH_H_
|
#ifndef GRAPH_H_
|
||||||
#define GRAPH_H_
|
#define GRAPH_H_
|
||||||
|
|
||||||
#include <map>
|
#include <unordered_map>
|
||||||
#include <set>
|
#include <unordered_set>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ public:
|
|||||||
std::uint16_t E();
|
std::uint16_t E();
|
||||||
|
|
||||||
// Adjacency matrix representation
|
// Adjacency matrix representation
|
||||||
std::map<T, std::set<T>> adjList;
|
std::unordered_map<T, std::unordered_set<T>> adjList;
|
||||||
|
|
||||||
friend std::ostream& operator<<<>(std::ostream& os, Graph<T>& G);
|
friend std::ostream& operator<<<>(std::ostream& os, Graph<T>& G);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ class SCC : public Digraph<T> {
|
|||||||
public:
|
public:
|
||||||
SCC() = default;
|
SCC() = default;
|
||||||
|
|
||||||
SCC(std::map<T, std::set<T>> G, T id) : Digraph<T>(G), id(id) { normalize(); }
|
SCC(std::unordered_map<T, std::unordered_set<T>> G, T id)
|
||||||
|
: Digraph<T>(G), id(id) { normalize(); }
|
||||||
|
|
||||||
SCC(Digraph<T> G, T id) : id(id) { normalize(); }
|
SCC(Digraph<T> G, T id) : id(id) { normalize(); }
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,8 @@ TEST_SUITE("Algorithm") {
|
|||||||
auto tree =
|
auto tree =
|
||||||
algo::BreadthFirstSearch<std::uint16_t>(G.adjList).execute(1);
|
algo::BreadthFirstSearch<std::uint16_t>(G.adjList).execute(1);
|
||||||
|
|
||||||
std::map<std::uint16_t, std::set<std::uint16_t>> expected = {
|
std::unordered_map<std::uint16_t,
|
||||||
|
std::unordered_set<std::uint16_t>> expected = {
|
||||||
{1, {2}},
|
{1, {2}},
|
||||||
{2, {3, 6}},
|
{2, {3, 6}},
|
||||||
{3, {4}},
|
{3, {4}},
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ TEST_SUITE("Graph") {
|
|||||||
|
|
||||||
auto reverse = G.reverse();
|
auto reverse = G.reverse();
|
||||||
|
|
||||||
std::map<std::uint16_t, std::set<std::uint16_t>> expected = {
|
std::unordered_map<std::uint16_t,
|
||||||
|
std::unordered_set<std::uint16_t>> expected = {
|
||||||
{1, {3}},
|
{1, {3}},
|
||||||
{2, {1}},
|
{2, {1}},
|
||||||
{3, {2, 5}},
|
{3, {2, 5}},
|
||||||
|
|||||||
Reference in New Issue
Block a user