adjacency_list<OutEdgeList, VertexList, Directed, VertexProperties, EdgeProperties, GraphProperties, EdgeList>
adjacency_list类实现了一个通用的邻接表图结构。模板参数提供了许多配置选项,以便您可以选择最符合您需求的类版本。邻接表(adjacency-list)基本上是一个二维结构,其中第一维的每个元素代表一个顶点,每个顶点包含一个一维结构,即其边列表。图 1 显示了有向图的邻接表表示。
VertexList类的adjacency_list模板参数控制使用哪种容器来表示外部二维容器。OutEdgeList模板参数控制使用哪种容器来表示边列表。对OutEdgeList和VertexList的选择将决定图结构的空间复杂度,并将决定各种图操作的时间复杂度。可能的选项和权衡在选择 Edgelist 和 VertexList 一节中讨论。Directed模板参数控制图是有向的、无向的,还是有向的且可以访问入边和出边(我们称之为双向的)。双向图占用有向图(每条边)的两倍空间,因为每条边都将出现在出边列表和入边列表中。图 2 显示了无向图的邻接表表示。
关于如何使用adjacency_list类的教程在使用 adjacency_list 一节中。
examples/family_tree.cpp 中的示例展示了如何用图表示家谱。
参数 | 描述 | 默认值 |
---|---|---|
OutEdgeList | 用于表示每个顶点的边列表的容器的选择器。 | vecS |
VertexList | 用于表示图的顶点列表的容器的选择器。 | vecS |
Directed | 一个选择器,用于选择图是有向的、无向的,还是有向的且具有双向边访问(访问出边和入边)。选项是directedS, undirectedS和bidirectionalS. | directedS |
VertexProperties | 用于指定内部属性存储。 | no_property |
EdgeProperties | 用于指定内部属性存储。 | no_property |
GraphProperties | 用于指定图对象的属性存储。 | no_property |
EdgeList | 用于表示图的边列表的容器的选择器。 | listS |
VertexAndEdgeListGraph、MutablePropertyGraph、可复制构造、可赋值 和 可序列化。
boost/graph/adjacency_list.hpp
此外,序列化功能位于 boost/graph/adj_list_serialize.hpp 中。
可以使用属性将颜色、距离、权重和用户定义的属性等属性附加到图的顶点和边。可以通过图提供的属性映射读取和写入属性值。属性映射是通过get(property, g)函数获得的。如何在内部属性一节中描述了如何使用属性。属性映射是实现属性映射概念中定义的接口的对象,或者可以是捆绑属性,它们具有更简洁的语法。所有属性值的类型必须是可复制构造的、可赋值的和默认构造的。从adjacency_list类获得的属性映射是左值属性映射概念的模型。如果adjacency_list是 const,则属性映射是常量,否则属性映射是可变的。
如果图的VertexList是vecS,则该图具有通过vertex_index_t属性的属性映射访问的内置顶点索引。索引落在[0, num_vertices(g))范围内并且是连续的。删除顶点时,将调整索引,以便它们保留这些属性。使用这些索引访问外部属性存储时必须小心。顶点索引的属性映射是可读属性映射的模型。
typedef adjacency_list<listS, vecS> Graph; // VertexList=vecS Graph G(N); // Fill in the graph... // Attempt to remove all the vertices. Wrong! graph_traits<Graph>::vertex_iterator vi, vi_end; for (boost::tie(vi, vi_end) = vertices(G); vi != vi_end; ++vi) remove_vertex(*vi, G); // Remove all the vertices. This is still wrong! graph_traits<Graph>::vertex_iterator vi, vi_end, next; boost::tie(vi, vi_end) = vertices(G); for (next = vi; vi != vi_end; vi = next) { ++next; remove_vertex(*vi, G); }出现问题的原因是我们正在调用remove_vertex(),当与adjacency_list一起使用时,其中VertexList=vecS,它会使图的所有迭代器和描述符失效(例如vi和vi_end),从而在循环的后续迭代中 causing trouble in subsequent iterations of the loop.
如果我们使用不同类型的adjacency_list,其中VertexList=listS,则调用remove_vertex不会使迭代器失效,除非迭代器指向被移除的实际顶点。以下代码对此进行了演示。
typedef adjacency_list<listS, listS> Graph; // VertexList=listS Graph G(N); // Fill in the graph... // Attempt to remove all the vertices. Wrong! graph_traits<Graph>::vertex_iterator vi, vi_end; for (boost::tie(vi, vi_end) = vertices(G); vi != vi_end; ++vi) remove_vertex(*vi, G); // Remove all the vertices. This is OK. graph_traits<Graph>::vertex_iterator vi, vi_end, next; boost::tie(vi, vi_end) = vertices(G); for (next = vi; vi != vi_end; vi = next) { ++next; remove_vertex(*vi, G); }
稳定性问题还影响顶点和边描述符。例如,假设您使用顶点描述符向量来跟踪最短路径树中顶点的父级(或前驱)(请参阅 examples/dijkstra-example.cpp)。您通过调用dijkstra_shortest_paths()创建父向量,然后从图中移除一个顶点。随后您尝试使用父向量,但由于所有顶点描述符都已失效,因此结果不正确。
std::vector<Vertex> parent(num_vertices(G)); std::vector<Vertex> distance(num_vertices(G)); dijkstra_shortest_paths(G, s, distance_map(&distance[0]). predecessor_map(&parent[0])); remove_vertex(s, G); // Bad idea! Invalidates vertex descriptors in parent vector. // The following will produce incorrect results for(boost::tie(vi, vend) = vertices(G); vi != vend; ++vi) std::cout << p[*vi] << " is the parent of " << *vi << std::endl;
请注意,在此讨论中,迭代器和描述符失效与不受操作直接影响的迭代器和描述符的失效有关。例如,执行remove_edge(u, v, g)将始终使任何 (u,v) 的边描述符或指向 (u,v) 的边迭代器失效,而与adjacency_list的类型无关。在关于迭代器和描述符失效的讨论中,我们只关心remove_edge(u, v, g)对指向其他边(不是 (u,v))的边描述符和迭代器的影响。
通常,如果您希望顶点和边描述符是稳定的(永不失效),请使用listS或setS作为VertexList和OutEdgeList的模板参数。如果您不太关心描述符和迭代器稳定性,而更关心内存消耗和图遍历速度,请使用adjacency_list和/或vecS作为VertexListvecSOutEdgeList模板参数。
下表总结了哪些操作会导致描述符和迭代器失效。表中,EL是OutEdgeList和EdgeList的缩写,VertexListVL表示, VertexList和。“邻接迭代器”类别包括out_edge_iterator
in_edge_iterator | 和 | adjacency_iterator | 类型。每个操作的文档中都提供了对描述符和迭代器失效的更详细描述。 | **表:**描述符和迭代器失效摘要。 | 函数 |
---|---|---|---|---|---|
顶点描述符 | 边描述符 | 边描述符 | 边描述符 | 顶点迭代器 边迭代器 |
邻接迭代器 |
add_edge() 正常 EL=vecS && Directed=directedS EL=vecS |
边描述符 | 边描述符 | 边描述符 | 顶点迭代器 边迭代器 |
邻接迭代器 |
remove_edge() | 边描述符 | 边描述符 | 边描述符 | remove_edge_if() 边迭代器 |
remove_edge_if() 边迭代器 |
remove_vertex() | remove_out_edge_if() | remove_out_edge_if() | remove_out_edge_if() | remove_out_edge_if() | remove_out_edge_if() |
adjacency_list(const GraphProperty& p = GraphProperty())hash_setS
adjacency_list(const adjacency_list& x)变体的OutEdgeList不允许平行边,而其他变体允许平行边。
adjacency_list& operator=(const adjacency_list& x)graph_traits<adjacency_list>::vertices_size_typeOutEdgeList不允许平行边,而其他变体允许平行边。
adjacency_list(vertices_size_type n, const GraphProperty& p = GraphProperty())adjacency_list_traits<OutEdgeList, VertexList, Directed_list, EdgeList>::vertices_size_type用于处理图中顶点数量的类型。graph_traits<adjacency_list>::edges_size_type
template <class EdgeIterator> adjacency_list(EdgeIterator first, EdgeIterator last, vertices_size_type n, edges_size_type m = 0, const GraphProperty& p = GraphProperty())创建一个具有 n 个顶点且边在范围 [first, last) 给定的边列表中指定的图对象。 EdgeIterator 必须是 输入迭代器 的模型。EdgeIterator的取值类型必须是std::pair,其中 pair 中的类型是整数类型。这些整数将对应于顶点,并且它们必须全部落在[0, n).
template <class EdgeIterator, class EdgePropertyIterator> adjacency_list(EdgeIterator first, EdgeIterator last, EdgePropertyIterator ep_iter, vertices_size_type n, edges_size_type m = 0, const GraphProperty& p = GraphProperty())adjacency_list_traits<OutEdgeList, VertexList, Directed_list, EdgeList>::vertices_size_type用于处理图中顶点数量的类型。范围内。创建一个具有 `n` 个顶点,且边在范围[first, last)返回的迭代器的类型。当EdgeIterator和给定的边列表中指定的图对象。必须是 输入迭代器 的模型。EdgeIterator的取值类型必须是std::pair,其中 pair 中的类型是整数类型。这些整数将对应于顶点,并且它们必须全部落在[0, n)返回的迭代器的类型。当value_type的ep_iter应该是EdgeProperties.
void clear()从图中移除所有边和顶点。
void swap(adjacency_list& x)将此图的顶点、边和属性与图OutEdgeList.
std::pair<vertex_iterator, vertex_iterator> vertices(const adjacency_list& g)结构访问返回一个迭代器范围,提供对图.
std::pair<edge_iterator, edge_iterator> edges(const adjacency_list& g)的顶点集的访问。返回一个迭代器范围,提供对图.
std::pair<adjacency_iterator, adjacency_iterator> adjacent_vertices(vertex_descriptor u, const adjacency_list& g)返回一个迭代器范围,提供对图的边集的访问。返回一个迭代器范围,提供对与顶点在图中相邻的顶点的访问。返回一个迭代器范围,提供对图例如,如果u -> v是图中的一条边,则v将在此迭代器范围内。
std::pair<inv_adjacency_iterator, inv_adjacency_iterator> inv_adjacent_vertices(vertex_descriptor u, const adjacency_list& g)返回一个迭代器范围,提供对图中与返回一个迭代器范围,提供对图相邻的顶点的访问。(返回一个迭代器范围,提供对与顶点uinv表示反向。) 例如,如果v -> u是图中的一条边,则v是图中的一条边,则 `u` 将在此迭代器范围内。此函数仅适用于双向和无向adjacency_list图。
std::pair<out_edge_iterator, out_edge_iterator> out_edges(vertex_descriptor u, const adjacency_list& g)返回一个迭代器范围,提供对顶点返回一个迭代器范围,提供对与顶点在图中相邻的顶点的访问。返回一个迭代器范围,提供对图u 的出边的访问。如果图是无向图,则此迭代器范围提供对顶点 `u` 上所有关联边的访问。对于有向图和无向图,对于出边返回一个迭代器范围,提供对与顶点ue, source(e, g) == u和target(e, g) == v一起使用时,其中v其中 v 是与 u 相邻的顶点。返回一个迭代器范围,提供对与顶点.
std::pair<in_edge_iterator, in_edge_iterator> in_edges(vertex_descriptor v, const adjacency_list& g)返回一个迭代器范围,提供对顶点 `u` 的入边的访问。此操作仅在为v在图中相邻的顶点的访问。返回一个迭代器范围,提供对图ubidirectionalSDirectedSDirected时可用。 对于入边 `e`,e, target(e, g) == v和source(e, g) == ue返回一个迭代器范围,提供对与顶点存在某个顶点 `v`,使得 `target(e,g) == u`,其中 `v` 是与 `u` 相邻的顶点,无论该图是有向图还是无向图。vu
vertex_descriptor source(edge_descriptor e, const adjacency_list& g)返回边 `e` 的源顶点。e.
vertex_descriptor target(edge_descriptor e, const adjacency_list& g)返回边 `e` 的目标顶点。e.
degree_size_type out_degree(vertex_descriptor u, const adjacency_list& g)返回离开顶点 `u` 的边数。返回一个迭代器范围,提供对与顶点.
degree_size_type in_degree(vertex_descriptor u, const adjacency_list& g)返回进入顶点 `u` 的边数。此操作仅在为返回一个迭代器范围,提供对与顶点ubidirectionalSDirectedSDirected时可用。
vertices_size_type num_vertices(const adjacency_list& g)返回图中的顶点数。返回一个迭代器范围,提供对图.
edges_size_type num_edges(const adjacency_list& g)返回图中的边数。返回一个迭代器范围,提供对图.
vertex_descriptor vertex(vertices_size_type n, const adjacency_list& g)返回图的顶点列表中的第 n 个顶点。
std::pair<edge_descriptor, bool> edge(vertex_descriptor u, vertex_descriptor v, const adjacency_list& g)如果从顶点返回一个迭代器范围,提供对与顶点到顶点v存在边,则返回一个包含这样一条边和的 pair。 如果和返回一个迭代器范围,提供对与顶点和v之间没有边,则返回一个包含任意边描述符和的 pair。.
std::pair<out_edge_iterator, out_edge_iterator> edge_range(vertex_descriptor u, vertex_descriptor v, const adjacency_list& g)返回一对出边迭代器,给出从返回一个迭代器范围,提供对与顶点到v的所有平行边的范围。此函数仅在OutEdgeList作为adjacency_list是一个根据目标顶点对出边进行排序并允许多条平行边的容器时有效。multisetS选择器选择这样的容器。
std::pair<edge_descriptor, bool> add_edge(vertex_descriptor u, vertex_descriptor v, adjacency_list& g)将边 *(u,v)* 添加到图中,并返回新边的边描述符。对于不允许平行边的图,如果边已在图中,则不会添加重复边,并且bool标志将为的 pair。false的 pair。。当标志为 `false` 时,返回的边描述符指向已存在的边。
新边在出边列表中的位置通常未指定,但可以通过选择OutEdgeList来实现出边列表的排序。如果VertexList选择器是vecS,并且如果任一顶点描述符(它们是整数)的值大于图中当前顶点数,则会放大图,使得顶点数为返回一个迭代器范围,提供对与顶点或vvstd::max(u,v) + 1.
如果图的OutEdgeList选择器是vecS在 `vecS` 的情况下,此操作将使任何表示对于顶点 *u* 无效。 如果OutEdgeList是一个在调用push(container, x)时使其迭代器无效的用户定义容器(请参阅自定义邻接表存储部分),则同样适用。如果图也是双向图,则任何 `out_edge_iterator`VertexList对于 *v* 也将失效。 如果图是无向图,则任何表示对于 *v* 也将失效。 如果图是有向图,则顶点描述符还会使任何VertexList=vecS.
std::pair<edge_descriptor, bool> add_edge(vertex_descriptor u, vertex_descriptor v, const EdgeProperties& p, adjacency_list& g)对于 *v* 失效。将边 *(u,v)* 添加到图中,并将 `p` 附加为边内部属性存储的值。另请参阅之前的 `add_edge()` 非成员函数以获取更多详细信息。add_edge()顶点描述符非成员函数以获取更多详细信息。
void remove_edge(vertex_descriptor u, vertex_descriptor v, adjacency_list& g)从图中移除边 *(u,v)*。
此操作将导致指向边 *(u,v)* 的任何未完成的边描述符或迭代器失效。此外,如果OutEdgeList选择器是vecS是 `vecS`,则此操作将使指向顶点 *u* 的边列表以及无向和双向情况下顶点 *v* 的边列表中的任何迭代器失效。此外,对于有向图,这会使任何VertexList=vecS.
void remove_edge(edge_descriptor e, adjacency_list& g)从图中移除边 `e`。这与eremove_edge(u,v,g)remove_edge(u, v, g)函数在多重图的情况下不同。此remove_edge(e, g)函数移除单个边,而remove_edge(u, v, g)函数移除所有边 *(u,v)*。
此操作使描述符 `e` 指向的相同边的任何未完成的边描述符和迭代器失效。此外,此操作将使指向ee的边列表中的任何迭代器失效。 此外,对于有向图,这会使任何in_edge_iteratorVertexList=vecS)、无向的(
void remove_edge(out_edge_iterator iter, adjacency_list& g)这与remove_edge(*iter, g)具有相同的效果。 不同之处在于,此函数在有向图的情况下具有恒定的时间复杂度,而 `remove_edge(*iter, g)` 具有 *O(E/V)* 的时间复杂度。remove_edge(e, g)remove_edge(*iter, g)
template <class Predicate> void remove_out_edge_if(vertex_descriptor u, Predicate predicate, adjacency_list& g)从图中移除顶点 *u* 的所有满足谓词的出边。 也就是说,如果谓词应用于边描述符时返回 true,则移除该边。Predicate
对描述符和迭代器稳定性的影响与对每个移除的边调用add_edge()相同。
template <class Predicate> void remove_in_edge_if(vertex_descriptor v, Predicate predicate, adjacency_list& g)从图中移除顶点 *v* 的所有满足谓词的入边。谓词的出边。 也就是说,如果谓词应用于边描述符时返回 true,则移除该边。Predicate
对描述符和迭代器稳定性的影响与对每个移除的边调用add_edge()相同。
此操作可用于无向和双向adjacency_list图,但不能用于有向图。
template <class Predicate> void remove_edge_if(Predicate predicate, adjacency_list& g)从图中移除所有满足谓词的边。谓词的出边。 也就是说,如果谓词应用于边描述符时返回 true,则移除该边。Predicate
对描述符和迭代器稳定性的影响与对每个移除的边调用add_edge()相同。
vertex_descriptor add_vertex(adjacency_list& g)向图中添加一个顶点,并返回新顶点的顶点描述符。
vertex_descriptor add_vertex(const VertexProperties& p, adjacency_list& g)向图中添加一个具有指定属性的顶点。返回新顶点的顶点描述符。
void clear_vertex(vertex_descriptor u, adjacency_list& g)移除顶点 *u* 的所有出入边。该顶点仍然出现在图的顶点集中。
对描述符和迭代器稳定性的影响与对每个移除的边调用add_edge()此操作使所有以返回一个迭代器范围,提供对与顶点失效。
void clear_out_edges(vertex_descriptor u, adjacency_list& g)移除顶点 *u* 的所有出边。该顶点仍然出现在图的顶点集中。
对描述符和迭代器稳定性的影响与对每个移除的边调用add_edge()此操作使所有以返回一个迭代器范围,提供对与顶点此操作使所有以 `u` 作为源的边的 `edge_descriptor` 失效。
此操作不适用于无向图(请改用EL=vecS)。
void clear_in_edges(vertex_descriptor u, adjacency_list& g)移除顶点 *u* 的所有入边。该顶点仍然出现在图的顶点集中。
对描述符和迭代器稳定性的影响与对每个移除的边调用add_edge()此操作使所有以返回一个迭代器范围,提供对与顶点此操作使所有以 `u` 作为目标的边的 `edge_descriptor` 失效。
此操作仅适用于双向图。
void remove_vertex(vertex_descriptor u, adjacency_list& g)从图的顶点集中移除顶点 *u*。 假设移除顶点 *u* 时,没有指向或来自顶点 *u* 的边。 确保这一点的一种方法是事先调用EL=vecS。
如果图的VertexList类的adjacency_list是vecS,则此操作会使图的所有顶点描述符、边描述符和迭代器失效。 每个顶点的内置vertex_index_t属性将重新编号,以便在操作后顶点索引仍然形成连续范围[0, num_vertices(g))。 如果您正在使用基于内置顶点索引的外部属性存储,则需要调整外部存储。 另一种选择是不使用内置顶点索引,而是使用属性来添加您自己的顶点索引属性。 如果您需要频繁使用remove_vertex()函数,则listS选择器是VertexList时可用。
template <class PropertyTag> property_map<adjacency_list, PropertyTag>::type get(PropertyTag, adjacency_list& g) template <class PropertyTag> property_map<adjacency_list, Tag>::const_type get(PropertyTag, const adjacency_list& g)属性映射访问器指定的顶点属性的属性映射对象。返回的迭代器的类型。当指定的顶点属性的属性映射对象。必须与图的模板参数中指定的属性之一匹配。template argument.
template <class PropertyTag, class X> typename property_traits<property_map<adjacency_list, PropertyTag>::const_type>::value_type get(PropertyTag, const adjacency_list& g, X x)的属性值,其中 `d` 是顶点或边描述符。OutEdgeList,其中OutEdgeListd
template <class PropertyTag, class X, class Value> void put(PropertyTag, const adjacency_list& g, X x, const Value& value)的属性值为OutEdgeList到。 `value` 的类型. OutEdgeListdValue必须可转换为typename property_traits<property_map<adjacency_list, PropertyTag>::type>::value_type
template <class GraphProperties, class GraphPropertyTag> typename graph_property<adjacency_list, GraphPropertyTag>::type& get_property(adjacency_list& g, GraphPropertyTag);指定的附加到图对象GraphPropertyTag的属性。返回一个迭代器范围,提供对图返回的迭代器的类型。当graph_propertyboost/graph/adjacency_list.hpp 中定义了 `graph_property_traits` 类。
template <class GraphProperties, class GraphPropertyTag> const typename graph_property<adjacency_list, GraphPropertyTag>::type& get_property(const adjacency_list& g, GraphPropertyTag);指定的附加到图对象GraphPropertyTag的属性。返回一个迭代器范围,提供对图返回的迭代器的类型。当graph_propertyboost/graph/adjacency_list.hpp 中定义了 `graph_property_traits` 类。
template<class SavingArchive> SavingArchive& operator<<(SavingArchive& ar, const adjacency_list& graph);将图序列化到存档中。要求图的顶点和边属性是可序列化的。
template<class LoadingArchive> LoadingArchive& operator>>(LoadingArchive& ar, const adjacency_list& graph);从存档中读取图。要求图的顶点和边属性是可序列化的。
版权所有 © 2000-2001 |
Jeremy Siek, 印第安纳大学 ([email protected]) 李烈权, 印第安纳大学 ([email protected]) Andrew Lumsdaine, 印第安纳大学 ([email protected]) |