【发布时间】:2020-09-09 16:35:25
【问题描述】:
我正在研究一些包含实现伪代码的笔记上的通用二叉搜索树 (BST) 和 AVL 树 (AVL)。我对它们的一些实现细节有些疑惑。
BST 基于下面的struct Node
struct Node{
int key;
Node* parent;
Node* left;
Node* right;
//constructors
}
//methods
AVL 版本基本相同,增加了几个字段用于平衡树(为了清楚起见,我将其称为 AVLNode,但注释上没有这种区别):
struct AVLNode{
int key;
int height;
int size;
AVLNode* parent;
AVLNode* leftchild;
AVLNode* rightchild;
//constructors
}
//methods
两棵树之间的很多操作是相同的,我可以轻松地使用模板以便在两棵树上重用它们。但是,请考虑插入新节点的操作insert。 BST 的代码类似于
//Insert node with key k in tree with root R
void insert(const int& k, Node* root){
Node* N=find(k, root); //finds where to insert the node
if (N->key>k)
N->leftchild=new Node(k,N); //inserts as a left child
else
N->rightchild=new Node(k,N); //inserts as a right child
}
现在,重点是AVL树的insert操作基本相同。笔记中呈现的伪代码如下:
void avlInsert(int k, AVLNode* R){
insert(k,R); //same operations as for Nodes, shown above
AVLNode* N=find(x,R); //find node inserted (generic operation for BST)
rebalance(N); //perform balancing operations specific to AVL trees
}
此时我有点困惑,我知道上面只是一个伪代码,但我想知道是否有办法重用已经为Node 提供的操作insert。使用模板特化只是意味着为 AVLNode 写一个不同的特化 insert<AVLNode>,所以这不是我所指的。
我认为一种方法是将AVLNode 定义为Node 的子类,然后使用类似
struct AVLNode : Node {
//implementation
}
void avlInsert(int k, AVLNode* R){
Node *root=R;
insert(k,root);
AVLNode* N=find(x,R);
rebalance(N);
}
但我不太确定这会起作用,而且我不知道如何管理指向 parent 和孩子的指针(即它们必须是指向 Node 内 Node 和 AVLNode 的指针在AVLNode).
有没有办法避免重写相同的代码?
【问题讨论】:
-
你考虑过oop吗?看起来 AVL 节点是一个特殊的节点。您可以让 AVL 节点扩展无,然后尽可能使用通用节点
-
是的,请阅读最后一段。
-
重点是
Node中有3个指针Node*,必须是AVLNode中的AVLNode*。如果我只是在AVLNode中重新定义它们,那么子类将在AVLNode中拥有三个无用的Node*指针。 -
您能否显示您不想重复的
insert代码?我不清楚有多少重复。如果代码基本相同,或许可以使用模板。 -
不要为继承或简化而烦恼。你会付出比你得到的好处更多的努力。由于结构是独立的,请保持这种方式。
标签: c++ class templates binary-search-tree avl-tree