You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Boost Labeled Graph删除顶点后仍存在的问题咨询

问题分析与解决

你遇到的问题核心是Boost Labeled Graph的remove_vertex操作不会自动清理标签到顶点描述符的映射。底层的邻接表确实已经删除了顶点(所以num_vertices返回1是对的),但标签映射里还保留着"1"对应的旧顶点描述符条目,导致graph.vertex("1")不会返回null_vertex()

为什么会这样?

labeled_graph是一个包装器,它在底层adjacency_list之上维护了一个标签到顶点描述符的哈希映射。当你调用remove_vertex时,它只会操作底层的邻接表,并不会同步更新这个映射。所以即使顶点已经被删除,标签仍然指向原来的(现在已经无效的)顶点描述符。

解决方案:手动移除标签

在删除顶点后,需要额外调用remove_label()方法来清理标签映射。这样后续调用vertex("1")就会正确返回null_vertex()

另外要注意:删除顶点后,原来的顶点描述符(比如v1)已经失效,不要再用它来执行任何图操作(比如检查边是否存在),因为底层邻接表的顶点存储已经发生了变化。

修改后的完整代码

#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/labeled_graph.hpp>
#include <cmath> // infinity
#include <cassert>
using namespace std;

struct EdgeProperties {
    double weight = INFINITY;
    EdgeProperties() = default;
    EdgeProperties(const double d) : weight(d) {}
};

struct Node {
    string id;
    Node() = default;
    Node(const string i) : id(i) {}
};

typedef boost::labeled_graph<boost::adjacency_list<boost::hash_setS, boost::hash_setS, directedS, Node, EdgeProperties>, std::string> BoostGraph;
typedef BoostGraph::vertex_descriptor Vertex;
typedef BoostGraph::edge_descriptor Edge;

int main(){
    BoostGraph graph;
    const Vertex& v1 = add_vertex("1", Node("1"), graph);
    const Vertex& v2 = add_vertex("2", Node("2"), graph);
    const pair<Edge, bool>& edge = add_edge(v1, v2, EdgeProperties(INFINITY), graph);

    assert(2 == boost::num_vertices(graph));
    assert(1 == boost::num_edges(graph));
    assert(boost::edge(v1, v2, graph).second); // edge from v1->v2 exists

    // 删除v1的正确步骤
    clear_vertex(v1, graph);          // 先清理该顶点的所有边
    graph.remove_vertex(v1);          // 从底层邻接表删除顶点
    graph.remove_label("1");          // 手动移除标签映射

    // 验证删除结果
    assert(graph.vertex("1") == graph.null_vertex()); // 现在会通过
    assert(1 == boost::num_vertices(graph));
    assert(0 == boost::num_edges(graph));
    // 注意:不能再用v1来检查边,改用通过标签获取v2的描述符
    Vertex v2_valid = graph.vertex("2");
    assert(not boost::edge(graph.null_vertex(), v2_valid, graph).second);

    cout << "All tests passed" << endl;
    return 0;
}

关键修改点

  1. 添加了graph.remove_label("1")来清理标签映射。
  2. 检查边是否存在时,不再使用已失效的v1,而是用null_vertex()或者重新获取有效的顶点描述符。

内容的提问来源于stack exchange,提问作者Saleem gagguturu

火山引擎 最新活动