作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在研究一些包含实现伪代码的注释上的通用二进制搜索树(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
}
在这一点上,我有点困惑,我知道上面只是一个伪代码,但我想知道是否有一种方法可以重用已经为
insert
提供的
Node
操作。使用模板特化只是意味着为
insert<AVLNode>
编写一个不同的特化
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
和childs的指针(即它们必须是
Node
中的
Node
和
AVLNode
中的
AVLNode
的指针)。
最佳答案
您可以在此处使用CRTP。这将允许您在基类中创建左右节点和父节点。例如考虑这样的事情:
template<typename T>
struct BaseNode{
int key;
T* parent;
T* left;
T* right;
};
struct AVLNode : public BaseNode<AVLNode>{
int height;
int size;
AVLNode(const int&k, AVLNode*root){};
AVLNode(){};
};
struct Node : public BaseNode<Node>{
Node(const int&k, Node*root){};
Node(){};
};
template<typename T>
T* find(const int& k, T* root){return root;};
template<typename T>
void insert(const int& k, T* root){
T* N=find(k, root); //finds where to insert the node
if (N->key>k)
N->left=new T(k,N); //inserts as a left child
else
N->right=new T(k,N); //inserts as a right child
}
void test(){
AVLNode avl_root;
Node node_root;
insert(42, &avl_root);
insert(42, &node_root);
}
不利之处在于,编译器将生成更多不必要的代码。因为它为每种类型创建一个新的插入函数。对于您来说,这可能不是问题,但值得考虑。有关生成的代码,请参见
godbolt。
unique_ptr
或shared_ptr
的智能指针
关于c++ - 实现二进制搜索树时对类的怀疑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63815912/
所以基本上我所做的是向后构建一棵树。我从叶子开始,然后添加他们的 parent ,然后是他们的 parent (最后是一个 3 级树)。 我添加叶子没问题(我查询数据库,并为每个条目创建一个 TNod
我们正在使用 React 并且有类似的代码: const isDescendant = (predicateFn, child) => { let node = child.parentNode;
我是一名优秀的程序员,十分优秀!