我正在尝试使用boost序列化序列化大型(几何)图形结构。
我将我的图形存储为邻接列表,也就是说,我的结构如下:
class Node {
double x,y;
std::vector<Node*> adjacent_nodes;
...
}
class Graph {
std::vector<Node*> nodes;
...
}
现在使用&gt; 10k个节点我的问题是,当我开始序列化(保存)我的图形时,它会在返回之前递归调用所有这些节点的序列化,因为图形是连接的。
更准确地说,在序列化Graph时,它将通过序列化&#34;节点中的第一个节点来开始。向量。在这样做时,它需要序列化&#34; adjacent_nodes&#34;第一节点的一部分,例如,包含第二个节点。
因此,它需要在返回第一个节点的序列化之前序列化第二个节点,依此类推。
我从2010年发现了this thread,其中有人解释了完全相同的问题。但是,他们没有在那里找到有效的解决方案。
非常感谢任何帮助。
我的结构更详细:
class Node {
double x,y;
std::vector<Node*> adjacent_nodes;
public:
inline double get_x() const { return x; }
inline double get_y() const { return y; }
inline std::vector<Node*> const& get_adjacent_nodes() const { return adjacent_nodes; }
Node (double x, double y):x(x),y(y) {}
void add_adjacent(Node* other) {
adjacent_nodes.push_back(other);
}
private:
Node() {}
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive &ar, const unsigned int) {
ar & x;
ar & y;
ar & adjacent_nodes;
}
};
class Simple_graph {
std::vector<Node*> nodes;
void add_edge(int firstIndex, int secondIndex) {
nodes[firstIndex]->add_adjacent(nodes[secondIndex]);
nodes[secondIndex]->add_adjacent(nodes[firstIndex]);
}
public:
/* methods to get the distance of points, to read in the nodes, and to generate edges */
~Simple_graph() {
for (auto node: nodes) {
delete node;
}
}
private:
friend class boost::serialization::access;
template <class Archive>
void serialize(Archive &ar, const unsigned int) {
ar & nodes;
}
};
编辑:在上述主题中添加一些建议,引用Dominique Devienne:
1)在第一次传递时保存所有节点而不用它们的拓扑信息 向量,因此记录所有&#34;跟踪&#34;那么指针呢 为每个人写下拓扑信息,从那以后你就不会“re re” 只写一个&#34; ref&#34;到已经序列化的指针。
2)有可能写一个&#34;弱参考&#34;指针, 只添加了指向&#34;追踪&#34;用特殊标志映射 说它不是真的&#34;写的,这样写的拓扑 一个尚未编写的节点类似于&#34;前向引用&#34;至 那些相邻的节点。要么以后真的要写节点 在,或它永远不会,我想序列化应该处理 优雅。
#1并不需要更改boost序列化,但将责任放在客户端代码上。特别是因为你必须&#34;外部&#34;保存 邻居,所以它不再被很好地封装,并编写一个子集 表面的节点变得更加复杂。
#2需要提前寻找在遇到前向引用时读取实际对象,以及另外一个单独的映射 知道在哪里寻找它。这可能与助推器不相容 序列化(我承认对此几乎一无所知)。
现在可以实施这些提案吗?
答案 0 :(得分:1)
由于您已经有一个带有指向所有节点的指针的向量,因此您可以使用索引序列化adjacent_nodes
向量,而不是序列化实际的节点数据。
在序列化节点时,您需要将this
指针转换为索引。如果您可以将节点索引存储在节点中,这是最简单的,否则您必须通过nodes
搜索才能找到正确的指针(可以通过创建某种关联容器来加速此过程)指向索引的指针。)
当您需要读入数据时,您可以创建初始nodes
向量,其中包含指向空/虚节点的指针(将在序列化时填充)。
如果这不可行,您可以将节点索引加载到临时数组中,然后在读入所有节点后返回并填充指针。但是您不必寻求或重新阅读文件的任何部分。
答案 1 :(得分:0)
如果图形中没有任何较大的循环,则可以按照图的“ end ”中的节点出现在矢量开头的方式对Node矢量进行排序。
示例: 假设我们有:
p1->p2->p3->....->p1000
如果您尝试序列化vector v = {p1, p2, p3, ... , p1000}
,将会失败
但它可以与vector v = {p1000, p999, p998, ... , p1}
一起使用
但是如果你有类似的东西
p1->p2->p3->....->p1000->p1