C ++分支递归结构?

时间:2013-10-20 11:56:59

标签: c++ recursion struct octree

我有以下内容。结构是原型的,所以它编译得很好。

struct vertexNodeInfo
{
    vector<vertexNodeInfo> node;
};

我正在尝试写一个八叉树。我想要做的是使用递归函数继续向每个节点添加一个节点,直到我到达一个特定的点,此时该函数,而不是添加另一个节点,添加一个叶子。

,如果没有其他节点或叶子,我想不使用内存。

也许模板会在这种情况下有所帮助,但我不确定如何使用它们......

我认为我没有很好地解释自己。这是一个图表:

branching recursive struct

我不知道我要求的东西是不可能的,也不是太容易理解,或者只是简单的愚蠢,但我无法自己解决。对不起,我无法解释它。

我使用的是C ++ 98/03(VC ++ 2008),无法使用C ++ 11

任何帮助都会非常感激。

附加信息:

更好的解释:我想要一个数组数组的数组数组。内存使用非常重要(我存储了数百万个元素,因此单个字节会产生巨大差异)。每个数组可以包含8个以上的数组,但在我需要使用它之前,我希望每个数组都不使用内存。这是一种八叉树。

更多其他信息:

这是另一张图。它有点大,所以您可能需要右键单击它并选择Open image in new tab以使其可读。

想要的是“棕色”(红色+绿色)框,其中每个框都为更多节点和叶数据保留内存。这将为我的需求使用太多的记忆。

这基本上就是我想要实现的,为简单起见为2D:

2D example of my idea of an octree

4 个答案:

答案 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}},因为每个点都保证只存在于一个子节点中,并且您可以在subnodesitems之间选择一个任意的截止点。

否则如果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,您可以轻松调整它以执行八叉树。在此之后,创建递归函数,将实际的八叉树深度作为参数,这样您就可以执行所需的操作。不幸的是,我不太了解你的问题所以我不能更精确。