我正在制作一棵树(本质上是一个前缀树,但对于数字而不是字符串),它是根据数字元组的排序列表构建的((1,1,2),(1,2,5),(2) ,1,0)等...),每一个都与一个标量值相关联(最可能是int或double)。由于它只构建一次然后多次迭代/搜索,我计划使用std :: vectors来保存每个节点的子节点。要搜索树,我只需要调用std :: lower_bound对每个节点的_children向量进行二进制搜索,该向量将包含每个节点的std ::对及其各自的键。但是,底部节点必须包含一个向量,该向量的对由每个元组中的最后一个条目及其各自的值组成,因此必须与BranchNode的类型不同。代码如下所示:
class GenNode
{
};
template<typename key_type,typename value_type>
class BranchNode : GenNode
{
void insert(std::pair< std::vector<key_type> , value_type>);
private:
std::vector< std::pair<key_type,GenNode*> > _children;
};
template<typename key_type,typename value_type>
class LeafNode : GenNode
{
private:
std::vector< std::pair<key_type,value_type> > _children;
};
然而,这真的很难看,因为这两个类必须从无用的GenNode类继承,以便每个BranchNode的子节点可以是其他BranchNodes或LeafNodes ...有更好的方法吗?
答案 0 :(得分:2)
如果要将两种类型存储在同一个向量中,则需要相关的类(一个继承自其他类或继承自共同祖先的类)。
拥有一个空的共同祖先可能看起来很难看。但是,如果将搜索操作(以及其他迭代/处理)作为虚方法放入基类,并在BranchNode
和LeafNode
中实现它,您可以获得更优雅的设计(实现将不同)。
在这种情况下,基类也应该模板化。 我的意思是拥有一个基类,如:
template<typename key_type,typename value_type>
class GenNode {
public:
virtual value_type search(key_type key) = 0;
};
答案 1 :(得分:2)
是的,您需要两种不同的类型。事实上,像这样的事件(Leaf OR Node
)被称为discriminated union。
有几种方法可以实现它,但在C ++中,有一个带有两个派生类的公共基类可能是最常见的。
有一个共同基础的有趣替代方法是boost::variant
使用recursive wrapper。这特别有趣,因为它避免使用指针(因此为您处理内存管理)。