二叉树再学习

本文详细介绍了二叉树的概念,包括其定义、常见面试题型以及二叉树节点和树的类定义。展示了创建、销毁、遍历、查找节点、获取叶子节点数量、计算树高、交换节点子树、判断节点存在及寻找最近公共祖先等操作的C++实现。此外,还提供了测试代码以验证这些操作的正确性。
摘要由CSDN通过智能技术生成

概述

一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。
二叉树作为树的一种,是一种重要的数据结构,二叉树中的面试题比较常见的题型大概有下面几个:创建一颗二叉树(先序,中序,后序)、遍历一颗二叉树(先序,中序,后序和层次遍历)、求二叉树中叶子节点的个数、求二叉树的高度、求二叉树中两个节点的最近公共祖先、打印和为某一值的全部路径、求某一节点是否在一个树中等等。

二叉树节点BinTreeNode:

 //二叉树节点
   class BinTreeNode
   {
    private:
        int data;
        BinTreeNode*left,*right;
    public:
      //构造函数用初始化列表进行初始化
        BinTreeNode(const int&item,BinTreeNode*lptr=NULL,BinTreeNode*rptr=NULL):data(item),left(lptr),right(rptr){};
        void set_data(int item)
        {
            data=item;
        }
        int get_data()const
        {
            return data;
        }
        void set_left(BinTreeNode*l)
        {
            left=l;
        }
        BinTreeNode*get_left()const
        {
            return left;
        }
        void set_right(BinTreeNode*r)
        {
            right=r;
        }
        BinTreeNode*get_right()const
        {
            return right;
        }
   };

二叉树:BinTree

class BinTree
{
private:
 BinTreeNode*root;
public:
 BinTree(BinTreeNode*t=NULL):root(t){};
 ~BinTree()
 {
     destroytree(root);
 }
 void destroytree(BinTreeNode*r);
 //设置根节点
 void set_root(BinTreeNode*t)
 {
     root=t;
 }
 //获取根节点
 BinTreeNode*get_root()const
 {
     return root;
 }
 //1.创建二叉树,返回根节点
 BinTreeNode*create_tree();
 //2.前序遍历
 void pre_order(BinTreeNode*r)const;
 //3.中序遍历
 void in_order(BinTreeNode*r)const;
 //4.后续遍历
 void past_order(BinTreeNode*r)const;
 //5.层次遍历
 void level_order(BinTreeNode*r)const;
 //6.获取叶子结点个数
 int get_leaf_num(BinTreeNode*r)const;
 //7.获得二叉树高度
 int get_tree_height(BinTreeNode*r)const;
 //8.交换二叉树的左右儿子
 void swap_left_right(BinTreeNode*r);
 //9.求两个节点pNode1和pNode2在以r为树根的树中的最近公共祖先
 BinTreeNode* get_nearest_common_father(BinTreeNode *r,BinTreeNode *pNode1,BinTreeNode *pNode2)const;
 //10.打印和为某一值的所有路径
 void print_rout(BinTreeNode *r,int sum)const;
 //11.判断一个节点t是否在以r为根的子树中
 bool is_in_tree(BinTreeNode *r,BinTreeNode *t)const;
};

创建二叉树

我们以#代替空指针
3 7 3 9 # # # 6 # # 1 # 5 # 4 # #
我们一递归的方式来创建二叉树
在这里插入图片描述

//创建二叉树,这里不妨使用前序创建二叉树,遇到‘#’表示节点为空
BinTreeNode*BinTree::create_tree()
{
    char item;
    BinTreeNode*t,*t_l,*t_r;
    cin>>item;
    if(item!='#')
    {
        BinTreeNode*pTmpNode=new BinTreeNode(item-48);
        t=pTmpNode;
        t_l=create_tree();
        t->set_left(t_l);
        t_r=create_tree();
        t->set_right(t_r);
        return t;
    }
    else 
    {
        t=NULL;
        return NULL;
    }
}

二叉树销毁

//销毁二叉树
void BinTree::destroytree(BinTreeNode*r)
{
     if(r==NULL)
         return;
     else
     {
         destroytree(r->get_left());
         destroytree(r->get_right());
         delete(r);
     }
}

先序/中序/后序遍历

遍历结果
先序遍历:3 7 3 9 6 1 5 4
中序遍历:9 3 7 6 3 1 5 4
后序遍历:9 3 6 7 4 5 1 3

void BinTree::pre_order(BinTreeNode*r)const
{
    BinTreeNode*ptmpNode=r;
    if(ptmpNode!=NULL)
    {
        cout<<ptmpNode->get_data()<<" ";
        pre_order(ptmpNode->get_left());
        pre_order(ptmpNode->get_right());
    }
}
void BinTree::in_order(BinTreeNode*r)const
{
    BinTreeNode*ptmpNode=r;
    if(ptmpNode!=NULL)
    {
        in_order(ptmpNode->get_left());
         cout<<ptmpNode->get_data()<<" ";
        in_order(ptmpNode->get_right());
    }
}
void BinTree::past_order(BinTreeNode*r)const
{
    BinTreeNode*ptmpNode=r;
    if(ptmpNode!=NULL)
    {
        past_order(ptmpNode->get_left());
        past_order(ptmpNode->get_right());
        cout<<ptmpNode->get_data()<<" ";
    }
}

层序遍历

采用一个广度优先搜索的方法
层序遍历:3 7 1 3 6 5 9 4

void BinTree::level_order(BinTreeNode*r)const
{   
    if(r==NULL)
        return ;
    deque<BinTreeNode*>q;
    q.push_back(r);
    while(!q.empty())
    {
        BinTreeNode*pTmpNode=q.front();
        cout<<pTmpNode->get_data()<<" ";
        q.pop_front();
        if(pTmpNode->get_left()!=NULL)
        {
            q.push_back(pTmpNode->get_left());
        }
        if(pTmpNode->get_right()!=NULL)
        {
            q.push_back(pTmpNode->get_right());
        }
    }
}

获得叶子节点个数

int BinTree::get_leaf_num(BinTreeNode*r)const
{
    if(r==NULL)
    {
        return 0;
    }
    if(r->get_left()==NULL&&r->get_right()==NULL)  //没有子结点
    {
        return 1;
    }
    return get_leaf_num(r->get_left())+get_leaf_num(r->get_right());
}

获取树的高度

int BinTree::get_tree_height(BinTreeNode*r)const
{
    if(r==NULL)
    return 0;
    if(r->get_left()==NULL&&r->get_right()==NULL)   //叶子节点
    {
        return 1;
    }
    int l_height=get_tree_height(r->get_left());
    int r_height=get_tree_height(r->get_right());
    return l_height>=r_height?l_height+1:r_height+1;
}

交换所有节点的左右孩子

void BinTree::swap_left_right(BinTreeNode*r)
{
    if(r==NULL)
    {
        return ;
    }
    BinTreeNode*pTmpNode=r->get_left();
    r->set_left(r->get_right());
    r->set_right(pTmpNode);
    swap_left_right(r->get_left());
    swap_left_right(r->get_right());
}

判断某节点是否在树上

bool BinTree::is_in_tree(BinTreeNode*r,BinTreeNode*t)const
{
    bool has=false;
    if(r==NULL)
    return false;
    else if(r==t)
    return true;
    else
    {
        if(r->get_left()!=NULL)
        {
            has=is_in_tree(r->get_left(),t);
        }
        if(!has&&r->get_right()!=NULL)
        {
            has=is_in_tree(r->get_right(),t);
        }
    }
    return has;
}

找最近的公共父节点

BinTreeNode* BinTree::get_nearest_common_father(BinTreeNode *r,BinTreeNode *pNode1,BinTreeNode *pNode2)const
{
    if(is_in_tree(pNode1,pNode2))
    {
        return pNode1;
    }
    if(is_in_tree(pNode2,pNode1))
    {
        return pNode2;
    }
    bool one_in_left,one_in_right,another_in_left,another_in_right;
    one_in_left=is_in_tree(r->get_left(),pNode1);
    another_in_right=is_in_tree(r->get_right(),pNode2);
    another_in_left=is_in_tree(r->get_left(),pNode2);
    one_in_right=is_in_tree(r->get_right(),pNode1);
    if((one_in_left&&another_in_right)||(one_in_right&&another_in_left))
    {
        return r;
    }
    else if(one_in_left&&another_in_left)
    {
        return get_nearest_common_father(r->get_left(),pNode1,pNode2);
    }
    else if(one_in_right&&another_in_right)
    {
        return get_nearest_common_father(r->get_right(),pNode1,pNode2);
    }
    else 
    {
        return NULL;
    }
}

打印和为某一值的所有路径

stack<BinTreeNode*>dfs_s;
stack<BinTreeNode*>print_s;
void BinTree ::print_rout(BinTreeNode*r,int sum)const
{
    if(r==NULL)
    return;
    sum-=r->get_data();
    dfs_s.push(r);
    if(sum<=0)
    {
        if(sum==0)
        {
            while(!dfs_s.empty())
            {
                print_s.push(dfs_s.top());
                dfs_s.pop();
            }
            while(!print_s.empty())
            {
                cout<<print_s.top()->get_data()<<" ";
                dfs_s.push(print_s.top());
                print_s.pop();
            }
            cout<<endl;
        }
        sum+=r->get_data();
        dfs_s.pop();
        return;
    }
    print_rout(r->get_left(),sum);
    print_rout(r->get_right(),sum);
    sum+=r->get_data();
    dfs_s.pop();
}

测试代码

#include"bintree.hpp"
using namespace bintree;
int main()
{
    BinTree tree;
    /*--------------------------------------------------------------------------*/
    cout<<"请输入二叉树前序序列进行建树,'#'代表空节点:"<<endl;
    tree.set_root(tree.create_tree());
    cout<<endl;
    /*--------------------------------------------------------------------------*/
    cout<<"前序遍历的结果:";
    tree.pre_order(tree.get_root());
    cout<<endl<<endl;
    /*--------------------------------------------------------------------------*/
    cout<<"中序遍历的结果:";
    tree.in_order(tree.get_root());
    cout<<endl<<endl;
    /*--------------------------------------------------------------------------*/
    cout<<"后序遍历的结果:";
    tree.past_order(tree.get_root());
    cout<<endl<<endl;
    /*--------------------------------------------------------------------------*/
    cout<<"层次遍历的结果:";
    tree.level_order(tree.get_root());
    cout<<endl<<endl;
    /*--------------------------------------------------------------------------*/
    cout<<"该二叉树叶子节点的个数:";
    cout<<tree.get_leaf_num(tree.get_root())<<endl<<endl;
    /*--------------------------------------------------------------------------*/
    cout<<"该二叉树的高度是:";
    cout<<tree.get_tree_height(tree.get_root())<<endl<<endl;
    /*--------------------------------------------------------------------------*/
    tree.swap_left_right(tree.get_root());
    cout<<"交换左右子树之后的先序遍历结果为:";
    tree.pre_order(tree.get_root());
    cout<<endl<<endl;
    /*--------------------------------------------------------------------------*/
    BinTreeNode *p1 = tree.get_root()->get_right()->get_left();
    BinTreeNode *p2 = tree.get_root()->get_left()->get_left();
    BinTreeNode *p3 = tree.get_root()->get_right()->get_right()->get_right();
    cout<<p1->get_data()<<" 和 "<<p2->get_data()<<"的最近公共祖先是:";
    BinTreeNode *p = tree.get_nearest_common_father(tree.get_root(),p1,p2);
    cout<<p->get_data()<<endl;
    cout<<p1->get_data()<<" 和 "<<p3->get_data()<<"的最近公共祖先是:";
    p = tree.get_nearest_common_father(tree.get_root(),p1,p3);
    cout<<p->get_data()<<endl<<endl;
    /*--------------------------------------------------------------------------*/
    cout<<"路径如下:"<<endl;
    tree.print_rout(tree.get_root(),13);
    return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

binary~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值