二叉树的基本操作和二叉树的面试题

BinTree.h

#pragma once
typedef char BTDataType;
typedef struct BinTreeNode
{
    struct BinTreeNode* _pLeft;
    struct BinTreeNode* _pRight;
    BTDataType _data;
}BTNode,*PBTNode;

#include<malloc.h>
#include<assert.h>
#include<stdio.h>
#include<string.h>
#include<LinkedStack.h>
#include<Queue.h>
PBTNode BuyBinTreeNode(BTDataType data)
{
    PBTNode pNewNode = (PBTNode)malloc(sizeof(BTNode));
    if(pNewNode == NULL)
    {
        assert(0);
        return NULL;
    }
    pNewNode->_pLeft = NULL;
    pNewNode->_pRight = NULL;
    return pNewNode;

}
void _CreateBinTree(PBTNode* pRoot,const BTDataType* array, int size,int* index,BTDataType invalid)
    //创建二叉树当他没有左子树或者右子树的时候用'#'代替
{
    assert(pRoot);
    assert(index);
    if(*index < size && array[*index] != invalid)
    //创建根节点
    *pRoot = BuyBinTreeNode(array[*index]);
    ++(*index);
    //创建根节点的左子树
    _CreateBinTree(&(*pRoot)->_pLeft,array,size,index,invalid);
    ++(*index);
    //创建根节点的右子树
    _CreateBinTree(&(*pRoot)->_pRight,array,size,index,invalid);

}
void PreOrder(PBTNode pRoot)//前序遍历(递归)
{
    if(pRoot)
    {
        printf("%c ",pRoot->_data);
        PreOrder(pRoot->_pLeft);//递归走左子树
        PreOrder(pRoot->_pRight);//递归走右子树
    }


}
void PreOrderNor(BTNode* pRoot)//前序遍历(非递归)
{
    LinkStack s;
    if(NULL == pRoot)
    return;
    InitStack(&s);
    PushStack(&s,pRoot);

    while(!StackEmpty(&s))
    {
        PBTNode pCur = GetTop(&s);
        printf("%c ",pCur->_data);
        PopStack(&s);
        if(pCur->_pRight)
            PushStack(&s,pCur->_pRight);
        if(pCur->_pLeft)
            PushStack(&s,pCur->_pLeft);

    }

}
void PostOrder(PBTNode pRoot)//后序遍历(递归)
{

    if(pRoot)
    {
        PostOrder(pRoot->_pLeft);//递归走左子树
        PostOrder(pRoot->_pRight);//递归走右子树
        printf("%c ",pRoot->_data);
    }
}

void PostOrderNor(BTNode* pRoot)//后序遍历(非递归)
{
    BTNode* pCur = pRoot;
    BTNode* pTop = NULL;
    BTNode* pPrev = NULL;//标记最近访问过的结点
    Stack s;
    if(NULL == pRoot)
        return;
    InitStack(&s);
    while(pCur || !StackEmpty(&s))
    {
        //找以pCur为根的树最左侧的结点,并保存所经过的所有结点。
    while(pCur)
    {
        PushStack(&s,pCur);//保存到栈中
        pCur = pCur->_pLeft;
    }
    pTop = GetTop(&s);//取栈顶元素
    if(pTop->_pRight == NULL || pPrev == pTop->_pRight)//如果右子树为空
    {
        printf("%c",pTop->_data);
        pPrev = pTop;
        PopStack(&s);//让栈顶元素出栈
    }
    else//如果右子树存在
        pCur = pTop->_pRight;
    }

}

void LevelOrder(PBTNode pRoot)//层序遍历
{
    Queue q;
    if(NULL == pRoot)
    return;
    QueueInit(&q);
    QueuePush(&q,pRoot);

    while(!QueueEmpty(&q))
    {
        PBTNode pCur = QueueFront(&q);
        printf("%c ",pCur->_data);
        QueuePop(&q);
        if(pCur->_pLeft)
            QueuePush(&q,pCur->_pLeft);
        if(pCur->_pRight)
            QueuePush(&q,pCur->_pRight);
        //QueuePop(&q);
    }

}
void InOrder(PBTNode pRoot)//中序遍历(递归)
{
    if(pRoot)
    {
        InOrder(pRoot->_pLeft);//递归走左子树
        printf("%c ",pRoot->_data);
        InOrder(pRoot->_pRight);//递归走右子树

    }

}
void InOrderNor(BTNode* pRoot)//中序遍历(非递归)
{
    BTNode* pCur = pRoot;
    Stack s;
    if(NULL == pRoot)
        return ;
    InitStack(&s);
    while(pCur || !StackEmpty(&s))
    {
        //找以pCur为根最左侧的结点,并保存路径中所遇到的所有的结点
    while(pCur)
    {
        PushStack(&s,pCur);
        pCur = pCur->_pLeft;
    }
    pCur = GetTop(&s);
    printf("%c",pCur->_data);
    PopStack(&s);
    pCur = pCur->_pRight;

    }

}


void CreateBinTree(PBTNode* pRoot,const 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(pNewRoot->_pLeft)
            pNewRoot->_pLeft = CopyBinTree(pRoot->_pLeft);
        //拷贝根节点的右子树
        if(pNewRoot->_pRight)
            pNewRoot->_pRight = CopyBinTree(pRoot->_pRight);
    }
    return pNewRoot;

}
void DestroyBinTree(PBTNode *pRoot)//销毁树 用后序遍历
{
    assert(pRoot);
    if(*pRoot)
    {
        DestroyBinTree(&(*pRoot)->_pLeft);//销毁左子树
        DestroyBinTree(&(*pRoot)->_pRight);//销毁右子树
        free(*pRoot);
        *pRoot = NULL;
    }

}
void Swap(PBTNode* pLeft,PBTNode* pRight)
{   
    PBTNode pTemp = NULL;
    assert(pLeft);
    assert(pRight);

    pTemp = *pLeft;
    *pLeft = *pRight;
    *pRight = pTemp;

}
void MirrorBinTree(PBTNode pRoot)//二叉树的镜像递归
{
    if(pRoot)
    {
        Swap(&pRoot->_pLeft,&pRoot->_pRight);
        MirrorBinTree(pRoot->_pLeft);
        MirrorBinTree(pRoot->_pRight);
    }


}
void MirrorBinTreeNor(PBTNode pRoot)//二叉树的镜像非递归(层序遍历解决)
{
    Queue q;
    if(NULL == pRoot)
        return;
    QueueInit(&q);
    QueuePush(&q,pRoot);
    while(!QueueEmpty(&q))
    {
        PBTNode pCur = QueueFront(&q);
        Swap(&pCur->_pLeft,&pCur->_pRight);
        if(pCur->_pLeft)
            QueuePush(&q,pCur->_pLeft);
        if(pCur->_pRight)
            QueuePush(&q,pCur->_pRight);
        QueuePop(&q);
    }


}
int BinTreeSize(PBTNode pRoot)// 求二叉树中结点的个数
{
    if(NULL == pRoot)
        return 0;
    return  BinTreeSize(pRoot->_pLeft)+BinTreeSize(pRoot->_pRight)+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, rightHeight;
    if(NULL == pRoot)
        return 0;
    leftHeight = Height(pRoot->_pLeft);
    rightHeight = Height(pRoot->_pRight);
    return leftHeight > rightHeight? leftHeight + 1:rightHeight + 1;

}

int GetKLevelNode(PBTNode pRoot, int K)// 求二叉树中K层结点的个数
{

    if(NULL == pRoot || K < 1)
        return 0;
    if(K == 1)
        return 1;
    return GetKLevelNode(pRoot->_pLeft,K-1)+GetKLevelNode(pRoot->_pRight,K-1);

}
BTNode*  Find(BTNode* pRoot,BTDataType data)//在二叉树中找数据
{
    BTNode* pRet = NULL;
    if(NULL == pRoot)
        return NULL;
    if(data == pRoot->_data)
        return pRoot;
    if(pRet = Find(pRoot->_pLeft,data))
        return pRet;
    return Find(pRoot->_pRight,data);

}

int IsNodeInBinTree(BTNode* pRoot,BTNode* pNode)//判断一个节点是否在一颗二叉树中
{
    int ret = 0;
    if(NULL == pRoot|| NULL == pNode)//判断树是不是空的或者节点没有给
        return 0;
    if(pRoot == pNode)//看一下节点是不是根
        return 1;
    if(ret = IsNodeInBinTree(pRoot->_pLeft,pNode) )
        return ret;
    return IsNodeInBinTree(pRoot->_pRight,pNode);
}
 int IsCompleteBinTree(BTNode* pRoot)//判断一个二叉树是不是完全二叉树
 {
     //用层序遍历去找
     Queue q;
     int flag = 0;
     if(NULL == pRoot)//空数是完全二叉树
         return 1;
    QueueInit(&q);//初始化队列
    QueuePush(&q,pRoot)//把根节点放到队列
    while(!QueueEmpty(&q))//当队列不为空时
    {

        //取头交给pCur
        BinTreeNode* 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);

        }
        else if(pCur->_pLeft)//左孩子存在右孩子不存在
        {
            QueuePush(&q,pCur->_pLeft);
            flag = 1;
        }
        else if(pCur->_pRight)//右孩子存在,左孩子不存在.肯定不是完全二叉树
        {

            return 0;
        }
        else
            flag = 1;//说明是叶子节点

        }
        QueuePop(&q);
    }
    return 1;

 }
void TestBinTree()
{
    const char* str = "ABD###CE##F";
    PBTNode pRoot = NULL;
    PBTNode pNewTree = NULL;
    CreateBinTree(&pRoot, str, strlen(str),'#');

    if(IsCompleteBinTree(pRoot))
        printf("是完全二叉树!\n");
    else
        printf("不是完全二叉树!\n");


    printf("PreOrder: ");//前序遍历
    PreOrder(pRoot);
    printf("\n");

    MirrorBinTree(pRoot);
    MirrorBinTreeNor(pRoot);

    printf("PreOrder: ");//前序遍历
    PreOrder(pRoot);
    printf("\n"); 


    printf("PreOrder: ");//前序遍历(非递归)
    PreOrderNor (pRoot);
    printf("\n");


    printf("InOrder: ");//中序遍历(递归)
    InOrder(pRoot);
    printf("\n");

    printf("InOrderNor: ");//中序遍历(非递归)
    InOrderNor(pRoot);
    printf("\n");

    printf("PostOrder: ");//后续遍历
    PostOrder(pRoot);
    printf("\n");

    printf("PostOrderNor: ");//后续遍历(非递归)
    PostOrderNor(pRoot);
    printf("\n");

    pNewTree = CopyBinTree(pRoot);
    printf("PreOrder: ");
    PreOrder(pNewTree);
    printf("\n");

    printf("二叉树中节点的个数为:%d\n",BinTreeSize(pRoot));
    printf("二叉树中叶子节点的个数为:%d\n",GetLeafCount(pRoot));
    printf("二叉树的高度:%d\n",Height(pRoot));
    printf("二叉树中第三层节点的个数:%d\n",GetKLevelNode(pRoot,3));


    DestroyBinTree(&pRoot);
    DestroyBinTree(&pNewTree);

}

Test.c

#include"BinTree.h"
int main()
{
    TestBinTree();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41112517/article/details/80293550