Ответ 1
Хорошо, поэтому я переведу и адаптирую свой учебник к вашему конкретному вопросу. Документация всегда принимает тонны "использования пространства имен"; Я не буду использовать их, чтобы вы знали, что к чему. Пусть начнется:
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/astar_search.hpp>
Сначала определите вершину и край:
struct Vertex{
string name; // or whatever, maybe nothing
};
struct Edge{
// nothing, probably. Or a weight, a distance, a direction, ...
};
Создайте тип или график:
typedef boost::adjacency_list< // adjacency_list is a template depending on :
boost::listS, // The container used for egdes : here, std::list.
boost::vecS, // The container used for vertices: here, std::vector.
boost::directedS, // directed or undirected edges ?.
Vertex, // The type that describes a Vertex.
Edge // The type that describes an Edge
> MyGraph;
Теперь вы можете использовать ярлык для типа идентификаторов ваших вершин и краев:
typedef MyGraph::vertex_descriptor VertexID;
typedef MyGraph::edge_descriptor EdgeID;
Указать свой график:
MyGraph graph;
Прочитайте данные Graphviz и скопируйте график:
for (each Vertex V){
VertexID vID = boost::add_vertex(graph); // vID is the index of a new Vertex
graph[vID].name = whatever;
}
Обратите внимание, что graph[ a VertexID ]
дает Вершину, но graph[ an EdgeID ]
дает Edge. Здесь, как добавить один:
EdgeID edge;
bool ok;
boost::tie(edge, ok) = boost::add_edge(u,v, graphe); // boost::add_edge gives a std::pair<EdgeID,bool>. It complicated to write, so boost::tie does it for us.
if (ok) // make sure there wasn't any error (duplicates, maybe)
graph[edge].member = whatever you know about this edge
Итак, теперь у вас есть свой график. Вы хотите получить VertexID для Vertex "c". Чтобы это было просто, позвольте использовать линейный поиск:
MyGraph::vertex_iterator vertexIt, vertexEnd;
boost::tie(vertexIt, vertexEnd) = vertices(graph);
for (; vertexIt != vertexEnd; ++vertexIt){
VertexID vertexID = *vertexIt; // dereference vertexIt, get the ID
Vertex & vertex = graph[vertexID];
if (vertex.name == std::string("c")){} // Gotcha
}
И, наконец, чтобы получить соседние вершины:
MyGraph::adjacency_iterator neighbourIt, neighbourEnd;
boost::tie(neighbourIt, neighbourEnd) = adjacent_vertices( vertexIdOfc, graph );
for(){you got it I guess}
Вы также можете получить ребра с помощью
std::pair<out_edge_iterator, out_edge_iterator> out_edges(vertex_descriptor u, const adjacency_list& g)
std::pair<in_edge_iterator, in_edge_iterator> in_edges(vertex_descriptor v, const adjacency_list& g)
// don't forget boost::tie !
Итак, для вашего реального вопроса:
- Найти идентификатор вершин "c"
- Найти in_edges рекурсивно
- Найти out_edges рекурсивно
Пример для in_edges (никогда не компилировался или не пытался, из верхней части моей головы):
void findParents(VertexID vID){
MyGraph::inv_adjacency_iterator parentIt, ParentEnd;
boost::tie(parentIt, ParentEnd) = inv_adjacent_vertices(vID, graph);
for(;parentIt != parentEnd); ++parentIt){
VertexID parentID = *parentIt;
Vertex & parent = graph[parentID];
add_edge_to_graphviz(vID, parentID); // or whatever
findParents(parentID);
}
}
С другой стороны, просто переименуйте Parent в Children и используйте adjacency_iterator/mixed_vertices.
Надеюсь, что это поможет.