(数据结构)如何手搓一棵二叉树?

目录

二叉树结点 binnode

函数总览

构造:

size()

insertAsLc()

insertAsRc()

succ()

前序遍历

递归版本

迭代版本

中序遍历

递归版本

迭代版本

后序遍历

递归版本

迭代版本

层级遍历

代码

二叉树

函数总览:

updateHeight

updateHeightAbove

higerchild

insert函数

代码


二叉树是很多数据结构的基础

众所周知,二叉树中每个节点最多有两个儿子

对于二叉树,最重要的就是前中后序遍历,这也是本文写的最多的部分

整棵树分为两大部分实现,二叉树节点(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此文件

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值