二叉树面试题(上)

头文件

typedef char BTDataType;

typedef struct BinTreeNode
{
    struct BinTreeNode* _pLeft;
    struct BinTreeNode* _pRight;
    BTDataType _data;
}BTNode, *PBTNode;


/////////////////////////////////////////////////////
void CreateBinTree(PBTNode* pRoot, BTDataType* array, int size, BTDataType invalid);
void _CreateBinTree(PBTNode* pRoot, BTDataType* array, int size, int* index, BTDataType invalid);//创建二叉树
PBTNode CopyBinTree(PBTNode pRoot);//拷贝二叉树

void PreOrder(PBTNode pRoot);//前序遍历
void PreOrderNor(PBTNode pRoot);
void InOrder(PBTNode pRoot);//中序遍历
void InOrderNor(PBTNode pRoot);
void PostOrder(PBTNode pRoot);//后序遍历
void PostOrder(PBTNode pRoot);
int Size(PBTNode pRoot);//二叉树的大小
int GetLeafCount(PBTNode pRoot);//叶子结点的个数
int GetKLevel(PBTNode pRoot, int K);//第k层的结点的个数
int Height(PBTNode pRoot);//二叉树的高度
void LevelOrder(PBTNode pRoot);//层序遍历二叉树
void Mirror(PBTNode pRoot);//二叉树的镜像
void Mirror_Nor(PBTNode pRoot);
int IsCompleteBinTree(PBTNode pRoot);//判断是否是完全二叉树
PBTNode Find(PBTNode pRoot, BTDataType data);//找一个点
int IsNodeInBinTree(PBTNode pRoot, PBTNode pNode);//判断一个点是否在二叉树上
PBTNode LeftChild(PBTNode pNode);
PBTNode RightChild(PBTNode pNode);
void DestroyBinTree(PBTNode* pRoot);//销毁二叉树
PBTNode BuyBinTreeNode(BTDataType data);

函数实现

#include <assert.h>
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include "BinTree.h"
#include "Queue.h"
#include "Stack.h"


PBTNode BuyBinTreeNode(BTDataType data)
{
    PBTNode pNewNode = (PBTNode)malloc(sizeof(BTNode));
    assert(pNewNode);
    pNewNode->_data = data;
    pNewNode->_pLeft = NULL;
    pNewNode->_pRight = NULL;

    return pNewNode;
}


///////////////////////////////////////////////////////
// BinTree.c
void _CreateBinTree(PBTNode* pRoot, BTDataType* array, int size, int* index, BTDataType invalid)//创建二叉树

{
    assert(index);//添加一个索引,方便遍历
    if (*index < size&&invalid != array[*index])
    {
        //先创建根节点
        *pRoot = BuyBinTreeNode(array[*index]);
        //创建左子树
        ++(*index);
        _CreateBinTree(&(*pRoot)->_pLeft, array, size, index, invalid);
        //创建右子树
        ++(*index);
        _CreateBinTree(&(*pRoot)->_pRight, array, size, index, invalid);
}
}




void CreateBinTree(PBTNode* pRoot, BTDataType* array, int size, BTDataType invalid)
{
    int index = 0;
    _CreateBinTree(pRoot, array, size, &index, invalid);
}

PBTNode CopyBinTree(PBTNode pRoot)//拷贝二叉树
{
    PBTNode pNewRoot = NULL;
    if(pRoot)
    {
        // 拷贝当前树的根节点
        pNewRoot = BuyBinTreeNode(pRoot->_data);

        // 拷贝当前树的左子树
        if(pRoot->_pLeft)
            pNewRoot->_pLeft = CopyBinTree(pRoot->_pLeft);

        // 拷贝当前树的右子树
        if(pRoot->_pRight)
            pNewRoot->_pRight = CopyBinTree(pRoot->_pRight);
    }

    return pNewRoot;
}


// 根节点--->左子树--->右子树
void PreOrder(PBTNode pRoot)
{
    if(pRoot)
    {
        printf("%c  ", pRoot->_data);
        PreOrder(pRoot->_pLeft);
        PreOrder(pRoot->_pRight);
    }
}

// 中序:左子树--->根节点--->右子树
void InOrder(PBTNode pRoot)
{
    if(pRoot)
    {
        InOrder(pRoot->_pLeft);
        printf("%c  ", pRoot->_data);
        InOrder(pRoot->_pRight);
    }
}

// 左子树--->右子树--->根节点
void PostOrder(PBTNode pRoot)
{
    if(pRoot)
    {
        PostOrder(pRoot->_pLeft);
        PostOrder(pRoot->_pRight);
        printf("%c  ", pRoot->_data);
    }
}

void DestroyBinTree(PBTNode* pRoot)
{
    assert(pRoot);
    if(*pRoot)
    {
        DestroyBinTree(&(*pRoot)->_pLeft);
        DestroyBinTree(&(*pRoot)->_pRight);
        free(*pRoot);
        *pRoot = NULL;
    }
}

int Size(PBTNode pRoot)//二叉树的大小
{
    int leftSize = 0;
    int rightSize = 0;

    if(NULL == pRoot)
        return 0;

    leftSize = Size(pRoot->_pLeft);
    rightSize = Size(pRoot->_pRight);

    return leftSize+rightSize+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);
}

int Height(PBTNode pRoot)//高度
{
    int leftHeight = 0;
    int rightHeight = 0;
    if (NULL == pRoot)
        return 0;

    leftHeight = Height(pRoot->_pLeft);
    rightHeight = Height(pRoot->_pRight);

    return leftHeight>rightHeight? leftHeight+1:rightHeight+1;
}

int GetKLevel(PBTNode pRoot, int K)//深度
{
    if(NULL == pRoot || K <= 0)
        return 0;

    if(1 == K)
        return 1;

    return GetKLevel(pRoot->_pLeft, K-1)+GetKLevel(pRoot->_pRight, K-1);
}

void LevelOrder(PBTNode pRoot)//层序遍历二叉树
{
    Queue q;
    PBTNode pCur = NULL;
    if(NULL == pRoot)
        return;

    QueueInit(&q);
    QueuePush(&q, pRoot);//先将根结点放入队列中,

    while(!QueueEmpty(&q))
    {
        pCur = QueueFront(&q);//取队头

        printf("%c ", pCur->_data);//先是a,然后是b,然后是c

        if(pCur->_pLeft)
            QueuePush(&q, pCur->_pLeft);//b也放入到队列中

        if(pCur->_pRight)
            QueuePush(&q, pCur->_pRight);//c也放入到队列中

        QueuePop(&q);//出队列,先进先出
    }

    printf("\n");
    QueueDestroy(&q);
}

void Mirror(PBTNode pRoot)
{
    if(pRoot)
    {
        PBTNode p = pRoot->_pLeft;
        pRoot->_pLeft = pRoot->_pRight;
        pRoot->_pRight = p;

        Mirror(pRoot->_pLeft);
        Mirror(pRoot->_pRight);
    }
}

void Mirror_Nor(PBTNode pRoot)
{
    Queue q;
    if(NULL == pRoot)
        return;

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

    while(!QueueEmpty(&q))
    {
        PBTNode pCur = QueueFront(&q);
        PBTNode p = pCur->_pLeft;
        pCur->_pLeft = pCur->_pRight;
        pCur->_pRight = p;

        if(pCur->_pLeft)
            QueuePush(&q, pCur->_pLeft);

        if(pCur->_pRight)
            QueuePush(&q, pCur->_pRight);

        QueuePop(&q);
    }

    QueueDestroy(&q);
}

int IsCompleteBinTree(PBTNode pRoot)//是否为完全二叉树
{
    Queue q;
    int flag = 0;
    if(NULL == pRoot)
        return 1;

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

    while(!QueueEmpty(&q))
    {
        PBTNode pCur = QueueFront(&q);
        if(flag)
        {
            if(pCur->_pLeft || pCur->_pRight)//倒数第二层可能不是满的
                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);
    }

    return 1;
}

int IsNodeInBinTree(PBTNode pRoot, PBTNode pNode)//点是否在二叉树上
{
    int flag = 0;
    if(NULL == pRoot || NULL == pNode)//无结点
        return 0;

    if(pRoot == pNode)//结点为根节点
        return 1;

    if(flag = IsNodeInBinTree(pRoot->_pLeft, pNode))
        return flag;

    return IsNodeInBinTree(pRoot->_pRight, pNode);
}

PBTNode Find(PBTNode pRoot, BTDataType data)
{
    PBTNode pNode = NULL;
    if(NULL == pRoot)
        return NULL;

    if(pRoot->_data == data)//如果是根节点,则返回根
        return pRoot;

    if(pNode = Find(pRoot->_pLeft, data))/
        return pNode;

    return Find(pRoot->_pRight, data);
}

void PreOrderNor(PBTNode pRoot)//根,左,右
{
#if 0
    Stack s;
    if(NULL == pRoot)
        return;

    StackInit(&s);
    StackPush(&s, pRoot);//将根节点压入栈中

    while(!StackEmpty(&s))
    {
        PBTNode pCur = StackTop(&s);//取栈顶元素
        printf("%c ", pCur->_data);//打印
        StackPop(&s);//让栈顶元素出栈

        if(pCur->_pRight)//先压入右结点
            StackPush(&s, pCur->_pRight);

        if(pCur->_pLeft)//再压入左结点
            StackPush(&s, pCur->_pLeft);
    }

    printf("\n");
#endif

    Stack s;
    if(NULL == pRoot)
        return;

    StackInit(&s);
    StackPush(&s, pRoot);

    while(!StackEmpty(&s))
    {
        PBTNode pCur = StackTop(&s);
        StackPop(&s);
        while(pCur)
        {
            printf("%c ", pCur->_data);
            if(pCur->_pRight)
                StackPush(&s, pCur->_pRight);

            pCur = pCur->_pLeft;
        }
    }

    printf("\n");
}

void InOrderNor(PBTNode pRoot)//中序遍历,用栈,左中右
{
    Stack s;
    PBTNode pCur = pRoot;
    if(NULL == pRoot)
        return;

    StackInit(&s);

    while(pCur || !StackEmpty(&s))
    {
        // 1. 找当前树中最左侧的结点并保存所经路径中的所有节点
        while(pCur)
        {
            StackPush(&s, pCur);
            pCur = pCur->_pLeft;
        }

        pCur = StackTop(&s);
        printf("%c ", pCur->_data);
        StackPop(&s);

        pCur = pCur->_pRight;
    }

    printf("\n");
}


void PostOrderNor(PBTNode pRoot)//左右中
{
    Stack s;
    PBTNode pCur = pRoot;
    PBTNode pTop = NULL;

    // 记录最近访问过的结点
    PBTNode pPrev = NULL;  

    if(NULL == pRoot)
        return;

    StackInit(&s);

    while(pCur || !StackEmpty(&s))
    {
        while(pCur)
        {
            StackPush(&s, pCur);
            pCur = pCur->_pLeft;
        }

        pTop = StackTop(&s);
        if(NULL == pTop->_pRight || pTop->_pRight == pPrev)//此处如果不判断,会重复遍根的右结点位置
            //在此处因为a 的右边不为空,所以先不打印a
        {
            printf("%c ", pTop->_data);
            pPrev = pTop;
            StackPop(&s);
        }
        else
            pCur = pTop->_pRight;
    }
}

PBTNode LeftChild(PBTNode pNode)
{
    return (NULL == pNode)? NULL:pNode->_pLeft;
}

PBTNode RightChild(PBTNode pNode)
{
    return (NULL == pNode)? NULL:pNode->_pRight;
}

猜你喜欢

转载自blog.csdn.net/Ning_zhi_t/article/details/81783350