【数据结构(C++实现)】:二叉树的定义、性质、各种操作及其实现

目录

二叉树

二叉树的各种操作(C++)

        二叉树的结点定义

        二叉树接口的定义

        插入

        删除

        先序遍历

        中序遍历

        后序遍历

        层次遍历

        树的高度

完整代码

其他类型的树

二叉查找(搜索)树

2-3叉树

红黑树

AVL树

B树

B+树


  • 二叉树

  • 二叉树的各种操作(C++)

        二叉树的结点定义

/*二叉树结点*/
template <typename T>
class BiTreeNode{
public:
    T data;
    BiTreeNode<T>* left;
    BiTreeNode<T>* right;
    BiTreeNode(T data){
        this->data = data;
        this->left = NULL;
        this->right = NULL;
    }
};

        二叉树接口的定义

template <typename T>
class BiTree{
private:
    int size;/*树中结点的个数*/
public:
    BiTreeNode<T>* root;/*根结点的指针*/

    BiTree(){size=0;root=NULL;};
    ~BiTree(){remove(root);};

    bool insert_left(BiTreeNode<T>* node,T data);/*将data插入到node的左孩子*/
    bool insert_right(BiTreeNode<T>* node,T data);/*将data插入到node的右孩子*/
    bool remove(BiTreeNode<T>* &node);/*删除以node为根的子树*/
    bool preorderR(BiTreeNode<T>* node,list<T>* l);/*递归实现:先序遍历以node为根的树,并将遍历结果保存到l中*/
    bool preorderI(BiTreeNode<T>* node,list<T>* l);/*迭代实现:先序遍历以node为根的树,并将遍历结果保存到l中*/
    bool inorderR(BiTreeNode<T>* node,list<T>* l);/*递归实现:中序遍历以node为根的树,并将遍历结果保存到l中*/
    bool inorderI(BiTreeNode<T>* node,list<T>* l);/*迭代实现:中序遍历以node为根的树,并将遍历结果保存到l中*/
    bool postorderR(BiTreeNode<T>* node,list<T>* l);/*递归实现:后序遍历以node为根的树,并将遍历结果保存到l中*/
    bool postorderI(BiTreeNode<T>* node,list<T>* l);/*迭代实现:后序遍历以node为根的树,并将遍历结果保存到l中*/
    bool level(BiTreeNode<T>* node,list<T>* l);/*层次遍历以node为根的树,并将变量结果保存到l中*/
    int height(BiTreeNode<T>* node);/*以node为根的树的高度*/
};

        插入

/**************************************************************************
Function:insert_left
Description:将data插入到node的左孩子
Input:二叉树结点node,数据data
Output:插入是否成功
***************************************************************************/
template <typename T>
bool BiTree<T>::insert_left(BiTreeNode<T>* node,T data){
    if(node==NULL){//允许空树插入结点
        if(size>0)
            return false;
        else
            root = new BiTreeNode<T>(data);
    }else{
        if(node->left!=NULL)
            return false;
        else
            node->left = new BiTreeNode<T>(data);
    }
    size++;
    return true;
}
/**************************************************************************
Function:insert_right
Description:将data插入到node的右孩子
Input:二叉树结点node,数据data
Output:插入是否成功
***************************************************************************/
template <typename T>
bool BiTree<T>::insert_right(BiTreeNode<T>* node,T data){
    if(node==NULL){
        if(size>0)
            return false;
        else
            root = new BiTreeNode<T>(data);
    }else{
        if(node->right!=NULL)
            return false;
        else
            node->right = new BiTreeNode<T>(data);
    }
    size++;
    return true;
}

        删除

/**************************************************************************
Function:remove
Description:删除以node为根的子树
Input:二叉树结点node的引用
Output:删除是否成功
***************************************************************************/
template <typename T>
bool BiTree<T>::remove(BiTreeNode<T>* &node){
    /*之所以要传入指针的引用,是因为不但要释放node指向的空间,
    同样也需要将node内保存的地址更改为NULL*/
    if(node==NULL)
        return false;
    if(remove(node->left)&&remove(node->right)){
        delete node;//释放p指向的空间
        node = NULL;//清空p内的地址
        size--;
        return true;
    }else
        return false;
}

        先序遍历

              (1).规则:先访问根结点,然后按规则遍历左子树,再按规则遍历右子树;图2中的树先序遍历的结果为:124895367;

              (2).递归实现

template <typename T>
bool BiTree<T>::preorderR(BiTreeNode<T>* node,list<T>* l){
    if(node==NULL||l==NULL)
        return false;
    l->push_back(node->data);
    preorderR(node->left,l);
    preorderR(node->right,l);
    return true;
}

              (3).迭代实现

template <typename T>
bool BiTree<T>::preorderI(BiTreeNode<T>* node,list<T>* l){
    if(node==NULL||l==NULL)
        return false;
    stack<BiTreeNode<T>*> s;
    BiTreeNode<T>* p = node;
    while(p!=NULL||!s.empty()){
        if(p!=NULL){
            //压入栈时输出
            l->push_back(p->data);
            s.push(p);
            p = p->left;
        }else{
            p = s.top();
            s.pop();
            p = p->right;
        }
    }
    return true;
}

        中序遍历

              (1).先中序遍历左子树,再访问根结点,最后中序遍历右子树;图2中的树中序遍历结果:849251637;

              (2).递归实现

template <typename T>
bool BiTree<T>::inorderR(BiTreeNode<T>* node,list<T>* l){
    if(node==NULL||l==NULL)
        return false;
    inorderR(node->left,l);
    l->push_back(node->data);
    inorderR(node->right,l);
    return true;
}

              (3).迭代实现

template <typename T>
bool BiTree<T>::inorderI(BiTreeNode<T>* node,list<T>* l){
    if(node==NULL||l==NULL)
        return false;
    stack<BiTreeNode<T>*> s;
    BiTreeNode<T>* p = node;
    while(!s.empty()||p!=NULL){
        if(p!=NULL){
            s.push(p);
            p = p->left;//下一个该访问的结点
        }else{
            p = s.top();
            s.pop();//要访问就弹出
            l->push_back(p->data);//弹出栈时输出
            p = p->right;//下一个该访问的结点
        }
    }
    return true;
}

        后序遍历

              (1).后序遍历左子树,再后序遍历右子树,最终访问根结点;图2中的树后序遍历的结果:894526731;

              (2).递归实现

template <typename T>
bool BiTree<T>::postorderR(BiTreeNode<T>* node,list<T>* l){
    if(node==NULL||l==NULL)
        return false;
    postorderR(node->left,l);
    postorderR(node->right,l);
    l->push_back(node->data);
    return true;
}

              (3).迭代实现

template <typename T>
bool BiTree<T>::postorderI(BiTreeNode<T>* node,list<T>* l){
    if(node==NULL||l==NULL)
        return false;
    stack<BiTreeNode<T>*> s;
    BiTreeNode<T>* p = node;
    BiTreeNode<T>* pre = NULL;//用于标记先前访问过的结点
    while(!s.empty()||p!=NULL){
        if(p!=NULL){
            s.push(p);
            p = p->left;
        }else{
            BiTreeNode<T>* right = s.top()->right;
            if(right!=NULL&&right!=pre){
                p = right;
            }else{
                //在p==NULL且right!=NULL&&right!=pre时,
                //说明要访问栈顶结点了
                pre = s.top();
                l->push_back(pre->data);
                s.pop();
            }
        }
    }
    return true;
}

        层次遍历

              (1).从上到下,从左到右依次访问结点;图2中的树层次遍历结果为:123456789;

              (2).实现(需要借助队列)

template <typename T>
bool BiTree<T>::level(BiTreeNode<T>* node,list<T>* l){
    if(node==NULL||l==NULL)
        return false;
    queue<BiTreeNode<T>*> q;
    q.push(node);
    BiTreeNode<T>* p = NULL;
    while(!q.empty()){
        p = q.front();
        q.pop();
        l->push_back(p->data);
        if(p->left!=NULL)q.push(p->left);
        if(p->right!=NULL)q.push(p->right);
    }
    return true;
}

        树的高度

template <typename T>
int BiTree<T>::height(BiTreeNode<T>* node){
    if(node==NULL)
        return 0;
    int left_height = height(node->left);
    int right_height = height(node->right);
    return max(left_height,right_height)+1;
}
  • 完整代码


/*数据结构:二叉树*/

#include <iostream>
#include <list>
#include <stack>
#include <queue>

using namespace std;

/*二叉树结点*/
template <typename T>
class BiTreeNode{
public:
    T data;
    BiTreeNode<T>* left;
    BiTreeNode<T>* right;
    BiTreeNode(T data){
        this->data = data;
        this->left = NULL;
        this->right = NULL;
    }
};

template <typename T>
class BiTree{
private:
    int size;/*树中结点的个数*/
public:
    BiTreeNode<T>* root;/*根结点的指针*/

    BiTree(){size=0;root=NULL;};
    ~BiTree(){remove(root);};

    bool insert_left(BiTreeNode<T>* node,T data);/*将data插入到node的左孩子*/
    bool insert_right(BiTreeNode<T>* node,T data);/*将data插入到node的右孩子*/
    bool remove(BiTreeNode<T>* &node);/*删除以node为根的子树*/
    bool preorderR(BiTreeNode<T>* node,list<T>* l);/*递归实现:先序遍历以node为根的树,并将遍历结果保存到l中*/
    bool preorderI(BiTreeNode<T>* node,list<T>* l);/*迭代实现:先序遍历以node为根的树,并将遍历结果保存到l中*/
    bool inorderR(BiTreeNode<T>* node,list<T>* l);/*递归实现:中序遍历以node为根的树,并将遍历结果保存到l中*/
    bool inorderI(BiTreeNode<T>* node,list<T>* l);/*迭代实现:中序遍历以node为根的树,并将遍历结果保存到l中*/
    bool postorderR(BiTreeNode<T>* node,list<T>* l);/*递归实现:后序遍历以node为根的树,并将遍历结果保存到l中*/
    bool postorderI(BiTreeNode<T>* node,list<T>* l);/*迭代实现:后序遍历以node为根的树,并将遍历结果保存到l中*/
    bool level(BiTreeNode<T>* node,list<T>* l);/*层次遍历以node为根的树,并将变量结果保存到l中*/
    int height(BiTreeNode<T>* node);/*以node为根的树的高度*/
};

/**************************************************************************
Function:insert_left
Description:将data插入到node的左孩子
Input:二叉树结点node,数据data
Output:插入是否成功
***************************************************************************/
template <typename T>
bool BiTree<T>::insert_left(BiTreeNode<T>* node,T data){
    if(node==NULL){//允许空树插入结点
        if(size>0)
            return false;
        else
            root = new BiTreeNode<T>(data);
    }else{
        if(node->left!=NULL)
            return false;
        else
            node->left = new BiTreeNode<T>(data);
    }
    size++;
    return true;
}
/**************************************************************************
Function:insert_right
Description:将data插入到node的右孩子
Input:二叉树结点node,数据data
Output:插入是否成功
***************************************************************************/
template <typename T>
bool BiTree<T>::insert_right(BiTreeNode<T>* node,T data){
    if(node==NULL){
        if(size>0)
            return false;
        else
            root = new BiTreeNode<T>(data);
    }else{
        if(node->right!=NULL)
            return false;
        else
            node->right = new BiTreeNode<T>(data);
    }
    size++;
    return true;
}

/**************************************************************************
Function:remove
Description:删除以node为根的子树
Input:二叉树结点node的引用
Output:删除是否成功
***************************************************************************/
template <typename T>
bool BiTree<T>::remove(BiTreeNode<T>* &node){
    /*之所以要传入指针的引用,是因为不但要释放node指向的空间,
    同样也需要将node内保存的地址更改为NULL*/
    if(node==NULL)
        return false;
    if(remove(node->left)&&remove(node->right)){
        delete node;//释放p指向的空间
        node = NULL;//清空p内的地址
        size--;
        return true;
    }else
        return false;
}

/**************************************************************************
Function:preorderR、preorderI
Description:先序遍历以node为根的数,并将遍历结果保存到l中
Input:二叉树结点node,列表l
Output:遍历是否成功
***************************************************************************/
template <typename T>
bool BiTree<T>::preorderR(BiTreeNode<T>* node,list<T>* l){
    if(node==NULL||l==NULL)
        return false;
    l->push_back(node->data);
    preorderR(node->left,l);
    preorderR(node->right,l);
    return true;
}
template <typename T>
bool BiTree<T>::preorderI(BiTreeNode<T>* node,list<T>* l){
    if(node==NULL||l==NULL)
        return false;
    stack<BiTreeNode<T>*> s;
    BiTreeNode<T>* p = node;
    while(p!=NULL||!s.empty()){
        if(p!=NULL){
            //压入栈时输出
            l->push_back(p->data);
            s.push(p);
            p = p->left;
        }else{
            p = s.top();
            s.pop();
            p = p->right;
        }
    }
    return true;
}
/**************************************************************************
Function:inorderR、inorderI
Description:中序遍历以node为根的数,并将遍历结果保存到l中
Input:二叉树结点node,列表l
Output:遍历是否成功
***************************************************************************/
template <typename T>
bool BiTree<T>::inorderR(BiTreeNode<T>* node,list<T>* l){
    if(node==NULL||l==NULL)
        return false;
    inorderR(node->left,l);
    l->push_back(node->data);
    inorderR(node->right,l);
    return true;
}
template <typename T>
bool BiTree<T>::inorderI(BiTreeNode<T>* node,list<T>* l){
    if(node==NULL||l==NULL)
        return false;
    stack<BiTreeNode<T>*> s;
    BiTreeNode<T>* p = node;
    while(!s.empty()||p!=NULL){
        if(p!=NULL){
            s.push(p);
            p = p->left;//下一个该访问的结点
        }else{
            p = s.top();
            s.pop();//要访问就弹出
            l->push_back(p->data);//弹出栈时输出
            p = p->right;//下一个该访问的结点
        }
    }
    return true;
}
/**************************************************************************
Function:postorderR、postorderI
Description:后序遍历以node为根的数,并将遍历结果保存到l中
Input:二叉树结点node,列表l
Output:遍历是否成功
***************************************************************************/
template <typename T>
bool BiTree<T>::postorderR(BiTreeNode<T>* node,list<T>* l){
    if(node==NULL||l==NULL)
        return false;
    postorderR(node->left,l);
    postorderR(node->right,l);
    l->push_back(node->data);
    return true;
}
template <typename T>
bool BiTree<T>::postorderI(BiTreeNode<T>* node,list<T>* l){
    if(node==NULL||l==NULL)
        return false;
    stack<BiTreeNode<T>*> s;
    BiTreeNode<T>* p = node;
    BiTreeNode<T>* pre = NULL;//用于标记先前访问过的结点
    while(!s.empty()||p!=NULL){
        if(p!=NULL){
            s.push(p);
            p = p->left;
        }else{
            BiTreeNode<T>* right = s.top()->right;
            if(right!=NULL&&right!=pre){
                p = right;
            }else{
                //在p==NULL且right!=NULL&&right!=pre时,
                //说明要访问栈顶结点了
                pre = s.top();
                l->push_back(pre->data);
                s.pop();
            }
        }
    }
    return true;
}
/**************************************************************************
Function:level
Description:层次遍历以node为根的树,并将变量结果保存到l中
Input:二叉树结点node,列表l
Output:遍历是否成功
***************************************************************************/
template <typename T>
bool BiTree<T>::level(BiTreeNode<T>* node,list<T>* l){
    if(node==NULL||l==NULL)
        return false;
    queue<BiTreeNode<T>*> q;
    q.push(node);
    BiTreeNode<T>* p = NULL;
    while(!q.empty()){
        p = q.front();
        q.pop();
        l->push_back(p->data);
        if(p->left!=NULL)q.push(p->left);
        if(p->right!=NULL)q.push(p->right);
    }
    return true;
}

/**************************************************************************
Function:height
Description:以node为根的树的高度
Input:二叉树结点node
Output:树的高度
***************************************************************************/
template <typename T>
int BiTree<T>::height(BiTreeNode<T>* node){
    if(node==NULL)
        return 0;
    int left_height = height(node->left);
    int right_height = height(node->right);
    return max(left_height,right_height)+1;
}

int main(){
    BiTree<int>* biTree = new BiTree<int>();
    /*
    构建二叉树:
       3
     6   2
    8 9
    */
    biTree->insert_left(biTree->root,3);
    biTree->insert_left(biTree->root,6);
    biTree->insert_right(biTree->root,2);
    biTree->insert_left(biTree->root->left,8);
    biTree->insert_right(biTree->root->left,9);
    list<int> l;
    list<int>::iterator iter;
    //先序遍历
    biTree->preorderR(biTree->root,&l);
    cout<<endl<<"先序遍历(递归):";
    for(iter=l.begin();iter!=l.end();iter++)
        cout<<*iter<<",";
    l.clear();
    biTree->preorderI(biTree->root,&l);
    cout<<endl<<"先序遍历(迭代):";
    for(iter=l.begin();iter!=l.end();iter++)
        cout<<*iter<<",";
    l.clear();

    //中序遍历
    biTree->inorderR(biTree->root,&l);
    cout<<endl<<"中序遍历(递归):";
    for(iter=l.begin();iter!=l.end();iter++)
        cout<<*iter<<",";
    l.clear();
    biTree->inorderI(biTree->root,&l);
    cout<<endl<<"中序遍历(迭代):";
    for(iter=l.begin();iter!=l.end();iter++)
        cout<<*iter<<",";
    l.clear();

    //后序遍历
    biTree->postorderR(biTree->root,&l);
    cout<<endl<<"后序遍历(递归):";
    for(iter=l.begin();iter!=l.end();iter++)
        cout<<*iter<<",";
    l.clear();
    biTree->postorderI(biTree->root,&l);
    cout<<endl<<"后序遍历(迭代):";
    for(iter=l.begin();iter!=l.end();iter++)
        cout<<*iter<<",";
    l.clear();

    //层次遍历
    biTree->level(biTree->root,&l);
    cout<<endl<<"层次遍历:";
    for(iter=l.begin();iter!=l.end();iter++)
        cout<<*iter<<",";
    l.clear();
    cout<<endl<<biTree->height(biTree->root);
    delete biTree;
}
  • 其他类型的树

  1. 二叉查找(搜索)树

  2. 2-3叉树

  3. 红黑树

  4. AVL树

  5. B树

  6. B+树

  • 31
    点赞
  • 149
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BQW_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值