在 OP 中,派生类被命名为 AVLTree。不幸的是,OP 不是 MCVE。 “令人兴奋的”实现细节被忽略(甚至尚未开发)。在回忆了 AVL Tree 的工作原理后,我决定忽略它。因此,我想简单地展示类的派生是如何工作的:
注意:我拆分示例代码以防止嵌套滚动框。
来源trees.cc:
首先我要使用的标准库的一些头文件:
#include <iostream>
#include <iomanip>
#include <string>
基类BTree的声明:
class BTree {
从节点的嵌入类开始:
// types:
protected:
struct Node {
int value;
Node *pLeft, *pRight;
// constructor.
Node(int value): value(value), pLeft(nullptr), pRight(nullptr) { }
// destructor.
virtual ~Node() { delete pLeft; delete pRight; }
// disabled:
Node(const Node&) = delete;
Node& operator=(const Node&) = delete;
// prints node.
virtual void print(std::ostream &out)
{
out << "Node " << value;
}
};
...变量...
// variables:
protected:
Node *_pRoot;
...和方法。
// methods:
public:
// constructor.
BTree(): _pRoot(nullptr) { }
// destructor.
~BTree() { delete _pRoot; }
// disabled:
BTree(const BTree&) = delete;
BTree& operator=(const BTree&) = delete;
// inserts a node.
bool insert(int value) { return insert(_pRoot, value); }
// prints the tree.
void print(std::ostream &out, bool inOrder)
{
if (_pRoot) {
if (inOrder) printInfix(out, _pRoot, 0);
else print(out, _pRoot, 0);
} else out << "EMPTY." << std::endl;
}
// internal methods:
protected:
// creates and inserts a node.
bool insert(Node *&pNode, int value);
// prints a sub-tree.
void print(std::ostream &out, Node *pNode, int indent);
// prints a sub-tree in order.
void printInfix(std::ostream &out, Node *pNode, int indent);
};
内部方法的实现:
bool BTree::insert(Node *&pNode, int value)
{
if (!pNode) {
pNode = new Node(value);
return true;
}
if (value == pNode->value) return false; // ERROR!
return insert(
value < pNode->value ? pNode->pLeft : pNode->pRight, value);
}
void BTree::print(std::ostream &out, Node *pNode, int indent)
{
out << std::setw(indent) << "";
pNode->print(out);
out << std::endl;
indent += 2;
if (pNode->pLeft) print(out, pNode->pLeft, indent);
if (pNode->pRight) print(out, pNode->pRight, indent);
}
void BTree::printInfix(std::ostream &out, Node *pNode, int indent)
{
if (pNode->pLeft) printInfix(out, pNode->pLeft, indent + 2);
out << std::setw(indent) << "";
pNode->print(out);
out << std::endl;
if (pNode->pRight) printInfix(out, pNode->pRight, indent + 2);
}
第二个nd树的派生类:
class BTree2: public BTree {
从派生节点的嵌入类开始:
// types:
protected:
struct Node: public BTree::Node {
int height;
// constructor.
Node(int value, int height):
BTree::Node(value), height(height)
{ }
virtual ~Node() = default;
// disabled:
Node(const Node&) = delete;
Node& operator=(const Node&) = delete;
// prints node.
virtual void print(std::ostream &out)
{
out << "Node " << value << " (height: " << height << ")";
}
};
...没有变量,但有一些派生方法...
// methods:
public:
// constructor.
BTree2(): BTree() { }
// destructor.
~BTree2() = default;
// disabled:
BTree2(const BTree2&) = delete;
BTree2& operator=(const BTree2&) = delete;
// inserts a node.
bool insert(int value)
{
return insert((Node*&)_pRoot, value, 0);
}
// internal methods:
protected:
// creates and inserts a node.
bool insert(Node *&pNode, int value, int height);
};
...和实现:
bool BTree2::insert(Node *&pNode, int value, int height)
{
if (!pNode) {
pNode = new Node(value, height);
return true;
}
if (value == pNode->value) return false; // ERROR!
return insert(
(Node*&)(value < pNode->value ? pNode->pLeft : pNode->pRight),
value, pNode->height + 1);
}
最后但并非最不重要的一个小测试的主要功能:
// main function
int main()
{
// some test data
int data[] = { 3, 7, 21, 2, 12, 1, 104, 13 };
enum { nData = sizeof data / sizeof data[0] };
// binary tree
{ std::cout << "Binary Tree:" << std::endl;
BTree bTree;
std::cout << "Build..." << std::endl;
for (int value : data) bTree.insert(value);
std::cout << "Print Hierarchy..." << std::endl;
bTree.print(std::cout, false);
std::cout << "Print Sorted..." << std::endl;
bTree.print(std::cout, true);
std::cout << "Destroy..." << std::endl;
std::cout << std::endl;
}
// derived binary tree
{ std::cout << "Derived Binary Tree:" << std::endl;
BTree2 bTree;
std::cout << "Build..." << std::endl;
for (int value : data) bTree.insert(value);
std::cout << "Print Hierarchy..." << std::endl;
bTree.print(std::cout, false);
std::cout << "Print Sorted..." << std::endl;
bTree.print(std::cout, true);
std::cout << "Destroy..." << std::endl;
std::cout << std::endl;
}
// done
return 0;
}
我将示例上传到 ideone.com。
我在 Windows 10 的 cygwin 中使用 gcc 编译并测试了它:
$ g++ -std=c++11 -o trees trees.cc
$ ./trees.exe
Binary Tree:
Build...
Print Hierarchy...
Node 3
Node 2
Node 1
Node 7
Node 21
Node 12
Node 13
Node 104
Print Sorted...
Node 1
Node 2
Node 3
Node 7
Node 12
Node 13
Node 21
Node 104
Destroy...
Derived Binary Tree:
Build...
Print Hierarchy...
Node 3 (height: 0)
Node 2 (height: 1)
Node 1 (height: 2)
Node 7 (height: 1)
Node 21 (height: 2)
Node 12 (height: 3)
Node 13 (height: 4)
Node 104 (height: 3)
Print Sorted...
Node 1 (height: 2)
Node 2 (height: 1)
Node 3 (height: 0)
Node 7 (height: 1)
Node 12 (height: 3)
Node 13 (height: 4)
Node 21 (height: 2)
Node 104 (height: 3)
Destroy...
$
注意事项:
在struct Node 中引入虚拟方法可以使用dynamic_cast<>()。 AFAIK,dynamic_cast<>() 只能应用于指针类型。因此,我只是做了一个 C-cast(即(Node*&)),这是 C++ 纯粹主义者实际上不喜欢的。
class BTree2 的insert() 不使用class BTree 的任何插入内容。这是确保树中的每个节点实际上都是BTree2::Node 所必需的。
BTree::print() 不需要因为虚拟的Node::print() 方法而被重载。
这个设计只是展示了一些重用代码的方法。
模板只是一个不同的机会。标准库(例如std::set<>)提供了一个示例。