继承和 AVL/BST 树

Inheritance and AVL/BST Trees

有什么方法可以对Bst和Avl树使用相同的插入函数吗?问题是 Bst 和 Avl 有不同的 Node 类型,但我不想让 Bst Node 成为一般情况(里面有 height 和 Node* parent,这是没有意义的,因为不需要 parent 和 height inside a 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".

那么,如何解决仅仅因为Node变了就实现Avl Tree而不重写整个insert函数的问题呢?

也许您需要 CRTP(在这种情况下,您没有提供足够的信息来说明您的需求,即使是一个粗略的例子,但更简单、功能更弱的模板方法可能对您更有意义。有一个基础 class (在你的每个树类型下)没有数据成员,只是为公共代码定义静态模板函数。由于函数是静态的,你需要传入相关数据(插入应该是 &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?
   }
};

然后你的每个真正的树 classes 将继承自 tree_base 并调用 tree_base::insert(&root, new_node) 来完成 insert

的公共部分

它的 CRTP 版本将允许 root 成为基础 class 的成员,即使它指向派生 class 的节点类型。给定 root 作为基础 class 的成员,插入函数不需要 static 也不需要将 &root 作为输入。由于 CRTP 基础 class 已经正确地模板化以访问 Node 类型,基础 class 插入方法不需要是模板。所有这些都需要学习更多的东西(通过查看 CRTP 的一些真实示例),并且对于您想要的代码共享来说可能有点矫枉过正。

其实我也在做这方面的工作,我觉得你很清楚地描述了你想要什么。

起初,可能对给定的接口有点困惑,insert() 不应该 return 节点的指针,不是吗。我们可以使用 findNode() 函数,它 return Node 的指针并且只做这个工作。

回到主要问题,也许你可以使用模板为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
     }
}

@帮助post解决你的问题..