C语言二叉树的基本函数操作

本文档详细介绍了如何使用C语言实现二叉树的数据结构,包括节点定义、队列辅助的层次遍历、前序、中序和后序遍历,以及判断二叉树是否为完全二叉树的方法。
摘要由CSDN通过智能技术生成

BT.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef char BTDataType;
typedef struct BinaryTreeNode//二叉树节点
{
    BTDataType _data;
    struct BinaryTreeNode* _left;
    struct BinaryTreeNode* _right;
}BTNode;

typedef BTNode* QueueDataType;//队列节点存储二叉树节点地址,方便层序遍历
typedef struct queue//队列节点
{
    QueueDataType _data;
    struct queue* next;
}QNode;
typedef struct queueinfo//队列信息记录头尾,大小,传队列信息直接传这个结构体变量(信息找头尾)
{
    QNode* phead;
    QNode* ptail;
    int size;
}QInfo;

//初始化队列
void QueueInit(QInfo* queue);
// 销毁队列
void QueueDestory(QInfo* queue);
//搞个节点
QNode* QueueGetNode(QueueDataType data);
//队列插入数据
void QueueInsert(QInfo* queue, QueueDataType data);
// 队列头部删除数据,并获取它
QueueDataType QueuePop(QInfo* queue);
// 队列判空
int QueueIsEmpty(QInfo* queue);
// 队列大小
int QueueSize(QInfo* queue);
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, /*int n, */int* pi);
// 二叉树销毁
void BinaryTreeDestory(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);
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);

BT.c

#include"BT.h"
//初始化队列
void QueueInit(QInfo* queue)
{
//因为这个源码是实现二叉树的,用到队列只在一个函数内,所以采用非动态开辟内存方法,而是传入函数内创建好的,进行初始化,而非创建
    queue->phead = NULL;
    queue->ptail = NULL;
    queue->size = 0;
}
//销毁队列
void QueueDestory(QInfo* queue)
{
    while (queue->size)//同链表删除
    {
        QNode* next = queue->phead->next;
        free(queue->phead);
        queue->phead = next;
        queue->size--;
    }
}
//搞个节点
QNode* QueueGetNode(QueueDataType data)//因为队列底层是链表(此是不带头),返回搞的节点就行,顺序表得扩容
{
    QNode* newnode = (QNode*)malloc(sizeof(QNode));
    assert(newnode);//扩容失败
    newnode->_data = data;
    newnode->next = NULL;
    return newnode;
}
//队列尾部插入数据
void QueueInsert(QInfo* queue, QueueDataType data)
{
    if (queue->size == NULL)
    {
        queue->ptail = queue->phead = QueueGetNode(data);
    }
    else
    {
        queue->ptail->next= QueueGetNode(data);
        queue->ptail = queue->ptail->next;
    }
    queue->size++;
}
//队列头部获取并删除数据
BTNode* QueuePop(QInfo* queue)
{
    assert(queue);
    BTNode* mid = queue->phead->_data;
    QNode* next = queue->phead->next;
    free(queue->phead);
    queue->phead = next;
    queue->size--;
    return mid;
}
//队列判空
int QueueIsEmpty(QInfo* queue)
{
    assert(queue);
    return queue->size == NULL;
}
//返回队列长度
int QueueSize(QInfo* queue)
{
    assert(queue);
    return queue->size;
}
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, /*int n, */int* pi)//a是数组,pi是数组第几个,需要用指针实时记录
{//n是检查当前建历的节点加上空,与a最后结果pi相等,可不检查
    if (a[*pi] == '#')
    {
        (*pi)++;
        return NULL;
    }
    BTNode* pcur = (BTNode*)malloc(sizeof(BTNode));
    pcur->_data = a[(*pi)++];
    pcur->_left = BinaryTreeCreate(a, pi);
    pcur->_right= BinaryTreeCreate(a, pi);
    return pcur;//遍历完字符串树就构建完成了
}
// 二叉树销毁
void BinaryTreeDestory(BTNode** root)
{
    if (*root == NULL)
        return;
    BinaryTreeDestory(&((*root)->_left));
    BinaryTreeDestory(&((*root)->_right));
    //二叉树销毁用后续遍历,到了叶子节点才开始(操作)销毁
    free(*root);
    *root = NULL;
    //可以不销毁二级指针,只是外部BTNode*root1的地址的拷贝
}
// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
    if (root == NULL)
        return 0;
    return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;//分治思想,递归,总个数等于左子树加上右子树加上自己//后序,左右树遍历完了才操作(返回自己的值
}
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
    if (root == NULL)//单孩子节点遍历到空
        return 0;
    if (root->_left == NULL && root->_right == NULL)//叶子节点
        return 1;
    return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);//等于左边子树的叶子节点数加上右边节点的叶子数
}
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
    if (root == NULL)
        return 0;//找空结束
    if (k == 1)
        return 1;//找到第K层了且非空
    return BinaryTreeLevelKSize(root->_left, k - 1) + BinaryTreeLevelKSize(root->_right, k - 1);
    //子树中第k-1层节点个数
}
// 二叉树查找值为x的节点//仅找出一节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
    if (root == NULL)
        return 0;//返回0表示此子树未找到
    if (root->_data == x)
        return root;//返回找到的地址
    BTNode* leftback = BinaryTreeFind(root->_left, x);
    BTNode* rightback = BinaryTreeFind(root->_right, x);
    return leftback == NULL ? rightback : leftback;//反正都是空就返回右空
}
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{
    if (root == NULL)
        return;
    printf("%c ", root->_data);
    BinaryTreePrevOrder(root->_left);
    BinaryTreePrevOrder(root->_right);
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
    if (root == NULL)
        return;
    BinaryTreeInOrder(root->_left);
    printf("%c ", root->_data);
    BinaryTreeInOrder(root->_right);
}

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
    if (root == NULL)
        return;
    BinaryTreeInOrder(root->_left);
    BinaryTreeInOrder(root->_right);
    printf("%c ", root->_data);
}

// 层序遍历//用队列层序遍历

void BinaryTreeLevelOrder(BTNode* root)
{
    assert(root);
    QInfo queue;
    QueueInit(&queue);//传地址
    QueueInsert(&queue, root);
    while (!QueueIsEmpty(&queue))
    {

        BTNode* pcur = QueuePop(&queue);
#if 1
        printf("%c ", pcur->_data);
        if(pcur->_left)//不插入空节点,不然找左右值时要检查节点不为空
            QueueInsert(&queue, pcur->_left);
        if (pcur->_right)
            QueueInsert(&queue, pcur->_right);
#elif 2
        if (pcur)//插入空节点要检查
        {
            printf("%c ", pcur->_data);
            QueueInsert(&queue, pcur->_left);
            QueueInsert(&queue, pcur->_right);
        }
#endif
    }
    printf("\n");
}
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)//层序遍历,出到空节点停止并判断队列中是否只剩下空
{
    if (root == NULL)
        return 1;
    QInfo queue;
    QueueInit(&queue);
    QueueInsert(&queue, root);
    while (!QueueIsEmpty(&queue))
    {
        BTNode* mid = QueuePop(&queue);
        if (mid != NULL)
        {
            QueueInsert(&queue, mid->_left);
            QueueInsert(&queue, mid->_right);
        }
        else
        {
            break;//跳出检查队列是否只剩下空元素
        }
    }
    while (!QueueIsEmpty(&queue))
    {
        BTNode* mid = QueuePop(&queue);
        if (mid != NULL)
            return 0;
    }
}

main.c

#include"BT.h"
int main()
{
    char BTarry[] = "124##5##36##7##";//"ABD##E#H##CF##G##";
    int i = 0;
    char findchar = '3';
    BTNode* mid=0;
    BTNode* root = BinaryTreeCreate(BTarry, /*int n, */&i);
    printf("前,中,后序遍历:\n");
    BinaryTreePrevOrder(root);
    putchar('\n');
    BinaryTreeInOrder(root);
    putchar('\n');
    BinaryTreePostOrder(root);
    putchar('\n');
    putchar('\n');
    printf("叶子节点数 = %d\n", BinaryTreeLeafSize(root));
    putchar('\n');
    printf("找 %c 节点,%s\n", findchar, (mid = BinaryTreeFind(root, findchar)) == 0 ?"失败":"成功");
    printf("层序遍历: ");
    BinaryTreeLevelOrder(root);
    putchar('\n');
    printf("此二叉树 %s 完全二叉树\n", BinaryTreeComplete(root) == 1 ? "是" : "不是");
    BinaryTreeDestory(&root);
    return 0;
}

  • 29
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值