微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用 `ListS` 而不是 `VecS` 作为底层容器并能够做同样的事情?

如何解决如何使用 `ListS` 而不是 `VecS` 作为底层容器并能够做同样的事情?

我通常使用 vecS 作为 boost::adjacency_list 的容器:

struct myVertexType { std::vector<Stuff> vec; /* and more */ };
struct myEdgeType { /* some data too */ };
using Graph = boost::adjacency_list<
        boost::vecS,boost::vecS,boost::directedS,myVertexType,myEdgeType
    >;

然而,我遇到了一个引发问题的情况: 我引用了一些作为顶点捆绑属性存储的数据,当我创建另一个顶点时,这似乎使我的引用无效 (1)。

至少这是我从 reading this page 中了解到的(“迭代器和描述符稳定性/失效”部分)。

所以我切换到 listS,一切顺利:

using Graph = boost::adjacency_list<
        boost::listS,boost::listS,myEdgeType
    >;

直到...

直到我注意到 listS 时,boost::target( e1,g ) 无法编译! :

Graph g;
auto e1 = boost::add_edge(1,g).first;
auto t = boost::target( e1,g );

这也无法构建:(see on coliru)

Graph g;
boost::add_edge(1,g);
write_graphviz(std::cout,g );

所以我搜索了一下,找到了an answer by Sehe,说明

vecS一个隐式顶点索引。 listS 没有。因此它使用内部 property vertex_index_t

但是,给定的答案使用内部属性 (?)(或者是动态属性?)并且我使用自己的数据类型来表示顶点和边。

所以我的问题是:

如何构建基于列表的图形类型,使我能够执行 VecS 允许的所有“常规内容”?

(1) 说清楚一点,我引用了一个顶点中的向量,当我创建另一个顶点时,向量突然变空了!

编辑:阐明我的节点内的内容

解决方法

背景

“当我创建另一个顶点时,这似乎使我的引用无效(1)。”

是的,这是可能的。

您必须意识到在您选择容器选择器的基础上存在更大的性能权衡。许多算法可以获得非常不同的效率特征。

此外,一些语义也发生了微妙的变化(例如,当使用 setS 作为边缘容器选择器时,您自然不能再有重复的边缘;这也是 add_edge 返回 pair<descriptor,bool> 的原因)。

还要意识到通常您不需要引用甚至迭代器稳定性。 BGL 中的典型编码模式是传递/保持对属性(包)的引用,而是按值传递属性映射

属性映射抽象了对(可变)属性的访问。

您通常可以传递通常稳定的描述符(除非您要删除 vecS 中“中间”的顶点,因为所有后续顶点的隐含顶点索引明显发生变化).

也就是说,让我们继续解决您的问题:

问题

直到我注意到使用 listS,boost::target( e1,g ) 无法编译!

没有。编译得很好。

不好的是你用整数参数调用 add_edge。顶点描述符与列表/集合(基于节点的容器)不是一个整体。

更糟糕的是,不会为非 vecS adjacency_list 自动添加顶点,因此您无论如何都会引用超出范围的顶点。

引用这些的一般方法是:

V v0 = add_vertex(g);
V v1 = add_vertex(g);
auto [e1,inserted] = boost::add_edge(v0,v1,g);
assert(inserted);
[[maybe_unused]] V t = boost::target(e1,g);

graphviz 调用也很好,但由于同样的原因在 add_edge...

另外,你需要添加一个顶点索引。作为内部属性或将属性映射传递给算法函数。

这是一个完整的测试演示,展示了所有三种口味:

Live On Coliru

#include <boost/algorithm/string.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/core/demangle.hpp>
#include <iostream>
#include <numeric>
using boost::core::demangle;
using boost::algorithm::replace_all_copy;

struct myVertexType { /* some data */ };
struct myEdgeType { /* some data too */ };

template <typename containerS> void tests() {
    using Graph = boost::adjacency_list<
        containerS,containerS,boost::directedS,myVertexType,myEdgeType>;

    using V = typename Graph::vertex_descriptor;

    std::cout << "\n"
              << std::boolalpha << "tests() with "
              << demangle(typeid(containerS).name()) << " - "
              << "vertex_descriptor integral? " << std::is_integral<V>()
              << "\n";
    Graph g;

    V v0 = add_vertex(g);
    V v1 = add_vertex(g);
    auto [e1,g);
    assert(inserted);
    [[maybe_unused]] V t = boost::target(e1,g);

    std::ostringstream dot;
    if constexpr (std::is_same<boost::vecS,containerS>()) {
        boost::write_graphviz(dot,g);
    } else {
        std::map<V,int> index;
        for (auto v : boost::make_iterator_range(vertices(g)))
            index.emplace(v,index.size());

        auto index_map = boost::make_assoc_property_map(index);

        boost::dynamic_properties dp;
        dp.property("node_id",index_map); // get(boost::vertex_index,g)

        boost::write_graphviz_dp(dot,g,dp);
    }

    std::cout << "dot: " << replace_all_copy(dot.str(),"\n","") << "\n";
}

int main() {
    tests<boost::vecS>();
    tests<boost::setS>();
    tests<boost::listS>();
}

印刷品

tests() with boost::vecS - vertex_descriptor integral? true
dot: digraph G {0;1;0->1 ;}

tests() with boost::setS - vertex_descriptor integral? false
dot: digraph G {0;1;0->1 ;}

tests() with boost::listS - vertex_descriptor integral? false
dot: digraph G {0;1;0->1 ;}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?