我有以下内容。结构是原型的,所以它编译得很好。
struct vertexNodeInfo
{
vector<vertexNodeInfo> node;
};
我正在尝试写一个八叉树。我想要做的是使用递归函数继续向每个节点添加一个节点,直到我到达一个特定的点,此时该函数,而不是添加另一个节点,添加一个叶子。
,如果没有其他节点或叶子,我想不使用内存。也许模板会在这种情况下有所帮助,但我不确定如何使用它们......
我认为我没有很好地解释自己。这是一个图表:
我不知道我要求的东西是不可能的,也不是太容易理解,或者只是简单的愚蠢,但我无法自己解决。对不起,我无法解释它。
我使用的是C ++ 98/03(VC ++ 2008),无法使用C ++ 11
任何帮助都会非常感激。
附加信息:
更好的解释:我想要一个数组数组的数组数组。内存使用非常重要(我存储了数百万个元素,因此单个字节会产生巨大差异)。每个数组可以包含8个以上的数组,但在我需要使用它之前,我希望每个数组都不使用内存。这是一种八叉树。
更多其他信息:
这是另一张图。它有点大,所以您可能需要右键单击它并选择Open image in new tab
以使其可读。
我不想要的是“棕色”(红色+绿色)框,其中每个框都为更多节点和叶数据保留内存。这将为我的需求使用太多的记忆。
这基本上就是我想要实现的,为简单起见为2D:
答案 0 :(得分:6)
没有任何(手动)堆分配 [1] :
struct NodeInfo {
int id;
};
using Tree = boost::make_recursive_variant<
NodeInfo,
std::vector<boost::recursive_variant_>
>::type;
我知道变体带有自己的“复杂性”,但保留了内存局部性并避免了手动内存管理。
现在,为了更接近您声明的优化目标,您可以使用std::array<T, 8>
代替std::vector
,或者只是让vector
使用自定义allocator
进行分配来自内存池。
示例程序(见 Live on Coliru ):
#include <iostream>
#include <boost/variant.hpp>
#include <vector>
struct NodeInfo {
int id;
};
using Tree = boost::make_recursive_variant<
NodeInfo,
std::vector<boost::recursive_variant_>
>::type;
// for nicer code:
using Branch = std::vector<Tree>;
using Leaf = NodeInfo;
static std::ostream& operator<<(std::ostream& os, Leaf const& ni) {
return os << ni.id;
}
static std::ostream& operator<<(std::ostream& os, Branch const& b) {
os << "{ ";
for (auto& child: b) os << child << " ";
return os << "}";
}
int main()
{
Branch branch1 {
Leaf { 2 },
Leaf { 1 },
Branch {
Leaf { 42 },
Leaf { -42 },
}
};
Tree tree = Branch { branch1, Leaf { 0 }, branch1 };
std::cout << tree << "\n";
}
打印:
{ { 2 1 { 42 -42 } } 0 { 2 1 { 42 -42 } } }
[1] (在使用std :: vector之外)
答案 1 :(得分:2)
八叉树的核心结构是
struct Node {
std::vector<T> items;
std::array<std::unique_ptr<Node>, 8> subnodes;
Box BoundingBox;
};
class Octree {
Node n;
//... stuff
public:
Octree(Box location)
: n(location) {}
};
如果您在叶节点上需要额外的几个字节(以及非叶子节点上丢失的几个字节),您可以尝试使用指向子节点数组的指针,而不是按值保存它。
现在,如果 T是一个点,那么你可以使用boost :: variant来仅存储items
或 {{ 1}},因为每个点都保证只存在于一个子节点中,并且您可以在subnodes
和items
之间选择一个任意的截止点。
否则如果T是一种边界框,你就无法逃脱这一点,因为不完全适合任何子节点的边界框必须进入subnodes
列表,所以{{ 1}}列表必须存在,无论是否有子节点。
我还要说的是,如果你急需时间或空间优化,你应该认真研究自定义内存分配例程。
编辑:是的,我使用了一个指针数组,而不是一个指向数组的指针。长而短的是,在没有强大的C ++ 11支持的情况下描述该数组的正确初始化是一个完全的婊子,并且在我个人的使用中,它并不能保证我实际做出该死的事情的严重问题。如果需要,您可以尝试items
。从理论上讲,它应该是最好的选择。
答案 2 :(得分:0)
polimorphism怎么样?
struct TreeElem {
virtual ~TreeElem() {}
};
struct Node : public TreeElem {
std::vector<TreeElem*> _children;
};
struct Leaf : public TreeElem {
int _value;
};
你可以弄清楚其余的(TreeElem的虚拟成员)。
P.S:如果它不仅仅是微不足道的话,请使用智能指针。
答案 3 :(得分:-1)
检查che composite pattern,您可以轻松调整它以执行八叉树。在此之后,创建递归函数,将实际的八叉树深度作为参数,这样您就可以执行所需的操作。不幸的是,我不太了解你的问题所以我不能更精确。