简体   繁体   中英

Why doesn't my code work?

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 在此处输入图片说明

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM