我有一个C ++类,表示一个非常大的分层组织数据树(~Gb,基本上和我在内存中可以消除的一样大)。它使用STL列表在每个节点上存储信息,并在其他节点上存储迭代器。每个节点只有一个父节点,但有0-10个子节点。 抽象,它看起来像:
struct node {
public:
node_list_iterator parent; // iterator to a single parent node
double node_data_array[X];
map<int,node_list_iterator> children; // iterators to child nodes
};
class strategy {
private:
list<node> tree; // hierarchically linked list of nodes
struct some_other_data;
public:
void build(); // build the tree
void save(); // save the tree from disk
void load(); // load the tree from disk
void use(); // use the tree
};
我想将load()和save()实现到磁盘,它应该相当快,但明显的问题是:
我事先并不知道尺寸;
数据包含迭代器 是不稳定的;
我对C ++的无知是惊人的。
请问有人建议使用纯C ++解决方案吗?
答案 0 :(得分:1)
您可以使用boost.serialization库。这将保存容器的整个状态,甚至是迭代器。
答案 1 :(得分:1)
boost.serialization是一个解决方案,或恕我直言,你可以使用SQLite +访客模式来加载和保存这些节点,但听起来并不容易。
答案 2 :(得分:1)
您似乎可以使用以下语法保存数据:
File = Meta-data Node
Node = Node-data ChildCount NodeList
NodeList = sequence (int, Node)
也就是说,序列化时,根节点包含所有节点,直接(子)或间接(其他后代)。编写格式非常简单:只需从根节点开始执行递归写入功能。
阅读并不是那么难。 std::list<node>
迭代器是稳定的。一旦插入了根节点,它的迭代器就不会改变,即使插入它的子节点也不会改变。因此,当您正在读取每个节点时,您已经可以设置父迭代器。这当然会让您使用子迭代器,但这些都是微不足道的:每个节点都是其父节点的子节点。因此,在您阅读完所有节点后,您将修复子迭代器。从第二个节点开始,第一个子节点(第一个节点一个是根节点)并迭代到最后一个子节点。然后,对于每个子C,将其父级和子级获取到其父级的集合。现在,这意味着您必须在阅读时将int
子ID设置为一边,但您可以在与std::list<node>
并行的简单std :: vector中执行此操作。一旦您修复了相应父母中的所有子ID,您就可以丢弃该矢量。
答案 3 :(得分:1)
已经提出过Boost Serialization,这当然是合理的可能性。
很大程度上取决于您将如何使用数据 - 您在内存中使用多路树的事实并不意味着您必须将其存储为磁盘上的多路树。既然你(显然)已经在推动你可以存储在内存中的限制,那么显而易见的问题是你是否只是对序列化数据感兴趣,这样你就可以重新构建同一棵树了。需要,或者你是否想要像数据库这样的东西,这样你就可以根据需要将部分信息加载到内存中,并根据需要更新记录。
如果你想要后者,你的一些选择也将取决于结构的静态程度。例如,如果某个特定节点有N个子节点,那么该数字是常数还是可以更改?如果它可能会发生变化,那么最大儿童人数是否有限制?
如果你确实希望能够遍历磁盘上的结构,那么显而易见的可能就是你写出来时,用相应数据的文件偏移代替你在内存中使用的迭代器。
或者,由于看起来(至少大部分)单个节点中的数据具有固定大小,因此您可以创建类似数据库的固定大小记录结构,并在每个记录记录中创建记录号。父/儿童。
提前了解整体尺寸并不是特别重要(即使事先知道,我也不会想到我会使用这个尺寸。)
答案 4 :(得分:1)
实际上,我认为您最好的选择是将整个数据结构移动到数据库表中。通过这种方式,您(或我)处理序列化问题时,您可以获得更聪明的人的利益。它还可以防止您不必担心结构是否适合内存。
答案 5 :(得分:0)
之前我已经回答了类似的事情,所以我将总结一下:
1. 使用数据库。
2.替换链接(指针)的文件偏移量
3.将没有树结构的数据存储在记录中,作为数据库
4.使用XML创建树结构,使用节点名称而不是链接
5.如果你使用像SqLite或MySQL 这样的数据库,这将会变得容易得多。
当您在“序列化”上花费太多时间而不是项目的主要目的时,您需要使用数据库。
答案 6 :(得分:-1)
如果您要这样做是为了持久化,那么可以从网上使用多种解决方案,例如google“ persist std :: list”,也可以使用mmap滚动创建自己的文件支持的内存区域。