4
\$\begingroup\$

Playing around with pointers in C++, implemented an adjacency list graph.

Am I going too far/extreme trying to place data onto the heap?

graph.h

#include <memory>
#include <unordered_map>
#include <forward_list>
#include <utility>
template <typename TKey, typename TWeight>
class Graph{
 struct Adjacent {
 TKey key;
 TWeight weight;
 Adjacent(const TKey key, const TWeight weight): key(key), weight(weight) {};
 };
 struct Vertex {
 TKey value;
 std::unique_ptr<std::forward_list<Adjacent>> adjVertexList;
 explicit Vertex(const TKey value){
 this->value = value;
 adjVertexList = std::make_unique<std::forward_list<Adjacent>>();
 }
 };
private:
 // Since keys can be non-numeric,
 // use a hashmap to index into individual adj lists
 std::unordered_map<TKey, std::unique_ptr<Vertex>> vertices;
public:
 void addVertex(TKey value);
 // Everything other than addDirectedEdge is just for a nicer API
 void addDirectedEdge(TKey src, TKey dst, TWeight weight);
 void addUndirectedEdge(TKey src, TKey dst, TWeight weight);
 void addDirectedEdge(TKey src, TKey dst);
 void addUndirectedEdge(TKey src, TKey dst);
};

graph.cpp

#include <stdexcept>
#include "graph.h"
template <typename TKey, typename TWeight>
void Graph<TKey, TWeight>::addVertex(TKey value) {
 vertices.insert(std::make_pair(value, std::make_unique<Vertex>(value)));
}
template <typename TKey, typename TWeight>
void Graph<TKey, TWeight>::addDirectedEdge(TKey src, TKey dst, TWeight weight) {
 auto srcPtr = vertices.find(src);
 if(srcPtr == vertices.end())
 throw std::invalid_argument("Cannot find source");
 else if(vertices.find(dst) == vertices.end())
 throw std::invalid_argument("Cannot find destination");
 Vertex* vertex = srcPtr->second.get();
 vertex->adjVertexList->push_front(Adjacent(dst, weight));
}
template <typename TKey, typename TWeight>
void Graph<TKey, TWeight>::addUndirectedEdge(TKey src, TKey dst, TWeight weight) {
 addDirectedEdge(src, dst, weight);
 addDirectedEdge(dst, src, weight);
}
template <typename TKey, typename TWeight>
void Graph<TKey, TWeight>::addDirectedEdge(TKey src, TKey dst) {
 addDirectedEdge(src, dst, 0);
}
template <typename TKey, typename TWeight>
void Graph<TKey, TWeight>::addUndirectedEdge(TKey src, TKey dst){
 addUndirectedEdge(src, dst, 0);
}
```
asked Aug 24, 2020 at 17:19
\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

Am I going too far/extreme trying to place data onto the heap?

Yes. Containers like std::unordered_map and std::forward_list already store contents on the heap. If you declare a std::unordered_map on the stack, only a little bit of administrative data goes on the stack. But the same happens with std::unique_ptr. So in your code, the use of std::unique_ptr is superfluous and only increases indirection, which might be bad for performance. So just write:

template <typename TKey, typename TWeight>
class Graph {
 ...
 struct Vertex {
 ...
 std::forward_list<Adjacent> adjVertexList;
 ...
 };
 ...
 std::unordered_map<TKey, Vertex> vertices;
 ...
};
answered Aug 24, 2020 at 19:32
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.