目录
二叉树是很多数据结构的基础
众所周知,二叉树中每个节点最多有两个儿子
对于二叉树,最重要的就是前中后序遍历,这也是本文写的最多的部分
整棵树分为两大部分实现,二叉树节点(node)和树本身
二叉树结点 binnode
这里我们后面前中后序遍历要用到栈和队列
我们先把它include进来
(53条消息) 手写vector,list,stack,queue代码_lxrrrrrrrr的博客-CSDN博客
当然改成stl的也可以
函数总览
#define lxrbinnodeposi(T) lxrbinnode<T>*
typedef enum{RED,BLACK} Color;
template <typename T>
class lxrbinnode{
protected:
template <typename VST>
void visitAlongLeftBranch(VST &visit,lxrstack<lxrbinnodeposi(T)> &S);
void goAlongLeftBranch( lxrstack<lxrbinnodeposi(T)> &S);
void goToHLVFL(lxrstack<lxrbinnodeposi(T)> &S);
public:
lxrbinnodeposi(T) parent;
lxrbinnodeposi(T) leftchild;
lxrbinnodeposi(T) rightchild;
Color color;
T data;
int height;
//constructor
lxrbinnode() : parent(nullptr),leftchild(nullptr),rightchild(nullptr),height(0),color(BLACK),npl(0) {};
lxrbinnode(T const &val,lxrbinnodeposi(T) p=nullptr,Color color=BLACK):parent(p),leftchild(nullptr),rightchild(nullptr),data(val),height(0),color(color),npl(0) {};
int size() const; //compute the size of subtree rooted at now node
lxrbinnodeposi(T) insertAsLc(T const &val); //assume that this.leftchild==nullptr
lxrbinnodeposi(T) insertAsRc(T const &val); //assume that this.rightchild=nullptr
lxrbinnodeposi(T) succ(); //return the direct succ of now node
//tree traversal
template <typename VST> void preOrder_Re(VST visit);//use recursion to preorder traversal
template <typename VST> void preOrder_It1(VST visit);//use iteration to preorder traversal
template <typename VST> void preOrder_It2(VST visit);//use iteration to preorder traversal
template <typename VST> void inOrder_Re(VST visit);//use recursion to middle traversal
template <typename VST> void inOrder_It1(VST visit);//use iteration to middle traversal
template <typename VST> void inOrder_It2(VST visit);//use iteration to middle traversal
template <typename VST> void postOrder_Re(VST visit);//use recursion to postorder traversal
template <typename VST> void postOrder_It(VST visit);//use iteration to postorder traversal
template <typename VST> void levelOrder(VST visit);//traversal with depth
};
对于每个节点,包含几个基础的变量
parent:父节点
leftchild:左孩子
rightchild:右孩子
color:颜色(主要是为了之后写红黑树时用,暂时不管他)
data:这个节点的value
height:高度
首先介绍几个基础函数
构造:
构造非常简单,我们只需要定义一个默认构造和带值构造即可
lxrbinnode() : parent(nullptr),leftchild(nullptr),rightchild(nullptr),height(0),color(BLACK) {};
lxrbinnode(T const &val,lxrbinnodeposi(T) p=nullptr,Color color=BLACK):parent(p),leftchild(nullptr),rightchild(nullptr),data(val),height(0),color(color) {};
size()
计算这个节点的子树+这个节点的size
也很好写,左右子树size+1即可
template <typename T>
int lxrbinnode<T>::size() const {
int leftSize=this->leftchild ? this->leftchild->size() : 0;
int rightSize=this->rightchild ? this->rightchild->size() :0;
return leftSize+rightSize+1;
}
insertAsLc()
在当前节点的左边插入一个新节点,值为val
只需让新节点的parent指向此节点
此节点的leftchild指向新节点即可
template <typename T>
lxrbinnodeposi(T) lxrbinnode<T>::insertAsLc(T const &val){
lxrbinnodeposi(T) currNode=new lxrbinnode<T>(val);
currNode->parent=this;
this->leftchild=currNode;
return currNode;
}
insertAsRc()
同理
template <typename T>
lxrbinnodeposi(T) lxrbinnode<T>::insertAsRc(T const &val){
lxrbinnodeposi(T) currNode=new lxrbinnode<T>(val);
currNode->parent=this;
this->rightchild=currNode;
return currNode;
}
succ()
返回当前节点的直接后继
在二叉树中,我们定义直接后继等于在该树中序遍历中,此节点的下一个节点
不懂中序遍历可以往后看,后面会仔细讲
实现过程,看一遍中序遍历流程图就可以看懂
如果该节点有右儿子,我们只需要走到他的右儿子,继续一直向左走就可以找到
如果没有右儿子,我们就要往上找,只要该节点是他父节点的右儿子就一直向上走
走到顶再走一步即使答案
代码如下:
template <typename T>
lxrbinnodeposi(T) lxrbinnode<T>::succ(){
lxrbinnodeposi(T) succ;
if(rightchild){
succ=rightchild;
while(succ->leftchild) succ=succ->leftchild;
}
else{
succ=this;
while(succ->parent&&succ==succ->parent->rightchild) succ=succ->parent;
succ=succ->parent;
}
return succ;
}
接下来讨论前中后序遍历的递归和迭代版本
前序遍历
所谓前序遍历,就是对于每一个三元组,总是根在前面,左儿子其次,右儿子在后
从根节点开始,不断向左子树访问,直到当前结点x不拥有左子树,这也相当于左子树已经访问完毕,此时转入当前结点x的右子树。右子树访问完毕后,即以x为根的子树已经访问完毕,此时应该转入x父亲的右子树,随后是x父亲的父亲的右子树,然后是x父亲的父亲的...整个访问过程可以如下面这张图所示:
递归版本比较好写,迭代版用栈即可
递归版本
如上所说
先遍历此节点,如果有左儿子优先走左儿子,否则走右儿子
template <typename T>
template <typename VST>
void lxrbinnode<T>::preOrder_Re(VST visit){
visit(this->data);
if(this->leftchild) this->leftchild->preOrder_Re(visit);
if(this->rightchild) this->rightchild->preOrder_Re(visit);
}
迭代版本
用一个栈辅助操作,思想同上
先遍历此节点,由于栈是先进后出,所以我们要优先把右儿子压进栈中,然后压左儿子,
这样我们可以保证左儿子先出栈,也就保证了前序性
代码如下
template <typename T>
template <typename VST>
void lxrbinnode<T>::preOrder_It1(VST visit){
lxrstack<lxrbinnodeposi(T)> S;
lxrbinnodeposi(T) curr=this;
S.push(curr);
while(!S.empty()){
curr=S.pop();
visit(curr->data);
if(curr->rightchild) S.push(curr->rightchild);
if(curr->leftchild) S.push(curr->leftchild);
}
}
中序遍历
定义大同小异
对于每一个三元组,总是左儿子在前,根其次,右儿子在后
同样是从根节点开始,不断地沿着左子树向下走。不同的是,这里向下行进的过程中不能访问当前结点,只有等到当前结点的左子树完成访问时,才能轮到当前结点,因此想到引入一个栈来实现延迟缓冲的功能。走到最左侧的第一个没有左子树的叶子结点时,没有左子树也相当于已经完成了左子树的访问,于是随后便访问当前结点x,然后转入到x的右子树。
当x的右子树完成访问时,即标志着以x为根的子树访问完毕,随机访问x的父亲结点,然后访问x的父亲的右子结点。x的右兄弟结点访问完毕时,即标志着以x的父亲的根的子树访问完毕,随机访问x父亲的父亲,然后是x父亲的父亲的父亲...整个访问过程如下图所示:
递归版本
递归版本好写的原因在于不用动脑子
将三行代码按顺序排列即可
template <typename T>
template <typename VST>
void lxrbinnode<T>::inOrder_Re(VST visit){
if(this->leftchild) this->leftchild->inOrder_Re(visit);
visit(this->data);
if(this->rightchild) this->rightchild->inOrder_Re(visit);
}
迭代版本
迭代版本要稍微麻烦一点
goAlongLeft函数的作用是对于每一个节点,一直向左走,这一条左链都压入栈
具体实现:对于每一个节点,先一直向左走,将他的所有左儿子都压入栈,之后每一个左儿子
按顺序出栈,遍历此节点,再遍历此节点的右节点,之后下一个左儿子出栈.....
代码如下
template <typename T>
void lxrbinnode<T>::goAlongLeftBranch(lxrstack<lxrbinnodeposi(T)> &S){
lxrbinnodeposi(T) curr=this;
while(curr){
S.push(curr);
curr=curr->leftchild;
}
}
template <typename T>
template <typename VST>
void lxrbinnode<T>::inOrder_It1(VST visit){
lxrstack<lxrbinnodeposi(T)> S;
lxrbinnodeposi(T) curr=this;
while(true){
curr->goAlongLeftBranch(S);
if(S.empty()) break;
curr=S.pop();
visit(curr->data);
curr=curr->rightchild;
}
}
后序遍历
定义:对于每一个三元组,总是左儿子在前,右儿子其次,最后为根
首要的还是分析后续遍历各个节点之间的先后次序,哪个结点首先被访问,每个结点的直接后继是谁?
从根节点出发,不断沿着左子树向下进行,直到当前结点不具有左子树。此时应该进入右子树,然后重复上面的过程。这样,第一个被访问的结点,应该是最高左侧可见结点,即从左边向右看过去,未被遮挡的最高叶节点,该结点既可以是左节点,也可是右节点。从而,显而易见,这里也需要引入一个栈来实现延迟缓冲的作用。根据上面的分析,应该是当前结点首先入栈,其次是右孩子,最后是左孩子。
当一个结点访问完毕时,代表着以该结点为根的子树访问完毕,此时应该弹栈以访问下一个结点。此时弹栈无非两种情况:
当前结点是左结点。则弹栈的结点是当前结点的右结点。对右结点的处理应该继续迭代地访问右结点的最高左侧可见结点。
当前结点是右结点。则弹栈的结点是当前结点的父结点。此时应该访问当前结点,然后直接进入下一步的迭代,再次进行弹栈操作。
递归版本
和之前一样,交换下位置即可
template <typename T>
template <typename VST>
void lxrbinnode<T>::postOrder_Re(VST visit){
if(this->leftchild) this->leftchild->postOrder_Re(visit);
if(this->rightchild) this->rightchild->postOrder_Re(visit);
visit(this->data);
}
迭代版本
和上面叙述类似
代码如下
template <typename T>
void lxrbinnode<T>::goToHLVFL(lxrstack<lxrbinnodeposi(T)> &S){
lxrbinnodeposi(T) curr;
while(curr=S.top()){
if(curr->leftchild){
if(curr->rightchild) S.push(curr->rightchild);
S.push(curr->leftchild);
}
else S.push(curr->rightchild);
}
S.pop();
}
template <typename T>
template <typename VST>
void lxrbinnode<T>::postOrder_It(VST visit){
lxrstack<lxrbinnodeposi(T)> S;
lxrbinnodeposi(T) curr=this;
S.push(curr);
while(!S.empty()){
if(S.top()!=curr->parent) goToHLVFL(S);
curr=S.pop();
visit(curr->data);
}
}
层级遍历
层级遍历,就是按照深度一层一层的遍历
实现:考虑用队列(queue)对于每一个出队的节点。将他的左右儿子进队
这样能保证每一层都可以按序列出队
代码如下
template <typename T>
template <typename VST>
void lxrbinnode<T>::levelOrder(VST visit){
lxrqueue<lxrbinnodeposi(T)> q;
lxrbinnodeposi(T) curr=this;
q.enqueue(curr);
while(!q.empty()){
curr=q.dequeue();
visit(curr->data);
if(curr->leftchild) q.enqueue(curr->leftchild);
if(curr->rightchild) q.enqueue(curr->rightchild);
}
}
截至现在,二叉树节点文件已经完毕
总代码如下:
代码
#ifndef LXRBINNODE_H_
#define LXRBINNODE_H_
#include "../03 stack and queue/lxrstack.h"
#include "../03 stack and queue/lxrqueue.h"
#define lxrbinnodeposi(T) lxrbinnode<T>*
typedef enum{RED,BLACK} Color;
template <typename T>
class lxrbinnode{
protected:
template <typename VST>
void visitAlongLeftBranch(VST &visit,lxrstack<lxrbinnodeposi(T)> &S);
void goAlongLeftBranch( lxrstack<lxrbinnodeposi(T)> &S);
void goToHLVFL(lxrstack<lxrbinnodeposi(T)> &S);
public:
lxrbinnodeposi(T) parent;
lxrbinnodeposi(T) leftchild;
lxrbinnodeposi(T) rightchild;
Color color;
T data;
int height;
//constructor
lxrbinnode() : parent(nullptr),leftchild(nullptr),rightchild(nullptr),height(0),color(BLACK),npl(0) {};
lxrbinnode(T const &val,lxrbinnodeposi(T) p=nullptr,Color color=BLACK):parent(p),leftchild(nullptr),rightchild(nullptr),data(val),height(0),color(color),npl(0) {};
int size() const; //compute the size of subtree rooted at now node
lxrbinnodeposi(T) insertAsLc(T const &val); //assume that this.leftchild==nullptr
lxrbinnodeposi(T) insertAsRc(T const &val); //assume that this.rightchild=nullptr
lxrbinnodeposi(T) succ(); //return the direct succ of now node
//tree traversal
template <typename VST> void preOrder_Re(VST visit);//use recursion to preorder traversal
template <typename VST> void preOrder_It1(VST visit);//use iteration to preorder traversal
template <typename VST> void preOrder_It2(VST visit);//use iteration to preorder traversal
template <typename VST> void inOrder_Re(VST visit);//use recursion to middle traversal
template <typename VST> void inOrder_It1(VST visit);//use iteration to middle traversal
template <typename VST> void inOrder_It2(VST visit);//use iteration to middle traversal
template <typename VST> void postOrder_Re(VST visit);//use recursion to postorder traversal
template <typename VST> void postOrder_It(VST visit);//use iteration to postorder traversal
template <typename VST> void levelOrder(VST visit);//traversal with depth
};
template<typename T>
template<typename VST>
void lxrbinnode<T>::visitAlongLeftBranch(VST &visit, lxrstack<lxrbinnodeposi(T)> &S){
lxrbinnodeposi(T) curr=this;
while(curr){
visit(curr->data);
S.push(curr->rightchild);
curr=curr->leftchild;
}
}
template <typename T>
void lxrbinnode<T>::goAlongLeftBranch(lxrstack<lxrbinnodeposi(T)> &S){
lxrbinnodeposi(T) curr=this;
while(curr){
S.push(curr);
curr=curr->leftchild;
}
}
template <typename T>
void lxrbinnode<T>::goToHLVFL(lxrstack<lxrbinnodeposi(T)> &S){
lxrbinnodeposi(T) curr;
while(curr=S.top()){
if(curr->leftchild){
if(curr->rightchild) S.push(curr->rightchild);
S.push(curr->leftchild);
}
else S.push(curr->rightchild);
}
S.pop();
}
//public interfaces
template <typename T>
int lxrbinnode<T>::size() const {
int leftSize=this->leftchild ? this->leftchild->size() : 0;
int rightSize=this->rightchild ? this->rightchild->size() :0;
return leftSize+rightSize+1;
}
template <typename T>
lxrbinnodeposi(T) lxrbinnode<T>::insertAsLc(T const &val){
lxrbinnodeposi(T) currNode=new lxrbinnode<T>(val);
currNode->parent=this;
this->leftchild=currNode;
return currNode;
}
template <typename T>
lxrbinnodeposi(T) lxrbinnode<T>::insertAsRc(T const &val){
lxrbinnodeposi(T) currNode=new lxrbinnode<T>(val);
currNode->parent=this;
this->rightchild=currNode;
return currNode;
}
template <typename T>
lxrbinnodeposi(T) lxrbinnode<T>::succ(){
lxrbinnodeposi(T) succ;
if(rightchild){
succ=rightchild;
while(succ->leftchild) succ=succ->leftchild;
}
else{
succ=this;
while(succ->parent&&succ==succ->parent->rightchild) succ=succ->parent;
succ=succ->parent;
}
return succ;
}
//tree traversal
template <typename T>
template <typename VST>
void lxrbinnode<T>::preOrder_Re(VST visit){
visit(this->data);
if(this->leftchild) this->leftchild->preOrder_Re(visit);
if(this->rightchild) this->rightchild->preOrder_Re(visit);
}
template <typename T>
template <typename VST>
void lxrbinnode<T>::preOrder_It1(VST visit){
lxrstack<lxrbinnodeposi(T)> S;
lxrbinnodeposi(T) curr=this;
S.push(curr);
while(!S.empty()){
curr=S.pop();
visit(curr->data);
if(curr->rightchild) S.push(curr->rightchild);
if(curr->leftchild) S.push(curr->leftchild);
}
}
template <typename T>
template <typename VST>
void lxrbinnode<T>::preOrder_It2(VST visit){
lxrstack<lxrbinnodeposi(T)> S;
lxrbinnodeposi(T) curr=this;
while(true){
if(curr) curr->visitAlongLeftBranch(visit,S);
if(S.empty()) break;
curr=S.pop();
}
}
template <typename T>
template <typename VST>
void lxrbinnode<T>::inOrder_Re(VST visit){
if(this->leftchild) this->leftchild->inOrder_Re(visit);
visit(this->data);
if(this->rightchild) this->rightchild->inOrder_Re(visit);
}
template <typename T>
template <typename VST>
void lxrbinnode<T>::inOrder_It1(VST visit){
lxrstack<lxrbinnodeposi(T)> S;
lxrbinnodeposi(T) curr=this;
while(true){
curr->goAlongLeftBranch(S);
if(S.empty()) break;
curr=S.pop();
visit(curr->data);
curr=curr->rightchild;
}
}
template <typename T>
template <typename VST>
void lxrbinnode<T>::inOrder_It2(VST visit){
lxrbinnodeposi(T) curr=this;
bool backTrack=false;
while(curr){
if(!backTrack){
while(curr->leftchild) curr=curr->leftchild;
backTrack=true;
}
else{
visit(curr->data);
if(curr->rightchild){
curr=curr->rightchild;
backTrack=false;
}
else{
while(curr->parent&&curr==curr->parent->rightchild) curr=curr->parent;
curr=curr->parent;
}
}
}
}
template <typename T>
template <typename VST>
void lxrbinnode<T>::postOrder_Re(VST visit){
if(this->leftchild) this->leftchild->postOrder_Re(visit);
if(this->rightchild) this->rightchild->postOrder_Re(visit);
visit(this->data);
}
template <typename T>
template <typename VST>
void lxrbinnode<T>::postOrder_It(VST visit){
lxrstack<lxrbinnodeposi(T)> S;
lxrbinnodeposi(T) curr=this;
S.push(curr);
while(!S.empty()){
if(S.top()!=curr->parent) goToHLVFL(S);
curr=S.pop();
visit(curr->data);
}
}
template <typename T>
template <typename VST>
void lxrbinnode<T>::levelOrder(VST visit){
lxrqueue<lxrbinnodeposi(T)> q;
lxrbinnodeposi(T) curr=this;
q.enqueue(curr);
while(!q.empty()){
curr=q.dequeue();
visit(curr->data);
if(curr->leftchild) q.enqueue(curr->leftchild);
if(curr->rightchild) q.enqueue(curr->rightchild);
}
}
#endif
二叉树
接下来手搓二叉树部分
函数总览:
template <typename T>
class lxrbintree{
protected:
lxrbinnodeposi(T) __root;
int __size;
virtual bool updateHeight(lxrbinnodeposi(T) x);
virtual void updateHeightAbove(lxrbinnodeposi(T) x);
lxrbinnodeposi(T) higherChild(lxrbinnodeposi(T) x);
public:
//constructor
lxrbintree():__root(nullptr),__size(0) {};
//deconstructor
~lxrbintree()=default;
bool empty() const { return __size == 0; }
int size() const {return __size;}
lxrbinnodeposi(T) root() const {return __root;}
lxrbinnodeposi(T) insertAsRoot(T const &val);
lxrbinnodeposi(T) insertAsLc(lxrbinnodeposi(T) x,T const &val);
lxrbinnodeposi(T) insertAsRc(lxrbinnodeposi(T) x,T const &val);
};
对于每一棵二叉树,主要变量有
__root:根节点
__size:全树节点总数
接下来介绍主要函数
updateHeight
该函数主要作用是通过子节点更新该节点的高度
实现非常简单
该节点高度=MAX(左子树高度,右子树高度)+1
代码如下
template <typename T>
bool lxrbintree<T>::updateHeight(lxrbinnodeposi(T) x){
int prevHeight=x->height;
int leftHeight=x->leftchild ? x->leftchild->height:-1;
int rightHeight=x->rightchild ? x->rightchild->height:-1;
x->height=MAX(leftHeight,rightHeight)+1;
return prevHeight != x->height;
}
updateHeightAbove
作用:如果对节点x进行改动,高度变化会随着x的祖先一直向上更新
该函数作用即为更新x改动后对高度的影响
实现:一直枚举x的祖先,更新到顶部为止
代码如下:
template <typename T>
void lxrbintree<T>::updateHeightAbove(lxrbinnodeposi(T) x){
for(; x&& updateHeight(x);x=x->parent);
}
higerchild
顾名思义,返回这个节点高度更高的儿子
如果只有一个儿子直接返回那个儿子
否则比较一下
代码如下
template <typename T>
lxrbinnodeposi(T) lxrbintree<T>::higherChild(lxrbinnodeposi(T) x){
if(!x->leftchild) return x->rightchild;
if(!x->rightchild) return x->leftchild;
return x->leftchild->height < x->rightchild->height ? x->rightchild:x->leftchild;
}
insert函数
该函数为插入函数,只要为插入根节点,在节点x的左儿子插入一个节点
在节点x的右儿子插入一个节点
我们只需要插入之后更新一下高度即可
代码如下
template <typename T>
lxrbinnodeposi(T) lxrbintree<T>::insertAsRoot(T const &val){
__size=1;
return __root=new lxrbinnode<T>(val);
}
template <typename T>
lxrbinnodeposi(T) lxrbintree<T>::insertAsLc(lxrbinnodeposi(T) x,T const &val){
++__size;
lxrbinnodeposi(T) res=x->insertAsLc(val);
updateHeightAbove(x);
return res;
}
template <typename T>
lxrbinnodeposi(T) lxrbintree<T>::insertAsRc(lxrbinnodeposi(T) x,T const &val){
++__size;
lxrbinnodeposi(T) res=x->insertAsRc(val);
updateHeightAbove(x);
return res;
}
代码
总体代码如下
#ifndef LXRBINTREE_H_
#define LXRBINTREE_H_
#include "lxrbinnode.h"
#define FROMPARENTTO(X) (X->parent? __root:X==X->parent->leftchild? X->parent->leftchild: X->parent->rigthchild)
// if(x->parent!=0){
// return __root;
// }
// else{
// if(X==X->parent->leftchild){
// return X->parent->leftchild;
// }
// else{
// return x->parent->rightchild;
// }
// }
#define STATURE(X) ((X)?(X)->height:-1)
#define MAX(X,Y) ((X)>(Y)?(X):(Y))
template <typename T>
class lxrbintree{
protected:
lxrbinnodeposi(T) __root;
int __size;
virtual bool updateHeight(lxrbinnodeposi(T) x);
virtual void updateHeightAbove(lxrbinnodeposi(T) x);
lxrbinnodeposi(T) higherChild(lxrbinnodeposi(T) x);
public:
//constructor
lxrbintree():__root(nullptr),__size(0) {};
//deconstructor
~lxrbintree()=default;
bool empty() const { return __size == 0; }
int size() const {return __size;}
lxrbinnodeposi(T) root() const {return __root;}
lxrbinnodeposi(T) insertAsRoot(T const &val);
lxrbinnodeposi(T) insertAsLc(lxrbinnodeposi(T) x,T const &val);
lxrbinnodeposi(T) insertAsRc(lxrbinnodeposi(T) x,T const &val);
};
//protected methods
template <typename T>
bool lxrbintree<T>::updateHeight(lxrbinnodeposi(T) x){
int prevHeight=x->height;
int leftHeight=x->leftchild ? x->leftchild->height:-1;
int rightHeight=x->rightchild ? x->rightchild->height:-1;
x->height=MAX(leftHeight,rightHeight)+1;
return prevHeight != x->height;
}
template <typename T>
void lxrbintree<T>::updateHeightAbove(lxrbinnodeposi(T) x){
for(; x&& updateHeight(x);x=x->parent);
}
template <typename T>
lxrbinnodeposi(T) lxrbintree<T>::higherChild(lxrbinnodeposi(T) x){
if(!x->leftchild) return x->rightchild;
if(!x->rightchild) return x->leftchild;
return x->leftchild->height < x->rightchild->height ? x->rightchild:x->leftchild;
}
//public interfaces
template <typename T>
lxrbinnodeposi(T) lxrbintree<T>::insertAsRoot(T const &val){
__size=1;
return __root=new lxrbinnode<T>(val);
}
template <typename T>
lxrbinnodeposi(T) lxrbintree<T>::insertAsLc(lxrbinnodeposi(T) x,T const &val){
++__size;
lxrbinnodeposi(T) res=x->insertAsLc(val);
updateHeightAbove(x);
return res;
}
template <typename T>
lxrbinnodeposi(T) lxrbintree<T>::insertAsRc(lxrbinnodeposi(T) x,T const &val){
++__size;
lxrbinnodeposi(T) res=x->insertAsRc(val);
updateHeightAbove(x);
return res;
}
#endif
自此,一颗完整的二叉树就搓好了
二叉树可以派生出二叉搜索树BST
而BST又可以派生出一系列高级搜索树
后续会更新一些后面的搜索树,会include此文件