Reputation: 13843
I'm implementing a simple DFS traversal for directed graph:
#include <iostream>
#include <vector>
#include <climits>
#include <utility>
#include <deque>
#include <queue>
#include <algorithm>
#include <iomanip>
#include <list>
using namespace std;
enum class color_type {
BLACK,
WHITE,
GRAY
};
struct vertex {
char label;
color_type color;
int start;
int finish;
vertex *parent;
vector<vertex> adjacents;
vertex(char label)
:label(label), start(0), finish(0), color(color_type::WHITE) {
}
void add_neighbor(const vertex &v) {
adjacents.push_back(v);
}
};
class digraph {
private:
vector<vertex> vertices;
int count;
public:
digraph()
:count(0) {
vertex a('a');
vertex b('b');
vertex c('c');
add_edge(a, b);
add_edge(b, c);
add_edge(c, a);
vertices.push_back(a);
vertices.push_back(b);
vertices.push_back(c);
for (int i = 0; i < vertices.size(); ++i) {
vertices[i].color = color_type::WHITE;
vertices[i].parent = NULL;
}
}
void add_edge(vertex &u, vertex &v) {
u.add_neighbor(v);
}
void dfs() {
dfs_visit(vertices[0]);
}
void dfs_visit(vertex &u) {
count++;
u.start = count;
u.color = color_type::GRAY;
cout << "??? visit = " << u.label << endl;
cout << "# neighbors: " << u.adjacents.size() << '\n';
for (int i = 0; i < u.adjacents.size(); ++i) {
if (u.adjacents[i].color == color_type::WHITE) {
cout << "visit neighbor of [" << u.label << "] is: " << u.adjacents[i].label << endl;
u.adjacents[i].parent = &u;
dfs_visit(u.adjacents[i]);
}
}
u.color = color_type::BLACK;
count++;
u.finish = count;
}
public:
friend ostream& operator <<(ostream& o, const digraph &dg) {
for (int i = 0; i < dg.vertices.size(); ++i) {
o << dg.vertices[i].label << ":\n";
o << "\t start = " << dg.vertices[i].start << endl;
o << "\t finish = " << dg.vertices[i].finish << endl;
}
return o;
}
};
int main() {
digraph dg;
dg.dfs();
cout << dg << endl;
return 0;
}
The problem is the call to dfs_visit()
stop after visit the 2nd vertex. I pass a vertex u
by reference as parameter of dfs_visit()
function, but somehow the number of neighbor of vertex b
suddenly becomes 0
which is very odd.
It seemed to me that the vertices stored in the vector vertices
are not the same as the ones which are passed to dfs_visit
, but I don't really see how this could be the case. I've been using Java for a while and now I'm really rusty with C++. So could anyone shed me some lights regarding this issue?
Edit
Upvotes: 1
Views: 280
Reputation: 66194
This is probably closer to what you're looking for, using pointers for neighbors. Hope this helps. Ultimately the difference is the by-pointer addressing of neighbors within the primary vertex container, as opposed to all those copies being made in your code.
Note: the add-construction just sets up a node to have the "next" node in the vertices collection as its neighbor, finishing with the last node getting the first for a neighbor. This seemed to be what you're code was trying to accomplish.
#include <iostream>
#include <vector>
#include <climits>
#include <utility>
#include <deque>
#include <queue>
#include <algorithm>
#include <iomanip>
#include <list>
using namespace std;
enum class color_type {
BLACK,
WHITE,
GRAY
};
struct vertex {
char label;
color_type color;
int start;
int finish;
vertex *parent;
vector<vertex*> adjacents;
vertex(char label)
:label(label), start(0), finish(0), color(color_type::WHITE) {
}
void add_neighbor(vertex &v) {
adjacents.push_back(std::addressof(v));
}
};
class digraph {
private:
vector<vertex> vertices;
int count;
public:
digraph()
:count(0) {
vertices.push_back(vertex('a'));
vertices.push_back(vertex('b'));
vertices.push_back(vertex('c'));
for (size_t i=0; i<vertices.size(); ++i)
{
vertices[i].color = color_type::WHITE;
vertices[i].parent = NULL;
vertices[i].add_neighbor(vertices[(i+1)%vertices.size()]);
}
}
void dfs() {
dfs_visit(vertices[0]);
}
void dfs_visit(vertex &u) {
count++;
u.start = count;
u.color = color_type::GRAY;
cout << "??? visit = " << u.label << endl;
cout << "# neighbors: " << u.adjacents.size() << '\n';
for (int i = 0; i < u.adjacents.size(); ++i) {
if (u.adjacents[i]->color == color_type::WHITE) {
cout << "visit neighbor of [" << u.label << "] is: " << u.adjacents[i]->label << endl;
u.adjacents[i]->parent = &u;
dfs_visit(*(u.adjacents[i]));
}
}
u.color = color_type::BLACK;
count++;
u.finish = count;
}
public:
friend ostream& operator <<(ostream& o, const digraph &dg) {
for (int i = 0; i < dg.vertices.size(); ++i) {
o << dg.vertices[i].label << ":\n";
o << "\t start = " << dg.vertices[i].start << endl;
o << "\t finish = " << dg.vertices[i].finish << endl;
}
return o;
}
};
int main() {
digraph dg;
dg.dfs();
cout << dg << endl;
return 0;
}
Output
??? visit = a
# neighbors: 1
visit neighbor of [a] is: b
??? visit = b
# neighbors: 1
visit neighbor of [b] is: c
??? visit = c
# neighbors: 1
a:
start = 1
finish = 6
b:
start = 2
finish = 5
c:
start = 3
finish = 4
Upvotes: 1