专业人士,我需要一些表现意见,包括以下内容:
我想将对象存储在3D网格结构中,总体来说它将被填充〜33%,即3个网格点中的2个将为空。 简短图片说明:
可能选项A)
vector<vector<vector<deque<Obj>> grid;// (SizeX, SizeY, SizeZ);
grid[x][y][z].push_back(someObj);
这样我就会有很多空的deques,但访问其中一个会很快,不是吗?
其他选项B)将是
std::unordered_map<Pos3D, deque<Obj>, Pos3DHash, Pos3DEqual> Pos3DMap;
我添加/删除数据时添加和删除deques。可能使用的内存较少,但可能不那么快?你觉得怎么样?
如果我在每个位置都有多个容器怎么办?对3个不同的实体说3个桶,比如对象类型ObjA,ObjB,ObjC每个网格点,那么我的数据基本上变成了4D?
另一个例子:
使用选项1B我可以扩展Pos3D以包含桶号以解决更多稀疏数据。 我想要优化的可能查询:
之前我还考虑过基于树的数据结构,阅读最近邻居方法。由于我的数据是如此规则,我以为我会将所有树木构建的细胞分成更小的片段,然后制作最终叶片的静态3D网格。多数民众赞成我如何询问这里存储这个网格的最佳方法。
与此相关的问题,如果我有一个map<int, Obj>
,是否有一种快速的方式来询问“所有带有780和790之间密钥的对象”?或者是构建上述树的最快方式?
修改
我最终选择了具有fortran排序功能的3D boost :: multi_array。这有点像像我的世界使用的大块游戏。这有点像使用固定叶片大小和固定叶片量的kd树?现在工作得非常快,所以我很满意这种方法。
答案 0 :(得分:1)
正如@Joachim所指出的,这取决于您是喜欢快速访问还是小数据。粗略地说,这对应于您的选项A和B.
A)如果您想要快速访问,请使用多维std::vector
或数组(如果您愿意)。 std::vector
以最小的开销带来更轻松的维护,所以我更喜欢这样。在空间方面,它消耗 O(N ^ 3)空间,其中<em> N 是沿一个维度的网格点数。为了在迭代数据时获得最佳性能,请记住按照您定义的相反顺序解析索引:最里面的,最后面的最后面。
B)如果您希望保持尽可能小的东西,请使用哈希映射,并使用针对空间进行优化的哈希映射。这将导致空间 O(N),其中 N 是元素的数量。这是一个比较几个哈希映射的benchmark。我使用google::sparse_hash_map获得了很好的经验,这是我迄今为止看到的最小的持续开销。此外,很容易将其添加到您的构建系统。
如果您需要混合速度和小数据,或者事先不知道每个维度的大小,也可以使用哈希映射。
如果你有第四个维度的可变数量的元素,或者固定的大量元素,我会说你的数据是4D。使用选项1B)你确实添加了桶索引,对于1A)你要添加另一个向量。
- 哪个是最近的非空ObjC-bucket,用于定位x,y,z?
醇>
此操作通常称为最近邻搜索。你想要一个KDTree。如果你喜欢小型库,那就有libkdtree ++。否则,FLANN可能是一个选项。它是Point Cloud Library的一部分,可以完成很多关于多维数据的任务,也值得一看。