我正在尝试为树及其节点构建多级继承。所以我从一个BaseNode开始,然后我创建一个从BaseNode继承的BSTNode,然后我创建一个从BSTNode继承的AVLNode。这些类中的每一个都有需要重载的成员函数,但它们需要返回各自的类。因此,如果我调用 AVLNode-> 来 insert(1) 那么这应该返回一个 AVLNode 类型的指针,而 BSTNode->insert(1) 应该返回一个 BSTNode 类型的指针。而且,这些节点中的每一个都可以存储多种类型作为键,例如,我们可以有一个键为 int 类型的 BSTNode,还有另一个键为 long 类型的 BSTNode。这些节点将成为代表各自树的另一组类的一部分。
class BaseNode {
T key;
BaseNode<T>* insert();
}
class BSTNode: public BaseNode {
BSTNode<T>* insert(); // extending the BaseNode insert
}
class AVLNode: public BSTNode {
AVLNode<T>* insert(); // extending the BSTNode insert
}
class BST {
BSTNode<T>* root;
}
class AVL {
AVLNode<T> *root;
}
我曾尝试查看 CRTP,但它仅适用于 1 级继承。我需要一些关于如何解决这个问题或是否可以使用 C++ 解决的指针(双关语)。
这是我的代码:
template<typename T>
class AbstractBinaryTreeNode {
protected:
T key;
int counter;
AbstractBinaryTreeNode<T> *left, *right, *parent;
public:
virtual void inorder_print();
virtual void pre_order_print();
virtual void post_order_print();
virtual void print_key();
virtual T get_key();
virtual void set_key(T key);
virtual AbstractBinaryTreeNode<T>* get_parent();
virtual AbstractBinaryTreeNode<T>* get_left();
virtual AbstractBinaryTreeNode<T>* get_right();
virtual void set_parent(AbstractBinaryTreeNode<T>* node);
virtual void set_left(AbstractBinaryTreeNode<T>* node);
virtual void set_right(AbstractBinaryTreeNode<T>* node);
virtual bool check_ri();
virtual AbstractBinaryTreeNode* search(T key);
virtual AbstractBinaryTreeNode* insert(T key);
virtual AbstractBinaryTreeNode* remove();
virtual ~AbstractBinaryTreeNode() {};
};
template<typename T>
class BinaryTreeNode: public AbstractBinaryTreeNode<T> {
public:
void inorder_print() ;
void pre_order_print() ;
void post_order_print() ;
void print_key() ;
T get_key() ;
void set_key(T key) ;
BinaryTreeNode<T>* get_parent() ;
BinaryTreeNode<T>* get_left() ;
BinaryTreeNode<T>* get_right() ;
void set_parent(BinaryTreeNode<T>* node);
void set_left(BinaryTreeNode<T>* node);
void set_right(BinaryTreeNode<T>* node);
};
class BSTNode: public BinaryTreeNode<T> {
public:
BSTNode(T key);
bool check_ri() ;
BSTNode<T>* insert(T key);
BSTNode<T>* search(T key);
BSTNode<T>* remove();
BSTNode<T>* next_larger();
BSTNode<T>* find_min();
};
我得到的错误是:
error: invalid conversion from ‘BinaryTreeNode<int>*’ to ‘BSTNode<int>*’
编辑:经过思考,我研究了接口实现分离,但现在重载不起作用。
binary_tree_node.hpp
#pragma once
#include"Impl/binary_tree_node_impl.hpp"
template<typename T>
class BinaryTreeNode{
public:
BinaryTreeNodeImpl<T, BinaryTreeNode<T>>* impl;
BinaryTreeNode();
BinaryTreeNode(T key);
virtual void inorder_print();
virtual void pre_order_print();
virtual void post_order_print();
void print_key() ;
virtual T get_key() ;
void set_key(T key);
BinaryTreeNode<T>* get_parent();
BinaryTreeNode<T>* get_left();
BinaryTreeNode<T>* get_right();
virtual void set_parent(void* node);
virtual void set_left(void* node);
virtual void set_right(void* node);
virtual bool check_ri() = 0;
};
#include"binary_tree_node.tpp"
binary_tree_node.tpp
模板
BinaryTreeNode<T>::BinaryTreeNode() {
this->impl = new BinaryTreeNodeImpl<T, BinaryTreeNode<T>>();
}
template<typename T>
BinaryTreeNode<T>::BinaryTreeNode(T key) {
this->impl = new BinaryTreeNodeImpl<T, BinaryTreeNode<T>>(this);
}
template<typename T>
BinaryTreeNode<T>* BinaryTreeNode<T>::get_parent() {
return this->impl->get_parent();
}
template<typename T>
BinaryTreeNode<T>* BinaryTreeNode<T>::get_left() {
return this->impl->get_left();
}
template<typename T>
BinaryTreeNode<T>* BinaryTreeNode<T>::get_right() {
return this->impl->get_right();
}
template<typename T>
void BinaryTreeNode<T>::set_parent(void* node) {
this->impl->set_parent((BinaryTreeNode<T>*) node);
}
template<typename T>
void BinaryTreeNode<T>::set_left(void* node) {
this->impl->set_left((BinaryTreeNode<T>*)node);
}
template<typename T>
void BinaryTreeNode<T>::set_right(void* node) {
this->impl->set_right((BinaryTreeNode<T>*)node);
}
template<typename T>
void BinaryTreeNode<T>::print_key() {
this->impl->print_key();
}
template<typename T>
void BinaryTreeNode<T>::pre_order_print() {
this->impl->pre_order_print();
}
template<typename T>
void BinaryTreeNode<T>::inorder_print() {
this->impl->inorder_print();
}
template<typename T>
void BinaryTreeNode<T>::post_order_print() {
this->impl->post_order_print();
}
template<typename T>
T BinaryTreeNode<T>::get_key() {
return this->impl->get_key();
}
template<typename T>
void BinaryTreeNode<T>::set_key(T key) {
this->impl->set_key(key);
}
binary_tree_impl.hpp
#pragma once
template<typename T, class NodeType>
class BinaryTreeImpl {
public:
NodeType *root;
BinaryTreeImpl() {};
BinaryTreeImpl(T key) {};
virtual void inorder_print();
virtual void pre_order_print();
virtual void post_order_print();
virtual bool check_ri() = 0;
virtual NodeType* insert(T key) = 0;
virtual NodeType* remove(T key) = 0;
virtual NodeType* search(T key) = 0;
};
#include"binary_tree_impl.tpp"
binary_tree_impl.tpp
template<typename T, class NodeType>
void BinaryTreeImpl<T, NodeType>::inorder_print() {
if(this->root)
this->root->inorder_print();
}
template<typename T, class NodeType>
void BinaryTreeImpl<T, NodeType>::pre_order_print() {
if (this->root)
this->root->pre_order_print();
}
template<typename T, class NodeType>
void BinaryTreeImpl<T, NodeType>::post_order_print() {
if(this->root)
this->root->post_order_print();
}
binary_tree_node_impl.hpp
# pragma once
template<typename T, class NodeType>
class BinaryTreeNodeImpl {
public:
T key;
int counter;
NodeType *node;
NodeType *left, *right, *parent;
BinaryTreeNodeImpl() {};
BinaryTreeNodeImpl(T key, NodeType* node);
virtual bool check_ri() {};
virtual void inorder_print();
virtual void pre_order_print();
virtual void post_order_print();
T get_key();
void set_key(T key);
void print_key();
virtual NodeType* get_parent();
virtual NodeType* get_left();
virtual NodeType* get_right();
virtual void set_parent(void* node);
virtual void set_left(void* node);
virtual void set_right(void* node);
};
#include "binary_tree_node_impl.tpp"
binary_tree_node_impl.tpp
模板<
typename T, class NodeType>
BinaryTreeNodeImpl<T, NodeType>::BinaryTreeNodeImpl(T key, NodeType* node) {
this->key = key;
this->node = node;
}
template<typename T, class NodeType>
NodeType* BinaryTreeNodeImpl<T, NodeType>::get_parent() {
return this->parent;
}
template<typename T, class NodeType>
NodeType* BinaryTreeNodeImpl<T, NodeType>::get_left() {
return this->left;
}
template<typename T, class NodeType>
NodeType* BinaryTreeNodeImpl<T, NodeType>::get_right() {
return this->right;
}
template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::set_parent(void* node) {
this->parent = (NodeType*)node;
}
template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::set_left(void* node) {
this->left = (NodeType*)node;
}
template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::set_right(void* node) {
this->right = (NodeType*)node;
}
template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::print_key() {
std::cout<<this->key<<std::endl;
}
template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::pre_order_print() {
for(int i = 0; i < this->counter; i++)
std::cout<<this->key<<" ";
if (this->left)
this->left->pre_order_print();
if(this->right)
this->right->pre_order_print();
}
template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::inorder_print() {
if (this->left)
this->left->inorder_print();
for(int i = 0; i < this->counter; i++)
std::cout<<this->key<<" ";
if(this->right)
this->right->inorder_print();
}
template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::post_order_print() {
if (this->left)
this->left->pre_order_print();
if(this->right)
this->right->pre_order_print();
for(int i = 0; i < this->counter; i++)
std::cout<<this->key<<" ";
}
template<typename T, class NodeType>
T BinaryTreeNodeImpl<T, NodeType>::get_key() {
return this->key;
}
template<typename T, class NodeType>
void BinaryTreeNodeImpl<T, NodeType>::set_key(T key) {
this->key = key;
}
binary_tree.hpp
#pragma once
#include"binary_tree_node.hpp"
#include"Impl/binary_tree_impl.hpp"
template<typename T>
class BinaryTree {
public:
BinaryTreeImpl<T, BSTNode<T>> *impl;
BinaryTree() {};
BinaryTree(T key);
virtual void inorder_print();
virtual void pre_order_print();
virtual void post_order_print();
virtual bool check_ri() = 0;
virtual BinaryTreeNode<T>* insert(T key) = 0;
virtual BinaryTreeNode<T>* remove(T key) = 0;
virtual BinaryTreeNode<T>* search(T key) = 0;
};
#include"binary_tree.tpp"
binary_tree.tpp
template<typename T>
void BinaryTree<T>::inorder_print() {
this->impl->inorder_print();
}
template<typename T>
void BinaryTree<T>::pre_order_print() {
this->impl->pre_order_print();
}
template<typename T>
void BinaryTree<T>::post_order_print() {
this->impl->post_order_print();
}
bst_impl.hpp
#pragma once
#include"../../binary_tree/Impl/binary_tree_impl.hpp"
template<typename T, class NodeType>
class BSTImpl: public BinaryTreeImpl<T, NodeType> {
private:
NodeType *root;
public:
BSTImpl() {};
BSTImpl(T key);
bool check_ri();
NodeType* insert(T key) override;
NodeType* search(T key) override;
NodeType* remove(T key) override;
~BSTImpl();
};
#include"bst_impl.tpp"
bst_impl.tpp
template<typename T, class NodeType>
BSTImpl<T, NodeType>::BSTImpl(T key) {
if (this->root == nullptr)
this->root = new NodeType(key);
else
this->root->insert(key);
}
template<typename T, class NodeType>
NodeType* BSTImpl<T, NodeType>::insert(T key) {
if (this->root == nullptr)
this->root = new NodeType(key);
else
this->root->insert(key);
}
template<typename T, class NodeType>
bool BSTImpl<T, NodeType>::check_ri() {
if (this->root) {
return this->root->check_ri();
} else {
return true;
}
}
template<typename T, class NodeType>
NodeType* BSTImpl<T, NodeType>::search(T key) {
if (this->root)
return this->root->search(key);
else
return nullptr;
}
template<typename T, class NodeType>
NodeType* BSTImpl<T, NodeType>::remove(T key) {
if(this->root){
NodeType *temp = this->root->search(key);
if (temp == nullptr)
return nullptr;
else if (temp == this->root) {
NodeType *node = new NodeType(0);
node->set_left(this->root);
this->root->set_parent(node);
NodeType* deleted = this->root->remove();
this->root = node->get_left();
if(this->root)
this->root->set_parent(nullptr);
return deleted;
} else {
NodeType *deleted = temp->remove();
this->check_ri();
return deleted;
}
}
}
bst_node_impl.hpp
#pragma once
#include"../../binary_tree/Impl/binary_tree_node_impl.hpp"
template<typename T, class NodeType>
class BSTNodeImpl: public BinaryTreeNodeImpl<T, NodeType> {
public:
T key;
int counter;
NodeType *node;
NodeType *left, *right, *parent;
BSTNodeImpl(T key, NodeType* node);
bool check_ri();
T get_key();
NodeType* insert(T key);
NodeType* search(T key);
NodeType* remove();
NodeType* next_larger();
NodeType* find_min();
};
#include"bst_node_impl.tpp"
bst_node_impl.tpp
template<typename T, class NodeType>
BSTNodeImpl<T, NodeType>::BSTNodeImpl(T key, NodeType* node) {
this->right = nullptr;
this->left = nullptr;
this->parent = nullptr;
this->key = key;
this->counter = 1;
this->node = node;
}
template<typename T, class NodeType>
NodeType* BSTNodeImpl<T, NodeType>::find_min() {
return this->left ? this->left->find_min(): this->node;
}
template<typename T, class NodeType>
NodeType* BSTNodeImpl<T, NodeType>::next_larger() {
if (this->right)
return this->right->find_min();
else {
NodeType *temp = this->node;
while(temp->get_parent() && temp == temp->get_parent()->get_right()) {
temp = temp->get_parent();
}
return temp->get_parent();
}
}
template<typename T, class NodeType>
NodeType* BSTNodeImpl<T, NodeType>::remove() {
if (this->left == nullptr || this->right == nullptr) {
if(this->node == this->parent->get_left()) {
this->parent->set_left(this->left ? this->left : this->right);
if (this->parent->get_left()) {
this->parent->get_left()->set_parent(this->parent);
}
} else {
this->parent->set_right(this->left ? this->left : this->right);
if (this->parent->get_right()) {
this->parent->get_right()->set_parent(this->parent);
}
}
return this->node;
} else {
NodeType *temp = this->next_larger();
T temp_key = temp->get_key();
temp->set_key(this->key);
this->key = temp_key;
return temp->remove();
}
}
template<typename T, class NodeType>
NodeType* BSTNodeImpl<T, NodeType>::search(T key) {
if (this->key == key)
return this->node;
else if (this->key > key)
return this->left ? this->left->search(key) : nullptr;
else if (this->key < key)
return this->right ? this->right->search(key) : nullptr;
}
template<typename T, class NodeType>
NodeType* BSTNodeImpl<T, NodeType>::insert(T key) {
if (this->key == key) {
this->counter++;
return this->node;
}
else if (this->key > key) {
if (this->left == nullptr) {
this->left = new NodeType(key);
this->left = this->node;
return this->node;
} else {
this->left->insert(key);
}
} else {
if (this->right == nullptr) {
this->right = new NodeType(key);
this->right = this->node;
return this->node;
} else {
this->right->insert(key);
}
}
}
template<typename T, class NodeType>
bool BSTNodeImpl<T, NodeType>::check_ri() {
if (this->left == nullptr && this->right == nullptr)
return true;
if (this->left && this->left->get_key() > this->key)
return false;
if (this->right && this->right->get_key() < this->key)
return false;
if (this->left && this->right)
return this->left->check_ri() && this->right->check_ri();
else if (this->left)
return this->left->check_ri();
else
return this->right->check_ri();
}
template<typename T, class NodeType>
T BSTNodeImpl<T, NodeType>::get_key() {
return this->key;
}
bst_node.hpp
#pragma once
#include"Impl/bst_node_impl.hpp"
#include"../binary_tree/binary_tree_node.hpp"
template<typename T>
class BSTNode: public BinaryTreeNode<T> {
public:
BSTNodeImpl<T, BSTNode<T>>* impl;
BSTNode();
BSTNode(T key);
bool check_ri() override;
T get_key() override;
void inorder_print();
void pre_order_print();
void post_order_print();
BSTNode<T>* get_left();
BSTNode<T>* get_right();
BSTNode<T>* get_parent();
BSTNode<T>* insert(T key);
BSTNode<T>* search(T key);
BSTNode<T>* remove();
BSTNode<T>* next_larger();
BSTNode<T>* find_min();
void set_parent(void* node) override;
void set_left(void* node) override;
void set_right(void* node) override;
};
#include "bst_node.tpp"
bst_node.tpp
template<typename T>
BSTNode<T>::BSTNode(T key) {
this->impl = new BSTNodeImpl<T, BSTNode<T>>(key, this);
this->impl->get_key();
}
template<typename T>
BSTNode<T>* BSTNode<T>::find_min() {
return (BSTNode<T>*)this->impl->find_min();
}
template<typename T>
BSTNode<T>* BSTNode<T>::next_larger() {
return (BSTNode<T>*)this->impl->next_larger();
}
template<typename T>
BSTNode<T>* BSTNode<T>::remove() {
return (BSTNode<T>*)this->impl->remove();
}
template<typename T>
BSTNode<T>* BSTNode<T>::search(T key) {
return (BSTNode<T>*)this->impl->search(key);
}
template<typename T>
BSTNode<T>* BSTNode<T>::insert(T key) {
return (BSTNode<T>*)this->impl->insert(key);
}
template<typename T>
bool BSTNode<T>::check_ri() {
return this->impl->check_ri();
}
template<typename T>
void BSTNode<T>::set_left(void* node) {
this->impl->set_left((BSTNode<T>*) node);
}
template<typename T>
void BSTNode<T>::set_parent(void* node) {
this->impl->set_parent((BSTNode<T>*) node);
}
template<typename T>
void BSTNode<T>::set_right(void* node) {
this->impl->set_right((BSTNode<T>*) node);
}
template<typename T>
BSTNode<T>* BSTNode<T>::get_right() {
return (BSTNode<T>*)this->impl->get_right();
}
template<typename T>
BSTNode<T>* BSTNode<T>::get_left() {
return (BSTNode<T>*)this->impl->get_left();
}
template<typename T>
BSTNode<T>* BSTNode<T>::get_parent() {
return (BSTNode<T>*)this->impl->get_parent();
}
template<typename T>
T BSTNode<T>::get_key() {
return this->impl->get_key();
}
template<typename T>
void BSTNode<T>::pre_order_print() {
this->impl->pre_order_print();
}
template<typename T>
void BSTNode<T>::inorder_print() {
this->impl->inorder_print();
}
template<typename T>
void BSTNode<T>::post_order_print() {
this->impl->post_order_print();
}
bst.hpp
#pragma once
#include"../binary_tree/binary_tree.hpp"
#include"Impl/bst_impl.hpp"
#include"bst_node.hpp"
template<typename T>
class BST: public BinaryTree<T> {
public:
BSTImpl<T, BSTNode<T>> *impl;
BST();
BST(T key);
bool check_ri();
BSTNode<T>* insert(T key) override;
BSTNode<T>* search(T key) override;
BSTNode<T>* remove(T key) override;
};
#include "bst.tpp"
bst.tpp
template<typename T>
BST<T>::BST(){
this->impl = new BSTImpl<T, BSTNode<T>>();
}
template<typename T>
BST<T>::BST(T key){
this->impl = new BSTImpl<T, BSTNode<T>>(key);
}
template<typename T>
BSTNode<T>* BST<T>::insert(T key) {
return this->impl->insert(key);
}
template<typename T>
bool BST<T>::check_ri() {
return this->impl->check_ri();
}
template<typename T>
BSTNode<T>* BST<T>::search(T key) {
return this->impl->search(key);
}
template<typename T>
BSTNode<T>* BST<T>::remove(T key) {
return this->impl->remove(key);
}
main.cpp
#include<bits/stdc++.h>
#include"bst_node.hpp"
#include"bst.hpp"
#include"../utils.hpp"
int main () {
std::vector<int> array = get_random_array<int>(10, 100);
BST<int> *bst = new BST<int>();
for(auto item: array) {
bst->insert(item);
bst->inorder_print();
bst->check_ri();
}
}
运行时出现段错误。