二叉树基本操作and面试题

代码实现


头文件

  • BinTree.h
#pragma once


#ifndef _BINTREE_H_
#define _BINTREE_H_

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 PostOrderNor(PBTNode pRoot);

// 求二叉树中结点的个数 
int Size(PBTNode pRoot);

// 求二叉树中叶子结点的个数 
int GetLeafCount(PBTNode pRoot);

// 获取第K层中结点个数 
int GetKLevel(PBTNode pRoot, int K);

// 获取二叉树的高度 
int Height(PBTNode pRoot);

// 二叉树层序遍历 
void LevelOrder(PBTNode pRoot);

// 二叉树镜像递归 
void Mirror(PBTNode pRoot);

// 二叉树镜像非递归 
void Mirror_Nor(PBTNode pRoot);

// 判断一棵树是否是完全二叉树 
int IsCompleteBinTree(PBTNode pRoot);

// 在二叉树中查找值为data的结点 
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);

#endif // !_BINTREE_H_
  • Stack.h
#pragma once
#include"BinTree.h"

#ifndef _STACK_H_
#define _STACK_H_

#define DataType PBTNode 
#define MAX_SIZE 10 

typedef struct Stack
{
    DataType _array[MAX_SIZE];
    int _size;
}Stack;

// 初始化栈 
void StackInit(Stack* s);

// 压栈 
void StackPush(Stack* s, DataType data);

// 出栈 
void StackPop(Stack* s);

// 获取栈顶元素 
DataType StackTop(Stack* s);

// 获取栈中元素个数 
int StackSize(Stack* s);

// 检测栈是否为空 
int StackEmpty(Stack* s);


#endif //_STACK_H_
  • Queue.h
#pragma once
#include"BinTree.h"

#ifndef _QUEUE_H_
#define _QUEUE_H_

#define DataType  PBTNode 
#define MAX_SIZE 10 

typedef struct 
{
    DataType _array[MAX_SIZE];
    int _size;
}Queue;

// 初始化队列 
void QueueInit(Queue* s);

// 入队列
void QueuePush(Queue* s, DataType data);

// 出队列
void QueuePop(Queue* s);

// 获取队头元素 
DataType QueueTop(Queue* s);

// 获取队列中元素个数 
int QueueSize(Queue* s);

// 检测队列是否为空 
int QueueEmpty(Queue* s);


#endif // !_QUEUE_H_

源文件

  • BinTree.c
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"BinTree.h"
#include"Stack.h"
#include"Queue.h"

// 创建二叉树
PBTNode BuyBinTreeNode(BTDataType data)
{
    PBTNode pRoot = NULL;
    pRoot = (PBTNode)malloc(sizeof(BTNode));
    assert(pRoot);

    pRoot->_data = data;
    pRoot->_pLeft = NULL;
    pRoot->_pRight = NULL;
    return pRoot;
}
void CreateBinTree(PBTNode* pRoot, BTDataType* array, int size, BTDataType invalid)
{
    int index = 0;
    _CreateBinTree(pRoot, array, size, &index, invalid);

}
void _CreateBinTree(PBTNode* pRoot, BTDataType* array, int size, int* index, BTDataType invalid)
{
    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);
    }
}

// 拷贝 
PBTNode CopyBinTree(PBTNode pRoot)
{
    PBTNode pNew = NULL;
    PBTNode pNew_Left = NULL;
    PBTNode pNew_Right = NULL;

    pNew = (PBTNode)malloc(sizeof(BTNode));
    if (pNew == NULL)
    {
        return NULL;
    }
    pNew->_data = pRoot->_data;

    if (pRoot->_pLeft != NULL)
    {
        pNew_Left = CopyBinTree(pRoot->_pLeft);
    }
    if (pRoot->_pRight != NULL)
    {
        pNew_Right = CopyBinTree(pRoot->_pRight);
    }

    pNew->_pLeft = pNew_Left;
    pNew->_pRight = pNew_Right;
    return pNew;
}
// 前序递归遍历 
void PreOrder(PBTNode pRoot)
{
    printf("%c ", pRoot->_data);

    if (pRoot->_pLeft)
        PreOrder(pRoot->_pLeft);
    if (pRoot->_pRight)
        PreOrder(pRoot->_pRight);
}
// 前序非递归 
void PreOrderNor(PBTNode pRoot)
{
    Stack stack;
    StackInit(&stack);
    PBTNode pCur = NULL;

    StackPush(&stack, pRoot);

    while (pCur || !StackEmpty(&stack))
    {
        pCur = StackTop(&stack);
        StackPop(&stack);

        if (pCur)
        {
            printf("%c ", pCur->_data);
            StackPush(&stack, pCur->_pRight);
            StackPush(&stack, pCur->_pLeft);
        }
    }

}
// 中序递归 
void InOrder(PBTNode pRoot)
{
    if (pRoot->_pLeft != NULL)
        InOrder(pRoot->_pLeft);

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

    if (pRoot->_pRight != NULL)
        InOrder(pRoot->_pRight);
}
// 中序非递归 
void InOrderNor(PBTNode pRoot)
{
    Stack stack;
    StackInit(&stack);
    PBTNode pCur = pRoot;
    while (pCur || !StackEmpty(&stack))
    {

        while (pCur)//将左边的节点全部入栈
        {
            StackPush(&stack, pCur);
            pCur = pCur->_pLeft;
        }

        pCur = StackTop(&stack);//读取目前最左边的节点
        StackPop(&stack);//出栈
        printf("%c ", pCur->_data);//访问当前节点

        pCur = pCur->_pRight;//开始读取右子树
    }
}

// 后续递归 
void PostOrder(PBTNode pRoot)
{
    if (pRoot->_pLeft != NULL)
        PostOrder(pRoot->_pLeft);

    if (pRoot->_pRight != NULL)
        PostOrder(pRoot->_pRight);

    printf("%c ", pRoot->_data);
}
// 后序非递归 
void PostOrderNor(PBTNode pRoot)
{
    Stack stack;
    StackInit(&stack);
    PBTNode pCur = pRoot;
    PBTNode pTop;
    PBTNode pPer=NULL;
    while (pCur || !StackEmpty(&stack))//节点全部读取完,且栈里面没有节点
    {
        while (pCur)//将左边的节点全部入栈
        {
            StackPush(&stack, pCur);
            pCur = pCur->_pLeft;
        }

        pTop = StackTop(&stack);//
        if (NULL == pTop->_pRight || pPer == pTop->_pRight)//判断是否有右子树,或者右子树已经被访问过
        {
            pPer = pTop;//记录当前节点,作为已访问的右子节点
            printf("%c ", pTop->_data);//没有右子树,或者右子树被访问过,输出当前节点
            StackPop(&stack);//出栈
        }
        else//如果右子树存在且没有访问
        {
            pCur = pTop->_pRight;//开始处理右子树
        }
    }   
}

// 求二叉树中结点的个数 
int Size(PBTNode pRoot)
{
    if (pRoot == NULL)
    {
        return 0;
    }
    return 1 + Size(pRoot->_pLeft) + Size(pRoot->_pRight);
}

// 求二叉树中叶子结点的个数 
int GetLeafCount(PBTNode pRoot)
{
    int count = 0;

    if (NULL == pRoot->_pLeft && NULL == pRoot->_pRight)
        count++;
    if (pRoot->_pLeft)
        count += GetLeafCount(pRoot->_pLeft);
    if(pRoot->_pRight)
        count+= GetLeafCount(pRoot->_pRight);
    return count;
}

// 获取第K层中结点个数 
int GetKLevel(PBTNode pRoot, int K)
{
    int count = 0;
    if (pRoot == NULL || K <= 0)
        return 0;
    if (K == 1 )
        return 1;
    count += GetKLevel(pRoot->_pLeft, K - 1);
    count += GetKLevel(pRoot->_pRight, K - 1);
    return count;
}
// 获取二叉树的高度 
int Height(PBTNode pRoot)
{
    if (pRoot == NULL)
        return 0;
    return Height(pRoot->_pLeft) > Height(pRoot->_pRight) ? Height(pRoot->_pLeft) + 1 : Height(pRoot->_pRight) + 1;
}

// 二叉树层序遍历 
void LevelOrder(PBTNode pRoot)
{
    Queue q;
    QueueInit(&q);
    PBTNode pCur = pRoot;
    QueuePush(&q, pRoot);

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

// 二叉树镜像递归 
void Mirror(PBTNode pRoot)
{
    PBTNode pLeft = NULL;
    PBTNode pRight = NULL;

    if (pRoot)
    {
        pLeft = pRoot->_pLeft;
        pRight = pRoot->_pRight;
        Mirror(pLeft);
        Mirror(pRight);
        pRoot->_pLeft = pRight;
        pRoot->_pRight = pLeft;
    }
}
// 二叉树镜像非递归 
void swap(PBTNode* pRoot)
{
    assert(*pRoot);
    PBTNode x = (*pRoot)->_pLeft;
    (*pRoot)->_pLeft = (*pRoot)->_pRight;
    (*pRoot)->_pRight = x;
}
void Mirror_Nor(PBTNode pRoot)
{
    PBTNode pCur = NULL;
    Queue q;
    QueueInit(&q);
    QueuePush(&q, pRoot);

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

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


}
// 判断一棵树是否是完全二叉树 
int IsCompleteBinTree(PBTNode pRoot)
{
    Queue q;
    QueueInit(&q);
    QueuePush(&q, pRoot);
    int Tag = 1;
    PBTNode pCur;

    while (!QueueEmpty(&q))
    {
        pCur = QueueTop(&q);
        QueuePop(&q);
        if (Tag)
        {
            if (pCur->_pLeft && pCur->_pRight)
            {
                QueuePush(&q, pCur->_pLeft);
                QueuePush(&q, pCur->_pRight);
            }
            else if (pCur->_pLeft && pCur->_pRight == NULL)
            {
                Tag = 0;
                QueuePush(&q, pCur->_pLeft);
            }
            else if (NULL == pCur->_pLeft && pCur->_pRight)
            {
                return 0;
            }
        }
        else
        {
            if (pCur->_pLeft || pCur->_pRight)
                return 0;
        }
    }
    return 1;
}

// 在二叉树中查找值为data的结点 
PBTNode Find(PBTNode pRoot, BTDataType data)
{
    //前序
    Stack s;
    StackInit(&s);
    StackPush(&s,pRoot);
    PBTNode pCur = NULL;

    while (pCur || !StackEmpty(&s))
    {
        pCur = StackTop(&s);
        StackPop(&s);
        if (pCur)
        {
            if (pCur->_data == data)
            {
                return pCur;
            }
            StackPush(&s, pCur->_pRight);
            StackPush(&s, pCur->_pLeft);
        }
    }
    return NULL;
}

 //判断一个节点是否在二叉树中前序非递归
int IsNodeInBinTree(PBTNode pRoot, PBTNode pNode)
{
    //前序
    Stack s;
    StackInit(&s);
    StackPush(&s, pRoot);
    PBTNode pCur = NULL;

    while (pCur || !StackEmpty(&s))
    {
        pCur = StackTop(&s);
        StackPop(&s);
        if (pCur)
        {
            if (pCur == pNode)
            {
                return 1;
            }
            StackPush(&s, pCur->_pRight);
            StackPush(&s, pCur->_pLeft);
        }
    }
    return 0;
}

// 获取当前节点的左孩子 
PBTNode LeftChild(PBTNode pNode)
{
    if (pNode)
        return pNode->_pLeft;
}

// 获取当前节点的右孩子 
PBTNode RightChild(PBTNode pNode)
{
    if (pNode)
        return pNode->_pRight;
}

//销毁二叉树-后续递归
void DestroyBinTree(PBTNode* pRoot)
{
    if ((*pRoot)->_pLeft)
        DestroyBinTree(&(*pRoot)->_pLeft);
    if ((*pRoot)->_pRight)
        DestroyBinTree(&(*pRoot)->_pRight);
    free(*pRoot);
}

///
//test
void test()
{
    char array[] = { 'A','B','D','#','#','#','C','E','#','#','F'};
    //char array[] = { '1','2','4','q','#','#','#','5','#','#','3','6','#','#','7' };
    PBTNode pRoot;
    PBTNode pBT;


    CreateBinTree(&pRoot, array, sizeof(array) / sizeof(array[0]), '#');
    pBT = CopyBinTree(pRoot);//拷贝

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

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

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

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


    printf("后续递归遍历:\t");
    PostOrder(pRoot);
    printf("\n");

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

    printf("节点总数:%d\n",Size(pRoot));

    // 求二叉树中叶子结点的个数 
    int count1 = GetLeafCount(pRoot);
    printf("叶子结点个数:%d\n", count1);

    // 获取第K层中结点个数 
    int count2 = GetKLevel(pRoot, 3);
    printf("第K层中结点个数: %d\n",count2);

    // 获取二叉树的高度 
    int H = Height(pRoot);
    printf("二叉树的高度: %d\n", H);

    // 二叉树层序遍历 
    printf("层序遍历:\t");
    LevelOrder(pRoot);
    printf("\n");

    // 二叉树镜像递归 
    Mirror(pRoot);
    printf("镜像递归 :\t");
    LevelOrder(pRoot);
    printf("\n");

    // 二叉树镜像递归 
    Mirror_Nor(pRoot);
    printf("镜像非递归 :\t");
    LevelOrder(pRoot);
    printf("\n");

    // 判断一棵树是否是完全二叉树 
    printf("否是完全二叉树:%d\n", IsCompleteBinTree(pRoot));

    // 在二叉树中查找值为data的结点 
    PBTNode F;
    F = Find(pRoot, 'E');
    printf("查找结果:");
    if (F)
        printf("%c\n", F->_data);
    else
        printf("无\n");

    // 判断一个节点是否在二叉树中 
    if (IsNodeInBinTree(pRoot, Find(pRoot, 'E')))
    {
        printf("存在\n");
    }

    //销毁二叉树-后续递归
    DestroyBinTree(&pRoot);
}
  • Stack.c
#include <assert.h>
#include <windows.h>
#include <stdio.h>
#include "Stack.h"

// 初始化栈 
void StackInit(Stack* s)
{
    assert(s);
    s->_size = 0;
}


// 压栈 
void StackPush(Stack* s, DataType data)
{
    assert(s);
    if (s->_size >= 10)
    {
        return;
    }
    else
    {
        s->_array[s->_size] = data;
        s->_size++;
    }
}

// 出栈 
void StackPop(Stack* s)
{
    assert(s);
    if (s->_size > 0)
    {
        s->_size--;
    }
}

// 获取栈顶元素 
DataType StackTop(Stack* s)
{
    if (s->_size > 0)
    {
        return s->_array[(s->_size) - 1];
    }
}

// 获取栈中元素个数 
int StackSize(Stack* s)
{
    return s->_size;
}

// 检测栈是否为空 
int StackEmpty(Stack* s)
{
    if (s->_size == 0)
    {
        return 1;
    }
    else return 0;
}

  • Queue.c
#include <assert.h>
#include <stdio.h>
#include "Queue.h"

// 初始化栈队列
void QueueInit(Queue* s)
{
    assert(s);
    s->_size = 0;
}


// 入队列
void QueuePush(Queue* s, DataType data)
{
    assert(s);
    if (s->_size >= 10)
    {
        return;
    }
    else
    {
        s->_array[s->_size] = data;
        s->_size++;
    }
}

// 出队列 
void QueuePop(Queue* s)
{
    assert(s);
    if (s->_size > 0)
    {
        s->_size--;
        for (int i = 0; i < s->_size; i++)
        {
            s->_array[i] = s->_array[i + 1];
        }
    }
}

// 获取队头元素
DataType QueueTop(Queue* s)
{
    if (s->_size > 0)
    {
        return s->_array[0];
    }
}

// 获取队列中元素个数 
int QueueSize(Queue* s)
{
    return s->_size;
}

// 检测队列是否为空 
int QueueEmpty(Queue* s)
{
    if (s->_size == 0)
    {
        return 1;
    }
    else return 0;
}
//打印队列
void QueuePrint(Queue* q)
{
    if (q->_size > 0 && q->_size < MAX_SIZE)
    {
        for (int i = 0; i < q->_size; i++)
        {
            printf("%c ", q->_array[i]);
        }
        printf("\n");
    }
}
  • test.c
#include<windows.h>

int main()
{
    test();

    system("pause");
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值