I know this type of question has been asked before. However, my reason for asking it is gaining insight into what is expected in a 45 min interview when asked to implement graph algorithms. I have never had to give an interview, but have been asked in several interviews, questions pertaining to graphs. Specifically adjacency lists implementations. Several times I have asked the interviewer if they would like me to just implement the algorithm, or if they would prefer the basic structure of the graph too. Most times the response was to provide some level of structure before implementing the algorithm.
Provided the information above, my review request is as follows:
- Is my implementation of a graph (provided below) sufficient?
- Would you as a reviewer of the code be appalled provided I wrote it in under 20 min?
- How would you simplify the code below such that it would be suitable for an interview, and sufficient enough to convey that you could solve problems like depth or breadth first search with it?
namespace graph
{
template <typename T>
struct directed_node
{
typedef typename std::list<std::shared_ptr<directed_node<T>>> adjacency_t;
explicit directed_node(const T &t) :
m_t(t)
{}
void connect(std::shared_ptr<directed_node<T>> node,
typename adjacency_t::iterator addr)
{
auto it = m_adjacents.begin();
for (it = m_adjacents.begin(); it != m_adjacents.end(); ++it) {
if (node->m_t == (*it)->m_t) {
break;
}
}
if (it == m_adjacents.end()) {
m_adjacents.push_back(node);
node->m_adjacent_addr = addr;
}
}
T m_t;
adjacency_t m_adjacents;
typename adjacency_t::iterator m_adjacent_addr;
};
template <typename T>
struct directed
{
typedef typename std::list<std::shared_ptr<directed_node<T>>> adjacency_t;
adjacency_t m_adjacency_list;
typename adjacency_t::iterator insert(typename
std::shared_ptr<directed_node<T>> node)
{
auto it = m_adjacency_list.begin();
for (it = m_adjacency_list.begin(); it != m_adjacency_list.end(); ++it) {
if ((*it)->m_t == node->m_t) {
return it;
}
}
return m_adjacency_list.insert(m_adjacency_list.end(), node);
}
};
template <typename T>
std::shared_ptr<directed<T>> create_directed()
{
return std::make_shared<directed<T>>();
}
template <typename T>
std::shared_ptr<directed_node<T>> connect_directed(directed<T> &g,
const T &from, const T &to)
{
std::shared_ptr<graph::directed_node<T>> n1 =
std::make_shared<graph::directed_node<T>>(from);
auto it1 = g.insert(n1);
if (it1 != g.m_adjacency_list.end()) {
n1 = (*it1);
}
std::shared_ptr<graph::directed_node<T>> n2 =
std::make_shared<graph::directed_node<T>>(to);
auto it2 = g.insert(n2);
if (it2 != g.m_adjacency_list.end()) {
n2 = (*it2);
}
n1->connect(n2, it2);
return n1;
}
}
int main()
{
std::shared_ptr<graph::directed<int>> g = graph::create_directed<int>();
graph::connect_directed(*g, 1, 2);
return 0;
}