数据结构——二叉树(C语言实现)

完全二叉树中节点度为1的最多有1个,没有左孩子就没有右孩子

树的结构定义是递归,任何一棵树都可以看成三部分,根和左子树,右子树

树不能构成回路或环以及孤立的点

二叉树不一定有两个子树,有可能为空

满二叉树必须是全满的,完全二叉树前K-1层都是满的,最后一层可以不满,但必须从左到右连续

顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。

若父亲节点是i,左孩子下标是2*i+1,右孩子下标是2*i+2。

若孩子下标是i,则父亲节点下标是(i-1)/2【向下取整】

二叉树的遍历分为:

前序(先根遍历,根->左子树->右子树:A B D N N E N N C N N,一般NULL不显示                 

中序(中根遍历,左子树->根->右子树:N D N B N E N A N C N)                                      

后序(后根遍历,左子树->右子树->根:N N D N N E B N N C A                                   

层序(A B C D E N N N N N N)从第一层到最后一层

前三个是深度优先遍历,最后一个是广度优先遍历,

判断是否为完全二叉树用层序(因为层序分成两段)

头文件及定义

#include<stdio.h>
#include<stdlib.h>

typedef char BTDataType;
typedef struct BinaryTreeNode//定义二叉树
{
    BTDataType _data;// 当前节点值域
    struct BinTreeNode* pLeft;   // 指向当前节点左孩子
    struct BinTreeNode* pRight; // 指向当前节点右孩子
}BTNode;

开辟新节点

BTNode* CreateNode(int x)//开辟节点
{
    BTNode* node = (BTNode*)malloc(sizeof(BTNode));
    node->_data = x;
    node->pLeft=NULL;
    node->pRight = NULL;
    return node;
}

二叉树前序遍历

void PrevOrder(BTNode* root)//二叉树前序遍历
{
    if (root == NULL)//如果是空树也打印一下
    {
        printf("NULL ");
        return;
    }

    printf("%c ", root->_data);
    PrevOrder(root->pLeft);
    PrevOrder(root->pRight);
}

二叉树中序遍历

void InOrder(BTNode* root)//二叉树中序遍历
{
    if (root == NULL)
    {
        printf("NULL ");
        return;
    }

   InOrder(root->pLeft);
   printf("%c ", root->_data);
   InOrder(root->pRight);
}

二叉树后序遍历

void PostOrder(BTNode* root)//二叉树后序遍历
{
    if (root == NULL)
    {
        printf("NULL ");
        return;
    }  

   PostOrder(root->pLeft);
   PostOrder(root->pRight);
   printf("%c ", root->_data);
}

二叉树层序遍历

int BinaryTreeLevelOrder(BTNode* root)//层序遍历,需要用到队列!
{
    Queue q;
    QueueInit(&q);
    if (root == NULL)
    {
        return;
    }
    QueuePush(&q, root);//先把二叉树的头节点放进队列

    while (!QueueEmpty(&q))//队列不为空,就出队头
    {
        BTNode* front = QueueFront(&q);
        QueuePop(&q);//Pop不是把数据删除,而是把它从队列中移除
        printf("%c ", front->_data);

        //不为空就把左右子树放进队列
        if (front->pLeft != NULL)
        {
            QueuePush(&q, front->pLeft);
        }
        if (front->pRight != NULL)
        {
            QueuePush(&q, front->pRight);
        }
    }
    QueueDestroy(&q);
    printf("\n");
}

判断一棵树是不是完全二叉树

//判断一棵树是不是完全二叉树,采用层序遍历,是返回1,不是返回0
int BinaryTreeComplete(BTNode* root)
{
    Queue q;
    QueueInit(&q);
    if (root == NULL)
    {
        return 1;//空树也是完全二叉树
    }
    QueuePush(&q, root);//先把二叉树的头节点放进队列

    while (!QueueEmpty(&q))//队列不为空,就出队头
    {
        BTNode* front = QueueFront(&q);
        QueuePop(&q);//Pop不是把数据删除,而是把它从队列中移除
        
        if (front == NULL)//若队列中出现空就跳出
        {
            break;
        }

        //把左右节点放进队列
        QueuePush(&q, front->pLeft);
        QueuePush(&q, front->pRight);
    }

    //只有当有效节点和NULL分成两段时才是完全二叉树
    //非完全二叉树在NULL的那一部分会出现有效节点
    while (!QueueEmpty(&q))
    {
        BTNode* front = QueueFront(&q);
        QueuePop(&q);

        if (front != NULL)
        {
           QueueDestroy(&q);
           return 0;
        }
    }
    QueueDestroy(&q);
    return 1;
}

求二叉树第K层节点个数

int BinanyTreeLevelKSize(BTNode* root, int k)//求二叉树第K层节点个数
{
    //当前树的第K层可以转换为左右子树的第K-1层,当层数等于1时就不需要分解
    if (root == NULL)
        return 0;

    else if (k == 1)
        return 1;

    return BinanyTreeLevelKSize(root->pLeft, k - 1) + 
           BinanyTreeLevelKSize(root->pRight, k - 1);
}

删除二叉树

void DestoryTree(BTNode* root)//删除二叉树
{
    if (root == NULL)
        return;

    //先销毁左右子树再销毁头节点
    DestoryTree(root->pLeft);
    DestoryTree(root->pRight);
    free(root);
}

查找二叉树中值为X的节点

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)//查找值为X的节点
{
    if (root == NULL)
        return 0;
    if (root == x)
        return root;

    //在左右子树查找
    BTDataType* node = BinaryTreeFind(root->pLeft, x);
    if (node == x)
    {
        return node;
    }

    node = BinaryTreeFind(root->pRight, x);
    if (node == x)
    {
        return node;
    }

    return NULL;//找不到返回空
}

计算二叉树中所有叶子节点个数

int TreeLeafSize(BTNode* root)//计算叶节点个数
{
    if (root == NULL)
    {
        return 0;
    }
    else if (root->pLeft == NULL && root->pRight == NULL)
    {
        return 1;
    }
    else
    {
        return TreeLeafSize(root->pLeft) + TreeLeafSize(root->pRight);
    }
}

计算二叉树中所有节点个数

int TreeSize(BTNode* root)//计算所有节点个数
{
    if (root == NULL)
    {
        return 0;
    }
    else
    {
        return 1 + TreeSize(root->pLeft) + TreeSize(root->pRight);
    }
}

  • 13
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值