一般二叉树

一般二叉树

什么是二叉树?

树是常用的一种非线性数据结构。

树有很多衍生分类,其中,二叉树便是最为常见的一种。

二叉树的定义是以递归形式给出的:一棵二叉树是结点的一个有限集合,该集合可能为空,或则是由一个根节点加上两棵分别称为左子树、右子树的、互不相交的二叉树组成。

二叉树的特点是每个结点最多有两个子女,分别称为该节点的左子树和右子树。

在二叉树中不存在度大于2的结点,并且二叉树的字子树有左子树、右子树之分,其子树的次序不能颠倒。

二叉树是分支数最大不超过2的有根有序树。

二叉树的性质

image-20211024150453728

二叉树的基本操作?

二叉树的基本操作有:

  • 创建二叉树
  • 前序遍历
  • 中序遍历
  • 后序遍历
  • 层序遍历
  • 求结点个数
  • 求二叉树的深度
  • 销毁二叉树

二叉树相关算法的基本模式

由于树本身的定义就是递归定义的,

所以二叉树的基本操作多半基于递归思想实现。

二叉树结点结构体的设计

//结点结构体的定义
struct BiNode
{
    /* data */
    int data;
    BiNode *lchild; //左孩子
    BiNode *rchild; //右孩子
};

二叉树类的设计

class BiTree
{
private:
    /* data */
    int IsRoot=0;
    BiNode *Creat();                //构造函数调用
    void Release(BiNode *bt);       //析构函数调用
    void PreOrder(BiNode *bt);      //前序遍历函数调用
    void InOrder(BiNode *bt);       //中序遍历函数调用
    void PostOrder(BiNode *bt);     //后序遍历函数调用过程
    int Size(BiNode *bt);           //获取结点个数调用过程
    int Height(BiNode *bt);         //获取二叉树高度的调用过程
    BiNode *root;                   //指向根节点的头指针
public:
    BiTree(){this->root=Creat();}   //构造函数  建立一棵二叉树
    ~BiTree(){Release(root);}       //析构函数,释放各结点的存储空间
    void PreOrder(){PreOrder(root);}    //前序遍历二叉树
    void InOrder(){InOrder(root);}      //中序遍历二叉树
    void PostOrder(){PostOrder(root);}  //后序遍历二叉树
    int Size(){return Size(root);}      //获取二叉树结点个数
    int Height(){return Height(root);}  //获取二叉树的高度(深度)
};

二叉树类的实现

创建二叉树

我们采用从键盘输入的方式进行创建,当输入0时表示该结点为空。

BiNode* BiTree::Creat()
{
    //可以采用广义表的方法去建立二叉树
    // if(IsRoot==0)
    // {
    //     cout<<"请输入根结点数据域(0表示空)"
    // }
    BiNode *bt;
    int da;     //临时变量
    cout<<"请输入该结点数据域(0表示空):";
    cin>>da;
    if(da==0)
    {
        bt=nullptr;
    }
    else
    {
        bt=new BiNode;
        bt->data=da;
        bt->lchild=Creat();     //递归调用创建结点方法
        bt->rchild=Creat();     //递归调用创建结点方法
    }
    return bt;      //返回总树及每一棵子树的根节点root
}

销毁二叉树

void BiTree::Release(BiNode *bt)
{
    //析构函数的调用过程
    cout<<"析构"<<endl;
    //和后续遍历的思想一致
    //左子树  右子树  根节点

    //递归终止条件
    if(bt==nullptr)
    {
        return;
    }
    else
    {
        Release(bt->lchild);    //递归调用释放左子树
        Release(bt->rchild);    //递归调用释放右子树
        delete bt;
    }
    cout<<"析构成功"<<endl;
}

前序遍历

void BiTree::PreOrder(BiNode *bt)
{
    //递归调用的终止条件
    if(bt==nullptr)
    {
        return;
    }
    else
    {
        //前序遍历: 根节点  左子树  右子树
        cout<<bt->data<<" ";        //输出数据域
        PreOrder(bt->lchild);
        PreOrder(bt->rchild);
    }
}

中序遍历

void BiTree::InOrder(BiNode *bt)
{
    //中序遍历
    if(bt==nullptr)
    {
        return;
    }
    else
    {
        //中序遍历: 左子树  根节点 右子树
        InOrder(bt->lchild);
        cout<<bt->data<<" ";
        InOrder(bt->rchild);
    }
}

后序遍历

void BiTree::PostOrder(BiNode *bt)
{
    //后序遍历
    if(bt==nullptr)
    {
        return;
    }
    else
    {
        //后序遍历:左子树 右子树 根节点
        PostOrder(bt->lchild);
        PostOrder(bt->rchild);
        cout<<bt->data<<" ";
    }
}

求结点个数

int BiTree::Size(BiNode *bt)
{
    if(bt==nullptr)
    {
        return 0;
    }
    return 1+Size(bt->lchild)+Size(bt->rchild);
}

求二叉树的深度

int BiTree::Height(BiNode *bt)
{
    //求二叉树的高度(深度)
    if(bt==nullptr)
    {
        return 0;
    }
    int i=Height(bt->lchild);
    int j=Height(bt->rchild);
    return i<j ? j+1 : i+1;
}

二叉树测试

#include<iostream>
#include"BiTree.h"
using namespace std;

int main()
{
    cout<<"基于链式存储结构的二叉树"<<endl;
    BiTree b1;
    cout<<"前序遍历:";
    b1.PreOrder();
    cout<<endl;

    cout<<"中序遍历:";
    b1.InOrder();
    cout<<endl;

    cout<<"后序遍历:";
    b1.PostOrder();
    cout<<endl;
    
    cout<<"当前二叉树共有"<<b1.Size()<<"个结点"<<endl;
    cout<<"当前二叉树的高度(深度)为"<<b1.Height()<<endl;
    system("pause");
    return 0;
}

完整代码

BiTree.h

/*
手撕二叉树
树结构本身是递归定义的
在这里,我们整个数据结构的定义和实现也大多基于递归
*/

#include<iostream>
using namespace std;

//结点结构体的定义
struct BiNode
{
    /* data */
    int data;
    BiNode *lchild; //左孩子
    BiNode *rchild; //右孩子
};

class BiTree
{
private:
    /* data */
    int IsRoot=0;
    BiNode *Creat();                //构造函数调用
    void Release(BiNode *bt);       //析构函数调用
    void PreOrder(BiNode *bt);      //前序遍历函数调用
    void InOrder(BiNode *bt);       //中序遍历函数调用
    void PostOrder(BiNode *bt);     //后序遍历函数调用过程
    int Size(BiNode *bt);           //获取结点个数调用过程
    int Height(BiNode *bt);         //获取二叉树高度的调用过程
    BiNode *root;                   //指向根节点的头指针
public:
    BiTree(){this->root=Creat();}   //构造函数  建立一棵二叉树
    ~BiTree(){Release(root);}       //析构函数,释放各结点的存储空间
    void PreOrder(){PreOrder(root);}    //前序遍历二叉树
    void InOrder(){InOrder(root);}      //中序遍历二叉树
    void PostOrder(){PostOrder(root);}  //后序遍历二叉树
    int Size(){return Size(root);}      //获取二叉树结点个数
    int Height(){return Height(root);}  //获取二叉树的高度(深度)
};

BiTree.cpp

#include"BiTree.h"

BiNode* BiTree::Creat()
{
    //可以采用广义表的方法去建立二叉树
    // if(IsRoot==0)
    // {
    //     cout<<"请输入根结点数据域(0表示空)"
    // }
    BiNode *bt;
    int da;     //临时变量
    cout<<"请输入该结点数据域(0表示空):";
    cin>>da;
    if(da==0)
    {
        bt=nullptr;
    }
    else
    {
        bt=new BiNode;
        bt->data=da;
        bt->lchild=Creat();     //递归调用创建结点方法
        bt->rchild=Creat();     //递归调用创建结点方法
    }
    return bt;      //返回总树及每一棵子树的根节点root
}

void BiTree::Release(BiNode *bt)
{
    //析构函数的调用过程
    cout<<"析构"<<endl;
    //和后续遍历的思想一致
    //左子树  右子树  根节点

    //递归终止条件
    if(bt==nullptr)
    {
        return;
    }
    else
    {
        Release(bt->lchild);    //递归调用释放左子树
        Release(bt->rchild);    //递归调用释放右子树
        delete bt;
    }
    cout<<"析构成功"<<endl;
}

void BiTree::PreOrder(BiNode *bt)
{
    //递归调用的终止条件
    if(bt==nullptr)
    {
        return;
    }
    else
    {
        //前序遍历: 根节点  左子树  右子树
        cout<<bt->data<<" ";        //输出数据域
        PreOrder(bt->lchild);
        PreOrder(bt->rchild);
    }
}

void BiTree::InOrder(BiNode *bt)
{
    //中序遍历
    if(bt==nullptr)
    {
        return;
    }
    else
    {
        //中序遍历: 左子树  根节点 右子树
        InOrder(bt->lchild);
        cout<<bt->data<<" ";
        InOrder(bt->rchild);
    }
}

void BiTree::PostOrder(BiNode *bt)
{
    //后序遍历
    if(bt==nullptr)
    {
        return;
    }
    else
    {
        //后序遍历:左子树 右子树 根节点
        PostOrder(bt->lchild);
        PostOrder(bt->rchild);
        cout<<bt->data<<" ";
    }
}

int BiTree::Size(BiNode *bt)
{
    if(bt==nullptr)
    {
        return 0;
    }
    return 1+Size(bt->lchild)+Size(bt->rchild);
}

int BiTree::Height(BiNode *bt)
{
    //求二叉树的高度(深度)
    if(bt==nullptr)
    {
        return 0;
    }
    int i=Height(bt->lchild);
    int j=Height(bt->rchild);
    return i<j ? j+1 : i+1;
}

main.cpp

#include<iostream>
#include"BiTree.h"
using namespace std;

int main()
{
    cout<<"基于链式存储结构的二叉树"<<endl;
    BiTree b1;
    cout<<"前序遍历:";
    b1.PreOrder();
    cout<<endl;

    cout<<"中序遍历:";
    b1.InOrder();
    cout<<endl;

    cout<<"后序遍历:";
    b1.PostOrder();
    cout<<endl;
    
    cout<<"当前二叉树共有"<<b1.Size()<<"个结点"<<endl;
    cout<<"当前二叉树的高度(深度)为"<<b1.Height()<<endl;
    system("pause");
    return 0;
}

思考

如何优化二叉树的创建过程?

前/中/后序遍历如何通过非递归方式实现?

层序遍历如何实现?基于队列?

用code改变世界的创造者们,节日快乐!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值