二叉树的经典面试题

二叉树的基本操作
二叉树的遍历(前/中/后/层,递归&非递归)
代码中用到的栈
代码中用到的队列
面试题
  1. 拷贝二叉树
  2. 判断一棵二叉树是否是完全二叉树
  3. 二叉树的镜像递归
  4. 二叉树的镜像非递归
  5. 求二叉树中结点的个数
  6. 获取二叉树中叶子结点的个数
  7. 求二叉树中K层结点的个数
  8. 求二叉树的高度
  9. 查找值为data的结点
  10. 判断一个结点是否在二叉树里

1、拷贝二叉树
  • 利用递归,依次拷贝根结点,左子树,右子树
  • 代码如下
PBTNode CopyBinTree(PBTNode pRoot)
{
    PBTNode pNewRoot = NULL;
    if (NULL == pRoot)
        return NULL;
    else
    {
        //拷贝根结点
        pNewRoot = BuyBinTreeNode(pRoot->_data);

        //拷贝左子树
        pNewRoot->pLeft = CopyBinTree(pRoot->pLeft);

        //拷贝右子树
        pNewRoot->pRight = CopyBinTree(pRoot->pRight);      
    }

    return pNewRoot;
}

2、判断一棵二叉树是否是完全二叉树
  • 如果二叉树为空,则返回1(空二叉树也是完全二叉树)
  • 如果二叉树没有左右子树,则返回1
  • 二叉树为完全二叉树时有以下几种情况:

这里写图片描述
- 代码如下

int IsCompleteBinTreeNode(PBTNode pRoot)
{
    Queue q;
    PBTNode pCur = NULL;
    int flag = 0;

    if (NULL == pRoot)
        return 1;
    if (NULL == pRoot->pLeft && NULL == pRoot->pRight)
        return 1;

    QueueInit(&q);
    QueuePush(&q, pRoot);

    while (!QueueEmpty(&q))
    {
        pCur = QueueFrontData(&q);

        if (flag)
        {
            if (pCur->pLeft != NULL || pCur->pRight != NULL)
                return 0;
        }
        else
        {
            if (pCur->pLeft && pCur->pRight)
            {
                QueuePush(&q, pCur->pLeft);
                QueuePush(&q, pCur->pRight);
                flag = 0;
            }
            else if (pCur->pLeft)
            {
                QueuePush(&q, pCur->pLeft);
                flag = 1;
            }
            else if (pCur->pRight)
            {
                return 0;
            }
            else
            {
                flag = 1;
            }
        }

        QueuePop(&q);
    }

    QueueDestory(&q);
    return 0;
}

3、二叉树的镜像递归
  • 如果二叉树为空,返回空
  • 如果二叉树不为空,求左子树和右子树的镜像,然后交换左子树和右子树
    -代码如下
void MirrorBinTree(PBTNode pRoot)
{
    if (NULL == pRoot)
        return;
    else
    {
        PBTNode pTemp = pRoot->pLeft;
        pRoot->pLeft = pRoot->pRight;
        pRoot->pRight = pTemp;

        MirrorBinTree(pRoot->pLeft);
        MirrorBinTree(pRoot->pRight);
    }

}

4、二叉树的镜像非递归
  • 利用队列,先将根结点入队,进入循环后,保存根结点,交换根结点的左右子树,如果左右子树存在,则入队 。最后再将根结点出队,依次类推,队列空时,镜像完成。

  • 别忘记销毁队列
    这里写图片描述

  • 代码如下
void MirrorBinTreeNor(PBTNode pRoot)
{
    Queue q;
    if (NULL == pRoot)
        return;

    QueueInit(&q);
    QueuePush(&q, pRoot);
    while (!QueueEmpty(&q))
    {
        PBTNode pCur = QueueFrontData(&q);
        PBTNode pTemp = pCur->pLeft;
        pCur->pLeft = pCur->pRight;
        pCur->pRight = pTemp;

        if (pCur->pLeft)
            QueuePush(&q, pCur->pLeft);
        if (pCur->pRight)
            QueuePush(&q, pCur->pRight);

        QueuePop(&q);
    }

    QueueDestory(&q);
}

5、求二叉树中结点的个数
  • 如果二叉树为空,节点个数为0
  • 如果二叉树不为空,二叉树节点个数 = 左子树节点个数 + 右子树节点个数 + 1
  • 代码如下
int BinTreeSize(PBTNode pRoot)
{
    if (NULL == pRoot)
        return 0;

    return BinTreeSize(pRoot->pLeft) + BinTreeSize(pRoot->pLeft) + 1;
}

6、获取二叉树中叶子结点的个数
  • 如果二叉树为空,返回0
  • 如果二叉树不为空且左右子树为空,返回1
  • 代码如下
int GetLeafCount(PBTNode pRoot)
{
    if (NULL == pRoot)
        return 0;
    if (NULL == pRoot->pLeft&& NULL == pRoot->pRight)
        return 1;

    return GetLeafCount(pRoot->pLeft) + GetLeafCount(pRoot->pRight);
}

7、求二叉树中K层结点的个数
  • 求第K层结点个数时,就相当于求第K-1层的左子树结点和右子树结点的和
  • 代码如下
int GetKLevelNode(PBTNode pRoot, int K)
{
    if (K < 1 || NULL == pRoot)
        return 0;
    if (1 == K)
        return 1;

    return GetKLevelNode(pRoot->pLeft, K - 1) +
        GetKLevelNode(pRoot->pRight, K - 1);
}

8、求二叉树的高度
  • 求出左右子树的高度,然后比较左右子树那个高,那个高那个就是二叉树的高度
  • 代码如下
int Height(PBTNode pRoot)
{
    if (NULL == pRoot)
        return 0;

    int LeftHeight = Height(pRoot->pLeft);
    int RightHeight = Height(pRoot->pRight);

    return LeftHeight > RightHeight ? LeftHeight + 1 : RightHeight + 1;
}
9 、查找值为data的结点
  • 如果为空而二叉树,则返回NULL
  • 如果根节点的值等于要找到值,直接返回根节点
  • 依次遍历左子树和右子树,找到则返回
PBTNode FindNode(PBTNode pRoot, BTDataType data)
{
    PBTNode pNode = NULL;

    if (NULL == pRoot)
        return NULL;    

    if (pRoot->_data == data)
        return pRoot;

    if (pNode == FindNode(pRoot->pLeft, data))
        return pNode;

    return FindNode(pRoot->pRight, data);
}
  • 最后在遍历左子树,用了if语句,遍历右子树没有用,原因如下
    用if语句判断左子树找到了,则保存,并返回,如果没有if语句,要返回时只能在用return FindNode(pRoot->pLeft data)语句遍历一次返回节点; ,它不能向右子树那样直接返回,因为我遍历完左子树,如果没有找到,我还需要遍历右子树
10. 判断一个结点是否在二叉树里
  • 如果为空而二叉树,则返回0
  • 如果根节点的值等于要找到值,直接返回1
  • 依次遍历左子树和右子树,找到则返回1,否则返回0
int IsBinTreeNode(PBTNode pRoot, PBTNode pNode)
{
    int flag = 0;
    if (NULL == pRoot||NULL == pNode)
        return 0;
    if (pNode == pRoot)
        return 1;

    if (flag = IsBinTreeNode(pRoot->pLeft, pNode))
        return flag;

    return IsBinTreeNode(pRoot->pRight, pNode);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值