箱柜的3D网格:嵌套的std :: vector vs std :: unordered_map

时间:2014-09-19 11:08:30

标签: c++ c++11 std boost-multi-array

专业人士,我需要一些表现意见,包括以下内容:

第一个问题:

我想将对象存储在3D网格结构中,总体来说它将被填充〜33%,即3个网格点中的2个将为空。 简短图片说明:

enter image description here

可能选项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?

另一个例子: enter image description here

使用选项1B我可以扩展Pos3D以包含桶号以解决更多稀疏数据。 我想要优化的可能查询:

  1. 从整个结构中删除ObjA-buckets中的所有对象
  2. 给我一些ObjB-buckets中的所有对象 网格位置
  3. 哪个是最近的非空ObjC-bucket 位置x,y,z?
  4. PS:

    之前我还考虑过基于树的数据结构,阅读最近邻居方法。由于我的数据是如此规则,我以为我会将所有树木构建的细胞分成更小的片段,然后制作最终叶片的静态3D网格。多数民众赞成我如何询问这里存储这个网格的最佳方法。 与此相关的问题,如果我有一个map<int, Obj>,是否有一种快速的方式来询问“所有带有780和790之间密钥的对象”?或者是构建上述树的最快方式?

    修改

    我最终选择了具有fortran排序功能的3D boost :: multi_array。这有点像像我的世界使用的大块游戏。这有点像使用固定叶片大小和固定叶片量的kd树?现在工作得非常快,所以我很满意这种方法。

1 个答案:

答案 0 :(得分:1)

回答第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)你要添加另一个向量。

  
      
  1. 哪个是最近的非空ObjC-bucket,用于定位x,y,z?
  2.   

此操作通常称为最近邻搜索。你想要一个KDTree。如果你喜欢小型库,那就有libkdtree ++。否则,FLANN可能是一个选项。它是Point Cloud Library的一部分,可以完成很多关于多维数据的任务,也值得一看。