我在C ++中为二进制搜索树创建了一个类(名为BST),现在尝试为继承BST类的AVL树创建一个类(名为AVL)。我已经在我的BST类中定义了一个结构(命名节点),现在想添加一个额外的成员' height'在派生的AVL类中使用它时。我无法找到一种方法如何重新定义结构并仅在将其用于AVL类时添加额外的成员。 这是我的BST课程代码:
class BST
{
protected:
struct node
{
int val;
node* left;
node* right;
};
node* root;
public:
BST()
{
this->root = NULL;
}
void insert(int val);
void display();
void displayPretty();
void displaySorted();
int min();
int max();
int height();
void remove(int val);
int after(int val);
int before(int val);
static bool isBST(BST tree);
~BST()
{
removeAll(this->root);
}
protected:
node* create(int val);
node* insertInto(node* root,int val);
void displayLevelOrder(queue<node*>* q);
void displayPretty(node* p, int indent);
void displayInorder(node* root);
node* getMin(node* root);
node* getMax(node* root);
int heightOf(node* root);
node* removeFrom(node* root,int val);
void removeAll(node* root);
node* getSuccessorOf(int val,node* root,node* prev);
node* getPredecessorOf(int val,node* root,node* next);
static bool isBST(node* root,int min,int max);
};
我对AVL类的不完整代码是:
class AVL : public BST
{
protected:
struct node
{
// redefine node here (by adding the 'height' member)
// such that all the node variables/pointers in BST (e.g. root)
// also get created with this new definition
};
public:
AVL() : BST(){}
void insert(int val);
void remove(int val);
private:
node* insertInto(node* root,int val);
node* removeFrom(node* root,int val)
};
我尝试过使用像这样的结构继承:
struct avlnode : node
{
int height;
};
但问题是avlnode->left
和avlnode->right
是node*
类型而不是avlnode*
类型,因此我无法从中访问高度成员。
任何帮助将不胜感激:D
答案 0 :(得分:1)
在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);
}
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 ++纯粹主义者实际上不喜欢的东西。
insert()
的{{1}}不使用class BTree2
的任何插入内容。这是确保树中的每个节点实际上都是class BTree
。
由于虚拟BTree2::Node
方法,BTree::print()
不需要重载。
此设计仅显示了一些重用代码的方法。
模板只是一个不同的机会。标准库(例如std::set<>)提供了一个示例。
答案 1 :(得分:0)
如果使用结构继承,Derived类将原样继承 struct node 并获得节点 *而不是 avlnode *
现在,您可能希望在派生类中重新定义struct node ,这将隐藏Parent中的节点并更喜欢'node'在Derived类中,但您在Parent类中使用的任何函数都将使用Parent类中'node'的定义。
也许您可以在父类的 node 中声明高度变量,并仅在派生类中使用它,或者在Derived类中声明vector<int> heights
并在那里存储高度。< / p>
此外,在类外部声明 struct node 并使用它的实例作为类的成员。