二叉树面试题

学习感悟:学习二叉树这块函数递归用的特别多,递归就是代码可读性高,非常简单,但是却比较难想到,所以自己一定要在底下多想多画,多调试,搞清楚函数的调用过程。

注:以下代码所用到的二叉树及存储结构参考:https://blog.csdn.net/virgofarm/article/details/80231440

一:二叉树中序遍历非递归

void InOrderNor(PBTNode pRoot)
{
    Stack s;
    PBTNode pCur = pRoot;
    if (NULL == pRoot)
        return;

    //使用栈之前一定要初始化
    StackInit(&s);

    while (pCur || !StackEmpty(&s))
    {
        //先找到跟节点最左侧的节点并保存这条路径上的所有节点
        while (pCur)
        {
            StackPush(&s, pCur);
            pCur = pCur->_pLeft;
        }

        //到这,说明pCur为空,回退走到最左侧节点,遍历之后,再到右子树
        pCur = StackTop(&s);
        StackPop(&s);
        printf("%c ", pCur->_data);
        pCur = pCur->_pRight;
    }
}

二:二叉树后序遍历非递归

void PostOrderNor(PBTNode pRoot)
{
    Stack s;
    PBTNode pCur = pRoot;
    PBTNode pTop = NULL;
    PBTNode pPre = NULL;//用来保存最近一次遍历的节点
    if (NULL == pRoot)
        return;

    StackInit(&s);

    while (pCur || !StackEmpty(&s))
    {
        //先找到以pCur为跟节点的最左侧节点,并保存路径上所有的节点
        while (pCur)
        {
            StackPush(&s, pCur);
            pCur = pCur->_pLeft;
        }

        //
        pTop = StackTop(&s);

        //如果pTop没有右子树,或者右子树被遍历过了才能遍历跟节点
        if (!pTop->_pRight || pPre == pTop->_pRight)
        {
            StackPop(&s);
            printf("%c ", pTop->_data);
            pPre = pTop;
        }

        //如果pTop都被遍历过了,那么他的右子树一定被遍历过了,所以不用在朝右子树走
        else
            pCur = pTop->_pRight;
    }


}

三:判断一棵二叉树是否有数据为data的节点,并返回该节点

PBTNode IsExitData(PBTNode pRoot, BTDataType data)
{
    PBTNode pRet = NULL;
    if (NULL == pRoot)
        return NULL;

    //前序,从跟节点开始找
    if (pRoot->_data == data)
        return pRoot;

    //去左子树找
    if (pRet = IsExitData(pRoot->_pLeft, data))
        return pRet;

    //去右子树找
    return IsExitData(pRoot->_pRight, data);
}

四:判断一个节点是否在一棵二叉树中

int IsExitPBTNode(PBTNode pRoot, PBTNode Node)
{
    if (NULL == pRoot)
        return 0;

    //前序,从跟节点开始找
    if (pRoot == Node)
        return 1;

    //去左子树找
    if (IsExitPBTNode(pRoot->_pLeft, Node))
        return pRoot->_pLeft;

    //去右子树找
    return IsExitData(pRoot->_pRight, Node);
}

五:判断一棵二叉树是否是完全二叉树:层序遍历

int IsCompleteBTree(PBTNode pRoot)
{
    int flag = 0;//用来标记关键节点
    Queue q;
    PBTNode pCur = pRoot;

    //空树是完全二叉树
    if (NULL == pRoot)
        return 1;

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

    while (!QueueEmpty(&q))
    {
        pCur = QueueFront(&q);
        QueuePop(&q);

        //如果flag等于1,说明已经找到关键点,此时关键点之后的所有节点都必须是叶子节点
        if (flag == 1)
        {
            if (pCur->_pLeft || pCur->_pRight)
                return 0;
        }

        //先要找到那个关键节点,如果有左子树且有右子树,为正常节点
        else if (pCur->_pLeft && pCur->_pRight)
        {
            //左子树入队列
            QueuePush(&q, pCur->_pLeft);

            //右子树入队列
            QueuePush(&q, pCur->_pRight);
        }

        //如果只有左子树,就是关键节点,从这个节点之后的所有节点都不能有子树
        else if (pCur->_pLeft)
        {
            flag = 1;//标记位置为1

            //左子树入队列
            QueuePush(&q, pCur->_pLeft);
        }

        //如果只有右子树,就一定不是完全二叉树
        else if (pCur->_pRight)
            return 0;

        //如果既没有左子树也没有右子树,这个节点也是关键点
        else
            flag = 1;
    }
}

猜你喜欢

转载自blog.csdn.net/virgofarm/article/details/80253680