我在尝试实现红黑树类时遇到了问题。我之前已经构建了一个二叉树类,所以我从它继承了我的红黑树。
二叉树声明是这样的:
template <typename KeyType, typename DataType>
class BTree{
protected:
struct BTreeNode{
KeyType key;
DataType data;
BTreeNode *left;
BTreeNode *right;
BTreeNode *parent;
BTreeNode(const KeyType &Key, const DataType &Data);
};
BTreeNode *root;
void clear(BTreeNode *root);
public:
BTree();
virtual ~BTree();
virtual bool insert(const KeyType &Key, const DataType &Data);
virtual bool erase(const KeyType &key);
DataType &getFirst(const KeyType &Key);
/**** some other methods ****/
}; // class bTree
红黑树是这样的:
template <typename KeyType, typename DataType>
class RBTree : public BTree<KeyType, DataType>{
protected:
struct RBTreeNode : BTree<KeyType, DataType>::BTreeNode{
enum RB{red, black} rb;
RBTreeNode(const KeyType &Key, const DataType &Data, RB Rb=red);
};
private:
void leftRotate(RBTreeNode *x);
void rightRotate(RBTreeNode *x);
public:
/**** some other methods ****/
}; // class RBTree
问题是,当我实施RBTree::leftRotate()
时,我必须写出RBTreeNode *y = x->right
和y=y->left
之类的内容,但x->right
和y->left
是{{1} },并且无法自动转换为BTreeNode *
。
我不希望我的代码充满RBTreeNode *
之类的内容,我也不想重新定义RBTreeNode或RBTree类,这意味着我必须重写BTree中的每个方法,如{ {1}}我可以直接使用。
那么我应该如何构建RBTree?我必须重写整个RBTree类吗?非常感谢。
答案 0 :(得分:0)
你可以使用这个技巧:
template <typename D>
struct Base{
D *root;
};
struct Derived : Base<Derived>
{
};
int main()
{
Derived x;
x.root = 0;
return 0;
}
我简化了很多你的例子并删除了所有其他模板参数,这些参数是不必要的,以说明这一点。请注意,Base类包含一个指向Derived类的指针,该类作为模板参数传递给它。
在您的情况下,将一个模板参数D添加到基类,定义基类类指针为D *类型,在定义派生类时,将派生类本身作为模板参数传递。例如。
template <typename KeyType, typename DataType>
class RBTree : public BTree<KeyType, DataType, RBTree<KeyType,DataType> >
{...}
这个主题有很多变化,例如,在你的情况下,你的模板参数可能是模板参数的模板。
当在基类中使用指向派生类的指针时,此技巧很有效。如果在基类中有一个实际的派生类实例,除非派生类没有数据成员,否则这通常是行不通的。