Boost标签图不';不要删除顶点

Boost标签图不';不要删除顶点,boost,boost-graph,Boost,Boost Graph,我使用boost::labeled_graph来获取顶点的名称。但是,标签图并没有一个remove_vertex_by_label函数,所以我像下面的代码一样移除顶点。但删除后,vertex_by_标签返回不存在的顶点 #包括 #包括 #包括 #包括 使用名称空间std; 使用名称空间boost; typedef邻接列表< 名单, vecS, 无向 >图形; typedef标号图< 图表 一串 >标签图; int main(int argc,char*argv[]){ 标签图lg; 向量名{“a

我使用boost::labeled_graph来获取顶点的名称。但是,标签图并没有一个remove_vertex_by_label函数,所以我像下面的代码一样移除顶点。但删除后,vertex_by_标签返回不存在的顶点

#包括
#包括
#包括
#包括
使用名称空间std;
使用名称空间boost;
typedef邻接列表<
名单,
vecS,
无向
>图形;
typedef标号图<
图表
一串
>标签图;
int main(int argc,char*argv[]){
标签图lg;
向量名{“a”、“b”、“c”、“d”、“e”};
用于(自动名称:名称(&N)
添加_顶点(名称,lg);
移除顶点(顶点由标签(“c”,lg),lg.graph());

cout从你写的内容可以清楚地看出问题:

remove_vertex(vertex_by_label("c", lg), lg.graph());
您编写了
lg.graph()
,而不是
lg
。因此,您不应该期望从
lg
中删除任何内容。您明确要求仅从基础图形模型中删除某些内容

以下是正确的版本:

lg.remove_vertex("c");
为最大限度地方便起见,您可以使用重载自由函数:

remove_vertex("c", lg);
关于迭代器稳定性的注记 我没有看过实现,但它看起来像
标记的_图
适配器依赖于底层图的迭代器稳定性

对顶点容器选择器使用
邻接列表
向量
,记录所有后续迭代器和引用,这些迭代器和引用将在移除顶点时失效

下面是一个使用
列表
作为顶点容器选择器的固定演示,它完全符合您的期望

注意:我使用了一个顶点属性包作为“友好的”顶点id,因此您不必打印原始顶点描述符

#include <iostream>
#include <string.h>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/labeled_graph.hpp>

using namespace boost;

typedef adjacency_list<listS, listS, undirectedS, int> Graph;
typedef labeled_graph<Graph, std::string> LabeledGraph;

int main() {

    LabeledGraph lg;
    auto vid = get(vertex_bundle, lg.graph());

    int id = 0;
    for (std::string name : { "a", "b", "c", "d", "e" })
        add_vertex(name, id++, lg);

    std::cout << "===================\nnum_vertices = " << num_vertices(lg) << "\n";
    for (std::string name : { "a", "b", "c", "d", "e" })
        std::cout << name + " = " << vid[vertex_by_label(name, lg)] << "\n";
    for (auto v : make_iterator_range(vertices(lg)))
        std::cout << vid[v] << " ";
    std::cout << "\n";

    // lg.remove_vertex("c");
    remove_vertex("c", lg);

    std::cout << "===================\nnum_vertices = " << num_vertices(lg) << "\n";
    for (std::string name : { "a", "b", /* "c",*/ "d", "e" })
        std::cout << name + " = " << vid[vertex_by_label(name, lg)] << "\n";
    for (auto v : make_iterator_range(vertices(lg)))
        std::cout << vid[v] << " ";
    std::cout << "\n";
}

在寻找支持迭代器需求的文档时,我发现适配器根本不受支持:尽管有bug报告,但我的代码版本在boost 1.64上运行良好。确认ASan、UBSan和valgrind的代码是干净的。(显然,在移除适配器后使用顶点标签
“c”
,是UB。不要这样做)
#include <iostream>
#include <string.h>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/labeled_graph.hpp>

using namespace boost;

typedef adjacency_list<listS, listS, undirectedS, int> Graph;
typedef labeled_graph<Graph, std::string> LabeledGraph;

int main() {

    LabeledGraph lg;
    auto vid = get(vertex_bundle, lg.graph());

    int id = 0;
    for (std::string name : { "a", "b", "c", "d", "e" })
        add_vertex(name, id++, lg);

    std::cout << "===================\nnum_vertices = " << num_vertices(lg) << "\n";
    for (std::string name : { "a", "b", "c", "d", "e" })
        std::cout << name + " = " << vid[vertex_by_label(name, lg)] << "\n";
    for (auto v : make_iterator_range(vertices(lg)))
        std::cout << vid[v] << " ";
    std::cout << "\n";

    // lg.remove_vertex("c");
    remove_vertex("c", lg);

    std::cout << "===================\nnum_vertices = " << num_vertices(lg) << "\n";
    for (std::string name : { "a", "b", /* "c",*/ "d", "e" })
        std::cout << name + " = " << vid[vertex_by_label(name, lg)] << "\n";
    for (auto v : make_iterator_range(vertices(lg)))
        std::cout << vid[v] << " ";
    std::cout << "\n";
}
===================
num_vertices = 5
a = 0
b = 1
c = 2
d = 3
e = 4
0 1 2 3 4 
===================
num_vertices = 4
a = 0
b = 1
d = 3
e = 4
0 1 3 4