有没有办法对Bst和Avl树使用相同的插入功能?问题是Bst和Avl有不同的Node类型,但我不想让Bst Node成为一般情况(内部有高度和Node * parent,这没有任何意义,因为不需要内部的父和高度BST)。
class Bst
{
public:
struct Node
{
int value;
Node* left;
Node* right;
};
Node* insert(Node* node) {/* do stuff using Bst::Node */}
// ...
};
class Avl : public Bst
{
public:
struct Node : public Bst::Node
{
int height;
Node* parent;
};
// now I want that Bst::insert use this Node
// instead of the old one
Node* insert(Node* node)
{
Node* inserted_node = Bst::insert(node);
/* rotations stuff */
return inserted_node;
}
};
我正在努力做的是Bst::Node "virtual"
。
那么,如何在不重写整个插入函数的情况下解决实现Avl Tree的问题,因为Node已经改变了?
答案 0 :(得分:0)
也许你想要CRTP(在这种情况下,即使是一个粗略的例子,你也没有给出足够的关于你需求的信息,但是一个更简单,功能更少的模板方法可能对你更有意义。有一个基类(在每个您的树类型没有数据成员,只是为公共代码定义静态模板函数。由于函数是静态的,您需要传入相关数据(对于应该是&root
的插入)但是不应该太麻烦。(粗糙和未经测试):
struct tree_base
{
template <class Node>
static Node* insert( Node** where, Node* what)
{
Node* here;
while ( (here = *where) != 0 )
{
if ( *what < *here ) where = &(here->left);
else if ( *here < *what ) where = &(here->right);
else
{
Trying to insert something already there, what should be done
}
}
*where = what;
return what; // Is that the desired return?
}
};
然后,每个真正的树类将继承自tree_base
,并会调用tree_base::insert(&root, new_node)
来执行insert
CRTP版本允许root成为基类的成员,即使它指向派生类的Node类型。将root作为基类的成员,insert函数不需要static
,也不需要&root
作为输入。由于CRTP基类已经被正确模板化以访问Node
类型,因此基类插入方法不需要是模板。所有这些都需要学习更多东西(通过查看CRTP的一些真实示例),并且可能对您想要的代码共享过度杀伤。
答案 1 :(得分:0)
实际上我也在研究这个东西,我认为你很清楚地描述了你想要什么。
首先,可能对给定的接口有点困惑,insert() 不应该返回节点的指针,不是吗。我们可以使用 findNode() 函数,该函数返回节点的指针,并且正好完成这项工作。
回到主要问题,也许您可以使用模板为 BST 中的每个函数设置节点类型。 但是BST不仅仅是一个抽象的接口,它也实现了BST的操作,所以它不是CRTP..
现在的伪代码可能如下: // 预定义:
//parent ptr also alleviate the implementation of BST.
template<typename T>
class BST{
... omit..
protected:
template<typename node_type>
class BST_Node{
public:
T val;
BST_Node *left, *right, *parent;
BST_Node():left{nullptr},
right{nullptr},
parent{nullptr}, val{}{};
// empty {} default to value initialization.
}
... omit ...
}
template<typename T>
class AVL_Node : public BST_Node{
public:
short height;
AVL_Node(T val):BST_Node(val), height(0){};
}
template<typename T>
void insert(T val){
AVL_Node<T> Node(val);
BST<T>::insert_node<AVL_Node>(Node);
AVL_Node<T>* ptr = BST<T>::find_node<AVL_Node>(val);
ptr->height = BST<T>::get_height(ptr);
state = chk_balance(ptr);
switch(state){
case 0: // tree very balance..
break;
case 1:
LL_rotate(ptr);
break;
case 2:
RR_rotate(ptr);
break;
... omit
}
}
@帮助这篇文章解决你的问题..