二叉树的操作和面试题

BinaryTree.h

#pragma once

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

typedef char BTDataType;

//树
typedef struct TreeNode
{
    BTDataType _data;
    struct TreeNode* _fristChild;
    struct TreeNode* _nextBrother;
}TreeNode;

//二叉树
typedef struct BTNode
{
    BTDataType _data;
    struct BTNode* _left;  //左孩子
    struct BTNode* _right;  //有孩子
}BTNode;

//创建二叉树
BTNode* CreateBTree(BTNode **ppRoot,BTDataType* arr, size_t *pIndex, BTDataType invalid, size_t len);
//创建一个节点
BTNode* BuyBTNode(BTDataType data);
//前序遍历递归
void BTreePrevOrderRV(BTNode *pRoot);
//中序遍历递归
void BTreeInOrderRV(BTNode *pRoot);
//后序遍历递归
void BTreePostOrderRV(BTNode *pRoot);
//层序遍历
void BTreeLevelOrder(BTNode *pRoot);
//拷贝二叉树
BTNode* CopyBinaryTree(BTNode *pRoot);
//求二叉树节点个数
size_t BinaryTreeSize(BTNode *pRoot);
//销毁二叉树
void BinaryTreeDestory(BTNode **pRoot);
//求叶子节点
size_t BinaryTreeLeafSize(BTNode *pRoot, size_t *count);
//二叉树的镜像(递归)
void BinaryTreeMirrorRV(BTNode *pRoot);
//二叉树的镜像(非递归)
void BinaryTreeMirror(BTNode *pRoot);
//求第k层的节点个数
size_t BinaryTreeKNode(BTNode *pRoot, int k);
//求二叉树的高度
size_t BinaryTreeHeight(BTNode *pRoot);
//判断是否是完全二叉树
int IsCompleteBinaryTree(BTNode *pRoot);
//找当前树中是否有data这个数
BTNode* FindDataBinaryTree(BTNode *pRoot, BTDataType data);
//找当前树中是否有这个节点
int FindNodeBinaryTree(BTNode *pRoot, BTNode *node);
//非递归前序遍历(方法一)
void BinaryTreePrevOrder1(BTNode *pRoot);
//非递归前序遍历(方法二)
void BinaryTreePrevOrder2(BTNode *pRoot);
//非递归的中序遍历
void BinaryTreeInOrder(BTNode *pRoot);
//后序非递归遍历
void BinaryTreePostOrder(BTNode *pRoot);

BinaryTree.c

#include"BinaryTree.h"
#include"Queue.h"

BTNode* BuyBTNode(BTDataType data)
{
    BTNode *newnode = (BTNode*)malloc(sizeof(BTNode));
    if (NULL == newnode)
    {
        assert(0);
        return NULL;
    }

    newnode->_data = data;
    newnode->_left = NULL;
    newnode->_right = NULL;

    return newnode;
}

//创建二叉树
BTNode* CreateBTree(BTNode **ppRoot, BTDataType* arr, size_t *pIndex, BTDataType invalid, size_t len)
{
    assert(ppRoot);
    if ((*pIndex < len) && (invalid != arr[*pIndex]))
    {
        //创建根节点
        *ppRoot = BuyBTNode(arr[*pIndex]);
        //创建左子树
        ++(*pIndex);
        (*ppRoot)->_left = CreateBTree(&((*ppRoot)->_left), arr, &(*pIndex), invalid, len);
        //创建右子树
        ++(*pIndex);
        (*ppRoot)->_right = CreateBTree(&((*ppRoot)->_right), arr, &(*pIndex), invalid, len);
    }

    return *ppRoot;
}

//前序遍历
void BTreePrevOrderRV(BTNode *pRoot)
{
    if (NULL == pRoot)
        return;

    printf("%c ", pRoot->_data);

    BTreePrevOrderRV(pRoot->_left);
    BTreePrevOrderRV(pRoot->_right);

}

//中序遍历
void BTreeInOrderRV(BTNode *pRoot)
{
    if (NULL == pRoot)
        return;

    BTreeInOrderRV(pRoot->_left);

    printf("%c ", pRoot->_data);

    BTreeInOrderRV(pRoot->_right);
}


//后序遍历
void BTreePostOrderRV(BTNode *pRoot)
{
    if (NULL == pRoot)
        return;

    BTreePostOrderRV(pRoot->_left);
    BTreePostOrderRV(pRoot->_right);

    printf("%c ", pRoot->_data);
}

//层序遍历
void BTreeLevelOrder(BTNode *pRoot)
{
    BTNode *cur = NULL;
    Queue q;
    QueueInit(&q);

    if (NULL == pRoot)
        return;

    //根节点入队列
    QueuePush(&q, pRoot);
    while (EmptyQueue(&q))
    {
        //先遍历根节点
        cur = QueueFront(&q);
        printf("%c ", cur->_data);
        //遍历完出队列
        QueuePop(&q);

        //左子树存在则遍历
        if (cur->_left)
            QueuePush(&q, cur->_left);

        //右子树存在则遍历
        if (cur->_right)
            QueuePush(&q, cur->_right);
    }

}


//拷贝二叉树
BTNode* CopyBinaryTree(BTNode *pRoot)
{
    BTNode *newtree = NULL;

    if (NULL == pRoot)
        return NULL;

    newtree = pRoot;
    newtree->_left = CopyBinaryTree(pRoot->_left);
    newtree->_right = CopyBinaryTree(pRoot->_right);

    return newtree;
}

size_t BinaryTreeSize(BTNode *pRoot)
{
    size_t left = 0;
    size_t right = 0;
    if (NULL == pRoot)
        return 0;

    //left = left + BinaryTreeSize(pRoot->_left);
    //right = right + BinaryTreeSize(pRoot->_right);

    //return left + right + 1;

    return BinaryTreeSize(pRoot->_left) + right + BinaryTreeSize(pRoot->_right) + 1;
}

//销毁二叉树
void BinaryTreeDestory(BTNode **pRoot) 
{
    assert(pRoot);

    if (*pRoot)  //如果树不为空
    {
        //销毁左子树
        BinaryTreeDestory(&(*pRoot)->_left);
        //销毁右子树
        BinaryTreeDestory(&(*pRoot)->_right);
        //销毁根
        free(*pRoot);
        *pRoot = NULL;
    }

}

//求叶子节点
size_t BinaryTreeLeafSize(BTNode *pRoot, size_t *count)
{
    if (NULL == pRoot)
        return 0;

    if (NULL == pRoot->_left && NULL == pRoot->_right)
        ++(*count);
    else
    {
        BinaryTreeLeafSize(pRoot->_left, &(*count));
        BinaryTreeLeafSize(pRoot->_right, &(*count));
    }

    return *count;
}

//交换函数
void Swap(BTNode **left, BTNode **right)
{
    BTNode *tmp = NULL;
    tmp = *left;
    *left = *right;
    *right = tmp;
}

//二叉树的镜像(前序递归) 
void BinaryTreeMirrorRV(BTNode *pRoot)
{
    if (NULL == pRoot)
        return;

    //先遍历根节点
    printf("%c ", pRoot->_data);

    //交换左右子树
    Swap(&(pRoot->_left), &(pRoot->_right));

    BinaryTreeMirrorRV(pRoot->_left);
    BinaryTreeMirrorRV(pRoot->_right);
}

//二叉树的镜像(层序非递归) 在层序遍历的时候交换左右节点
void BinaryTreeMirror(BTNode *pRoot)
{
    if (NULL == pRoot)
        return;

    Queue q;
    QueueInit(&q);

    //根入队
    QueuePush(&q, pRoot);

    while (EmptyQueue(&q))
    {
        //取队头元素
        BTNode *cur = QueueFront(&q);

        //遍历根节点
        printf("%c ", cur->_data);
        QueuePop(&q);

        if (cur->_left)
            QueuePush(&q, cur->_left);
        if (cur->_right)
            QueuePush(&q, cur->_right);

        //交换左右节点(无论是否存在)
        Swap(&(cur->_left), &(cur->_right));
    }
}

//求第k层的节点个数
size_t BinaryTreeKNode(BTNode *pRoot, int k)
{
    if (NULL == pRoot || k <= 0)
        return 0;

    if (1 == k)
        return 1;

    else
        return BinaryTreeKNode(pRoot->_left, k - 1) 
             + BinaryTreeKNode(pRoot->_right, k - 1);
}

//求二叉树的高度
size_t BinaryTreeHeight(BTNode *pRoot)
{
    if (NULL == pRoot)
        return 0;

    //优化,可以少递归将近一半
    if (NULL == pRoot->_left && NULL == pRoot->_right)
        return 1;

    return BinaryTreeHeight(pRoot->_left) > BinaryTreeHeight(pRoot->_right) ?
           BinaryTreeHeight(pRoot->_left) + 1 : BinaryTreeHeight(pRoot->_right) + 1;
}

//判断是否是完全二叉树
int IsCompleteBinaryTree(BTNode *pRoot)
{
    if (NULL == pRoot)
        return 0;

    Queue q;
    QueueInit(&q);
    BTNode *cur = NULL;

    int flag = 0;

    //根节点入队
    QueuePush(&q, pRoot);
    while (EmptyQueue(&q))
    {
        //取队头并出队
        cur = QueueFront(&q);
        QueuePop(&q);

        //临界点后面的节点一定没有孩子
        if (flag)
        {
            if (cur->_left || cur->_right)
                return 0;
        }
        else
        {
            if (cur->_left && cur->_right)
            {
                QueuePush(&q, cur->_left);
                QueuePush(&q, cur->_right);
            }
            else if (cur->_right)
                return 0;   //不是完全二叉树
            else if (cur->_left)
            {
                flag = 1;
                QueuePush(&q, cur->_left);
            }
            else
                flag = 1;
        }
    }

    return 1;
}

//找当前树中是否有data
BTNode* FindDataBinaryTree(BTNode *pRoot, BTDataType data)
{
    if (NULL == pRoot)
        return NULL;

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

    FindDataBinaryTree(pRoot->_left, data);
    FindDataBinaryTree(pRoot->_right, data);    
}

//找当前树中是否有这个节点
int FindNodeBinaryTree(BTNode *pRoot, BTNode *node)
{
    if (NULL == pRoot)
        return 0;

    if (node == pRoot)
        return 1;

    FindNodeBinaryTree(pRoot->_left, node);
    FindNodeBinaryTree(pRoot->_right, node);
}


//非递归的前序遍历(方法一)  和层次遍历的步骤一样
void BinaryTreePrevOrder1(BTNode *pRoot)
{
    if (NULL == pRoot)
        return;

    Stack s;
    StackInit(&s);
    //根入栈
    StackPush(&s, pRoot);

    while (EmptyStack(&s))
    {
        //遍历
        BTNode *cur = StackTop(&s);
        printf("%c ", cur->_data);
        //出栈
        StackPop(&s);

        //先让右孩子入栈
        if (cur->_right)
            StackPush(&s, cur->_right);
        //再让左孩子入栈
        if (cur->_left)
            StackPush(&s, cur->_left);
    }

}

//非递归前序遍历(方法二)
void BinaryTreePrevOrder2(BTNode *pRoot)
{
    if (NULL == pRoot)
        return;

    Stack s;
    StackInit(&s);
    //把根节点入栈
    StackPush(&s, pRoot);

    while (EmptyStack(&s))
    {
        //取栈顶元素并出栈
        BTNode *cur = StackTop(&s);
        StackPop(&s);

        while (cur)
        {
            //遍历栈顶节点
            printf("%c ", cur->_data);

            //如果该节点有右孩子就入栈
            if (cur->_right)
                StackPush(&s, cur->_right);
            //然后往左边走
            cur = cur->_left;
        }
    }
}

//非递归的中序遍历
void BinaryTreeInOrder(BTNode *pRoot)
{
    if (NULL == pRoot)
        return;

    Stack s;
    StackInit(&s);

    BTNode *cur = pRoot;
    //先找这棵树的最左边的节点,并保存这条路径上的所有节点
    while (cur || EmptyStack(&s))
    {
        while (cur)
        {
            StackPush(&s, cur);
            cur = cur->_left;
        }
        //去栈顶节点并遍历
        cur = StackTop(&s);
        printf("%c ", cur->_data);
        //出栈
        StackPop(&s);
        //再遍历右子树
        cur = cur->_right;
    }
}

//后序非递归遍历
void BinaryTreePostOrder(BTNode *pRoot)
{
    if (NULL == pRoot)
        return;

    Stack s;
    StackInit(&s);
    BTNode *cur = pRoot;
    BTNode *top = NULL;
    //用来标记前一个被遍历的节点
    BTNode *sign = NULL;  


    //找最左节点并保存路径中的所有节点
    while (cur || EmptyStack(&s))
    {
        while (cur)
        {
            StackPush(&s, cur);
            cur = cur->_left;
        }

        //取栈顶元素
        top = StackTop(&s);

        //如果该节点右子树为空或者右子树已经遍历过了则遍历这个节点,遍历完出栈
        if (NULL == top->_right || top->_right == sign)
        {
            printf("%c ", top->_data);
            //该节点已遍历则标记
            sign = top;
            StackPop(&s);

        }
        else
            cur = top->_right;

    }
}

test.c

#include"BinaryTree.h"
#include"Queue.h"

test1()
{
    BTNode *root;
    //BTNode *newTree;
    //BTDataType arr[] = "ABD##G##CE##F";
    BTDataType arr[] = "ABD###CE##F";

    size_t pIndex = 0;
    size_t len = strlen(arr);
    CreateBTree(&root, arr, &pIndex, '#', len);

    printf("递归前序遍历为: ");
    BTreePrevOrderRV(root);
    printf("\n");

    printf("非递归前序遍历为: ");
    BinaryTreePrevOrder1(root);
    printf("\n");

    printf("非递归前序遍历为: ");
    BinaryTreePrevOrder2(root);
    printf("\n");

    printf("递归中序遍历为: ");
    BTreeInOrderRV(root);
    printf("\n");

    printf("非递归中序遍历为: ");
    BinaryTreeInOrder(root);
    printf("\n");

    printf("递归后序遍历为: ");
    BTreePostOrderRV(root);
    printf("\n");

    printf("非递归后序遍历为: ");
    BinaryTreePostOrder(root);
    printf("\n");

    //newTree = CopyBinrayTree(root);
    //printf("前序遍历为: ");
    //BTreePrevOrderRV(newTree);
    //printf("\n");

    //printf("层序遍历为: ");
    //BTreeLevelOrder(root);
    //printf("\n");

    //printf("该树的节点个数为:%u\n", BinaryTreeSize(root));

    //size_t count = 0;
    //printf("该树的叶子个数为:%u\n", BinaryTreeLeafSize(root, &count));


    二叉树的镜像
    //printf("该二叉树的镜像二叉树为(前序递归):");
    //BinaryTreeMirrorRV(root);
    //printf("\n");

    //printf("该二叉树的镜像二叉树为(层序非递归):");
    //BinaryTreeMirror(root);
    //printf("\n");

    //printf("第K层的节点个数为:%u\n", BinaryTreeKNode(root, 3))

    //printf("该二叉树的高度为:%u\n", BinaryTreeHeight(root));

    //BinaryTreeDestory(&root);
    //printf("该树的节点个数为:%u\n", BinaryTreeSize(root));

    //printf("该树中是否有data: %p0x\n", FindDataBinaryTree(root, 'C'));

    //BTNode *node = FindDataBinaryTree(root, 'a');
    //printf("该树中是否有node: %d\n", FindNodeBinaryTree(root, node));

    //printf("判断该树是否是完全二叉树:%d\n", IsCompleteBinaryTree(root));
}


int main()
{
    test1();

    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值