数据结构复习——二叉树

1、基本概念。

二叉树:一种特化的树形结构。每个节点至多有两棵子树(每个节点的度小于等于2),即左子树与右子树,且左子树与右子树之间有左右差别。顺序不能颠倒。

满二叉树:每一层节点数为能所容纳的节点的最大数。

完全二叉树:最后一次层可以不满,但是要与满二叉树的节点编号对应。

2、二叉树的重要性质。

①第i层至多有[2^(i-1)]个结点。

②深度为d的二叉树至多共有[2^d-1]个结点。

③假定叶子结点个数为n0,度为2的节点个数为n2,则两者满足关系:n0=n1+1;

④节点个数为n的二叉树的深度为,Log2n+1;

⑤若一棵具有n个节点的完全二叉树的节点编号从上到下,从左到右,依次编号为1,2,3,...,n,则对于编号为i的节点,其父节点i/2;若2*i<=n,则其左子树根节点编号为2*i;若2*i+1<=n,则右子树节点编号为2*i+1;因此,最后一个非叶子节点为 [n/2-1]。

3、存储方式。

3-1、顺序存储;

3-2、链式存储。

4、实现。

4-1、二叉树的链式存储;

4-2、建立树;

4-3、遍历;

4-4、查找;

4-5、删除节点;

3、实现。

//定义树中的基本节点
struct BiTNode
{
    //数据域
    int data_;
    //指向左右节点的指针
    BiTNode *lChild_,*rChild_;

    BiTNode(int data):
        data_(data),
        lChild_(nullptr),
        rChild_(nullptr)
    {
    }
};

typedef BiTNode* BiTre;

//创建完全二叉树
void createTree(BiTre& tree)
{
    char data_;
    std::cin>>data_;

    if(data_=='#')
    {
        tree=nullptr;
    }
    else
    {
        if(nullptr==tree)
            tree=new BiTNode(data_);

        //创建左子树
        createTree(tree->lChild_);
        //创建右子树
        createTree(tree->rChild_);
    }

    return;
}

void printEle(BiTNode node)
{
    std::cout<<node.data_<<"\t";
}

/*
 * 递归的先序遍历二叉树
 */
void preTraverse(BiTre tree,void (*visited)(BiTNode node))
{
    if(nullptr==tree)
        return;

    visited(*tree);
    preTraverse(tree->lChild_,visited);
    preTraverse(tree->rChild_,visited);

}

/*
 * 递归的中序遍历二叉树
 */
void inorderTraverse(BiTre tree,void (*visited)(BiTNode node))
{
    if(nullptr==tree)
        return;

    inorderTraverse(tree->lChild_,visited);
    visited(*tree);
    inorderTraverse(tree->rChild_,visited);
}

///*
// * 递归的后序遍历二叉树
// */
//void inorderTraverse(BiTre tree,void (*visited)(BiTNode node))
//{
//    if(nullptr==tree)
//        return;

//    inorderTraverse(tree->lChild_,visited);
//    inorderTraverse(tree->rChild_,visited);
//    visited(*tree);
//}

/*
 * 向二叉树的节点中插入一个值为value的节点
 */
void insertANode2Tree(BiTre& tree,int value)
{
    BiTNode* newNode=new BiTNode(value);
    BiTre q=tree;
    //0、空树
    if(nullptr==q)
        q=newNode;

    //1、非空树,查找插入位置
    while(true)
    {
        //1-0 要插入的节点的值==当前节点的值,不做插入操作
        if(value==q->data_)
        {
            break;
        }
        //1-1 比当前节点的值小且左子树不为空,左子树中找
        else if(value<q->data_&&
                nullptr!=q->lChild_)
            q=q->lChild_;
        //1-2 比当前节点的值小且左子树为空,直接插入左子树,结束while loop
        else if(value<q->data_&&
                nullptr==q->lChild_)
        {
            q->lChild_=newNode;
            break;
        }
        //1-3 比当前节点的值大且右子树不为空,右子树中找
        else if(value>q->data_&&
                nullptr!=q->lChild_)
            q=q->rChild_;
        //1-4 比当前节点的值大且右子树为空,直接插入右子树,结束while loop
        else
        {
           q->rChild_=newNode;
           break;
        }
    }
    return;
}

/*
 * 从二叉树的中查找一个值为value的节点
 * 查找成功,返回指向值为value的节点的指针
 * 查找失败,返回空指针
 */
BiTNode* findANodeFromTree(BiTre& tree,int value)
{
    BiTNode* newNode=nullptr;
    BiTre q=tree;
    //0、空树
    if(nullptr==q)
        return newNode;

    //1、非空树,查找位置
    while(true)
    {
        //1-0 要插入的节点的值==当前节点的值 返回
        if(value==q->data_)
        {
            newNode=q;
            break;
        }
        //1-1 比当前节点的值小且左子树不为空,左子树中找
        else if(value<q->data_&&
                nullptr!=q->lChild_)
            q=q->lChild_;
        //1-2 比当前节点的值小且左子树为空,结束查找
        else if(value<q->data_&&
                nullptr==q->lChild_)
        {
            break;
        }
        //1-3 比当前节点的值大且右子树不为空,右子树中找
        else if(value>q->data_&&
                nullptr!=q->lChild_)
            q=q->rChild_;
        //1-4 比当前节点的值大且右子树为空,结束查找
        else
        {
           break;
        }
    }
    return newNode;
}

BiTNode* inOrderPost(BiTNode* p)
{
    BiTNode* pre=nullptr;
    //1、空树
    if(nullptr==p)
        return pre;
    //2、当前节点的右子树
    pre=p->rChild_;
    //3、走到右子树的最左端
    while(nullptr!=pre->lChild_)
        pre=pre->lChild_;
    return pre;
}

/**
 * @brief searchPre
 * 寻找一个节点的父母
 * @return 指向父母节点的指针
 */
BiTNode* searchPre(BiTre& tree,BiTNode& p)
{
    BiTNode* q=tree;
    if(nullptr!=q)
    {
        //0、找到了,q是p的父节点
        if(q->lChild_==&p||q->rChild_==&p)
            return q;
        //1、递归地在当前结点的左右子树中分别查找
        //1.2、当前结点q不是p的父母结点,递归地在当前结点的左子树中查找
        BiTNode* lRes=searchPre(q->lChild_,p);
        if(nullptr!=lRes)
            return lRes;

        //1.2、当前结点q不是p的父母结点且左子树中未找到
        //递归地在当前结点的右子树中查找
        BiTNode* rRes=searchPre(q->rChild_,p);
        if(nullptr!=rRes)
            return rRes;
    }
    //在tree中不存在结点p的父母结点
    return nullptr;
}

bool deleteNodeFromTree(BiTre& tree,int value)
{
    BiTre q=tree;
    //0、空树
    if(nullptr==q)
        return false;

    //1、非空树,查找位置
    while(true)
    {
        //1-0 要删除的节点的值==当前节点的值 删除当前结点
        if(value==q->data_)
        {
            //1-0-1、当前结点的左右子树均为空
            if(q->lChild_==nullptr&&q->rChild_==nullptr)
            {
                BiTNode* p=searchPre(tree,*q);
                //根结点没有父结点
                if(nullptr==p)
                {
                    p=q;
                    delete p;
                    p=nullptr;
                }
                else
                {
                    if(p->lChild_==q)
                    {
                        p->lChild_=nullptr;
                        delete q;
                        q=nullptr;
                    }
                    else
                    {
                        p->rChild_=nullptr;
                        delete q;
                        q=nullptr;
                    }
                }
            }
            //1-0-2、当前结点的右子树为空
            else if(q->lChild_!=nullptr&&q->rChild_==nullptr)
            {
                BiTNode* p=searchPre(tree,*q);
                //根结点没有父结点
                if(nullptr==p)
                {
                    p=q;
                    q=q->lChild_;
                    delete p;
                    p=nullptr;
                }
                else
                {
                    if(p->lChild_==q)
                    {
                        p->lChild_=q->lChild_;
                        delete q;
                        q=nullptr;
                    }
                    else
                    {
                        p->rChild_=q->rChild_;
                        delete q;
                        q=nullptr;
                    }
                }
            }
            //1-0-2、当前结点的左子树为空
            else if(q->lChild_==nullptr&&q->rChild_!=nullptr)
            {
                BiTNode* p=searchPre(tree,*q);
                //根结点没有父结点
                if(nullptr==p)
                {
                    p=q;
                    q=q->lChild_;
                    delete p;
                    p=nullptr;
                }
                else
                {
                    if(p->lChild_==q)
                    {
                        p->lChild_=q->rChild_;
                        delete q;
                        q=nullptr;
                    }
                    else
                    {
                        p->rChild_=q->lChild_;
                        delete q;
                        q=nullptr;
                    }
                }
            }
            else
            //当前结点的左右子树均不为空
            {
                //寻找q节点的后继p
                BiTNode* p=inOrderPost(q);
                q->data_=p->data_;
                BiTNode* pre=searchPre(tree,*q);
                pre->lChild_=q->rChild_;
                delete q;
                q=nullptr;
            }
            return true;
        }
        //1-1 比当前节点的值小且左子树不为空,左子树中找
        else if(value<q->data_&&
                nullptr!=q->lChild_)
            q=q->lChild_;
        //1-2 比当前节点的值小且左子树为空,结束查找
        else if(value<q->data_&&
                nullptr==q->lChild_)
        {
            break;
        }
        //1-3 比当前节点的值大且右子树不为空,右子树中找
        else if(value>q->data_&&
                nullptr!=q->lChild_)
            q=q->rChild_;
        //1-4 比当前节点的值大且右子树为空,结束查找
        else
        {
           break;
        }
    }
    return false;
}


    




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值