普通链式二叉树(2)

普通链式二叉树(2)

实现代码:

因为其中一部分要使用到队列来实现层序遍历,所以要用到队列的代码

Queue.h

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

typedef struct BinaryTreeNode* QDateType;

typedef struct QueueNode
{
    struct QueueNode* next;
    QDateType date;
}QNode;

typedef struct Queue
{
    QNode * head;
    QNode * tail;
    int size;
}Que;

//队列初始化
void QueueInit(Que* pq);
//队列销毁
void QueueDestroy(Que* pq);

//入队(尾部插入数据)
void QueuePush(Que* pq,QDateType x);
//出队(头部删除数据)
void QueuePop(Que* pq);

//获得队头节点的值
QDateType QueueFront(Que* pq);
//获得队尾节点的值
QDateType QueueBack(Que* pq);

//判断队列是否为空
bool QueueEmpty(Que* pq);
//获得队列的长度(有效元素个数)
int QueueSize(Que* pq);

Tree.h

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <math.h>

typedef char BTDataType;

typedef struct BinaryTreeNode
{
    BTDataType data;
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
}BTNode;



// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate1(BTDataType* a, int n, int* pi);
BTNode* BinaryTreeCreate2(BTDataType* a, int* pi);

// 二叉树销毁
void BinaryTreeDestroy1(BTNode** root);
void BinaryTreeDestroy2(BTNode* root);

// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);

// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);


// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root);

Queue.c

#include "Queue.h"

//队列初始化
void QueueInit(Que* pq)
{
    assert(pq);

    pq->head=pq->tail=NULL;
    pq->size=0;
}
//队列销毁
void QueueDestroy(Que* pq)
{
    assert(pq);
    QNode* cur=pq->head;
    while(cur)
    {
        QNode *next=cur->next;
        free(cur);
        cur=next;
    }

    pq->head=pq->tail=NULL;
    pq->size=0;
}

//入队(尾部插入数据)
void QueuePush(Que* pq,QDateType x)
{
    assert(pq);

    QNode *newnode=(QNode*) malloc(sizeof (QNode));
    if(newnode==NULL)
    {
        perror("malloc failed");
        exit(-1);
    }

    newnode->next=NULL;
    newnode->date=x;

    if(pq->tail==NULL)
    {
        pq->head=pq->tail=newnode;
    }
    else
    {
        pq->tail->next=newnode;
        pq->tail=newnode;
    }

    pq->size++;
}
//出队(头部删除数据)
void QueuePop(Que* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));

    if(pq->head->next==NULL)
    {
        free(pq->head);
        pq->head=pq->tail=NULL;
    }
    else
    {
        QNode *next=pq->head->next;
        free(pq->head);
        pq->head=next;
    }

    pq->size--;

}

//获得队头节点的值
QDateType QueueFront(Que* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));

    return pq->head->date;
}
//获得队尾节点的值
QDateType QueueBack(Que* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));

    return pq->tail->date;
}

//判断队列是否为空
bool QueueEmpty(Que* pq)
{
    assert(pq);

    return pq->head==NULL;
}
//获得队列的长度(有效元素个数)
int QueueSize(Que* pq)
{
    assert(pq);

    return pq->size;
}

Tree.c

#include "Tree.h"
#include "Queue.h"

 //通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate1(BTDataType* a, int n, int* pi)
{
    if(a[(*pi)]=='#')
    {
        (*pi)++;
        return NULL;
    }
    BTNode * root=(BTNode *) malloc(sizeof(BTNode));
    root->data=a[(*pi)++];
    root->left= BinaryTreeCreate1(a,n,pi);
    root->right= BinaryTreeCreate1(a,n,pi);

    return root;
}

BTNode* BinaryTreeCreate2(BTDataType* a, int* pi)
{
    if(a[(*pi)]=='#')
    {
        (*pi)++;
        return NULL;
    }
    BTNode * root=(BTNode *) malloc(sizeof(BTNode));
    root->data=a[(*pi)++];
    root->left= BinaryTreeCreate2(a,pi);
    root->right= BinaryTreeCreate2(a,pi);

    return root;
}


// 二叉树销毁
void BinaryTreeDestroy1(BTNode** root)
{
    if(*root==NULL)
        return ;

    BinaryTreeDestroy1((*root)->left);
    BinaryTreeDestroy1((*root)->right);

    free(*root);
    *root=NULL;
}
void BinaryTreeDestroy2(BTNode* root)
{
    if(root==NULL)
        return ;

    BinaryTreeDestroy2(root->left);
    BinaryTreeDestroy2(root->right);

    free(root);
    //*root=NULL;
    //在main函数调用完这个函数之后手动将root置空
}


// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
    return root==NULL ? 0
    : BinaryTreeSize(root->left)
    + BinaryTreeSize(root->right)+1;
}
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
    if(root==NULL)
        return 0;
    if(root->right==NULL && root->left==NULL)
        return 1;
    return BinaryTreeLeafSize(root->left)+ BinaryTreeLeafSize(root->right);
}
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
    assert(k>0);
    if(root==NULL)
        return 0;
    if(k==1)
        return 1;
    return BinaryTreeLevelKSize(root->left,k-1)+
           BinaryTreeLevelKSize(root->right,k-1);
}
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
    if(root==NULL)
        return NULL;

    if(root->data==x)
        return root;

    BTNode *ret=NULL;

    ret= BinaryTreeFind(root->left,x);
    if(ret!=NULL)
        return ret;

    ret= BinaryTreeFind(root->right,x);
    if(ret!=NULL)
        return ret;

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

    printf("%c",root->data);
    BinaryTreePrevOrder(root->left);
    BinaryTreePrevOrder(root->right);

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

    BinaryTreeInOrder(root->left);
    printf("%c",root->data);
    BinaryTreeInOrder(root->right);

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

    BinaryTreePostOrder(root->left);
    BinaryTreePostOrder(root->right);
    printf("%c",root->data);

}
// 通过队列进行层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
    Que q;
    QueueInit(&q);

    if(root)
        QueuePush(&q,root);

    while(!QueueEmpty(&q))
    {
        BTNode *front= QueueFront(&q);
        printf("%c ",front->data);

        if(front->left)
            QueuePush(&q,front->left);
        if(front->right)
            QueuePush(&q,front->right);

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

    QueueDestroy(&q);
}

//求树的高度
int BinaryTreeHeight(BTNode* root)
{
    if(root==NULL)
        return 0;

    int leftHeight= BinaryTreeHeight(root->left);
    int rightHeight= BinaryTreeHeight(root->right);

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

    //也可以只用下面这句
    //return fmax(BinaryTreeHeight(root->left), BinaryTreeHeight(root->right))+1;
}

// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
    Que q;
    QueueInit(&q);

    if(root)
        QueuePush(&q,root);

    while(!QueueEmpty(&q))
    {
        BTNode *front= QueueFront(&q);
        if(front==NULL)
            break;

        QueuePush(&q,front->left);

        QueuePush(&q,front->right);

        QueuePop(&q);
    }

    while (!QueueEmpty(&q))
    {
        BTNode *front= QueueFront(&q);
        QueuePop(&q);
        if(front!=NULL)
        {
            QueueDestroy(&q);
            return false;
        }
    }

    QueueDestroy(&q);
    return true;
}

补充:

以上代码中包含队列的代码,如对队列疑惑可以看我前面写的队列的博客。此外,以上代码中有部分知识,上一节已经讲过了,讲过的内容有:

(计算一颗树的节点个数)(计算一棵树的叶子节点的个数)(计算一棵树第k层节点个数)(前,中,后序遍历)

这些内容都在上一篇内容里面。

其次就是,这里树的节点存储的数据我设为了char类型,但是有些函数功能需要是int类型的,大家在Tree.h里的typedef char BTDataType;改成自己想要的类型就好了。

代码解析:

前序遍历数组,构建二叉树

(这个就是比较权威的建树手法了)

//通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate2(BTDataType* a, int* pi)
{
    if(a[(*pi)]=='#')
    {
        (*pi)++;
        return NULL;
    }
    BTNode * root=(BTNode *) malloc(sizeof(BTNode));
    root->data=a[(*pi)++];
    root->left= BinaryTreeCreate2(a,pi);
    root->right= BinaryTreeCreate2(a,pi);

    return root;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

销毁二叉树

// 二叉树销毁
void BinaryTreeDestroy1(BTNode** root)
{
    if(*root==NULL)
        return ;

    BinaryTreeDestroy1((*root)->left);
    BinaryTreeDestroy1((*root)->right);

    free(*root);
    *root=NULL;
}

void BinaryTreeDestroy2(BTNode* root)
{
    if(root==NULL)
        return ;

    BinaryTreeDestroy2(root->left);
    BinaryTreeDestroy2(root->right);

    free(root);
    //*root=NULL;
    //在main函数调用完这个函数之后手动将root置空
}

在这里插入图片描述

二叉树查找值为x的节点

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

    if(root->data==x)
        return root;

    BTNode *ret=NULL;

    ret= BinaryTreeFind(root->left,x);
    if(ret!=NULL)
        return ret;

    ret= BinaryTreeFind(root->right,x);
    if(ret!=NULL)
        return ret;

    return NULL;
}

在这里插入图片描述
在这里插入图片描述

求树的高度

//求树的高度
int BinaryTreeHeight(BTNode* root)
{
    if(root==NULL)
        return 0;

    int leftHeight= BinaryTreeHeight(root->left);
    int rightHeight= BinaryTreeHeight(root->right);

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

    //也可以只用下面这句,换掉前3句,也就是int leftHeight开始的3句就可以去掉。
    //return fmax(BinaryTreeHeight(root->left), BinaryTreeHeight(root->right))+1;
}

在这里插入图片描述
在这里插入图片描述

层序遍历

// 通过队列进行层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
    Que q;
    QueueInit(&q);

    if(root)
        QueuePush(&q,root);

    while(!QueueEmpty(&q))
    {
        BTNode *front= QueueFront(&q);
        printf("%c ",front->data);

        if(front->left)
            QueuePush(&q,front->left);
        if(front->right)
            QueuePush(&q,front->right);

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

    QueueDestroy(&q);
}

在这里插入图片描述
在这里插入图片描述

判断这个树是不是完全二叉树

// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
    Que q;
    QueueInit(&q);

    if(root)
        QueuePush(&q,root);

    while(!QueueEmpty(&q))
    {
        BTNode *front= QueueFront(&q);
        if(front==NULL)
            break;

        QueuePush(&q,front->left);

        QueuePush(&q,front->right);

        QueuePop(&q);
    }

    while (!QueueEmpty(&q))
    {
        BTNode *front= QueueFront(&q);
        QueuePop(&q);
        if(front!=NULL)
        {
            QueueDestroy(&q);
            return false;
        }
    }

    QueueDestroy(&q);
    return true;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值