继承和AVL / BST树

时间:2015-11-25 14:49:14

标签: c++ inheritance binary-search-tree avl-tree

有没有办法对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已经改变了?

2 个答案:

答案 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
     }
}

@帮助这篇文章解决你的问题..