数据结构 | C/C++二叉树的实现(含接口函数声明、附完整代码和注释)

目录

 一、定义和头文件

二、功能实现

三、难点讲解

1、层序遍历

2、完全二叉树检验

四、测试函数

五、运行结果


 一、定义和头文件

typedef char BTDataType;

typedef struct BinaryTreeNode
{
    BTDataType _data;
    struct BinaryTreeNode* _left;
    struct BinaryTreeNode* _right;
    BinaryTreeNode(const BTDataType& data)
        :_data(data),
        _left(nullptr),
        _right(nullptr)
    {}
    ~BinaryTreeNode()
    {
        _left = _right = nullptr;
    }
}BTNode;

// 通过前序遍历的数组"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);

二、功能实现

#include<iostream>
#include <cstring>
#include <queue>
using namespace std;
typedef char BTDataType;

typedef struct BinaryTreeNode
{
    BTDataType _data;
    struct BinaryTreeNode* _left;
    struct BinaryTreeNode* _right;
    BinaryTreeNode(const BTDataType& data)
        :_data(data),
        _left(nullptr),
        _right(nullptr)
    {}
    ~BinaryTreeNode()
    {
        _left = _right = nullptr;
    }
}BTNode;

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
/*
    a : 前序遍历得到二叉树的源string
    n : 遍历的长度
    pi: 记录当前遍历的下标位置
*/
BTNode* BinaryTreeCreate(const BTDataType* a, int n, int* pi)
{
    if (a[*pi] == '#' || *pi > n)
    {
        (*pi)++;
        return nullptr;
    }

    BTNode* cur = new BTNode(a[(*pi)++]);
    cur->_left = BinaryTreeCreate(a, n, pi);
    cur->_right = BinaryTreeCreate(a, n, pi);
    return cur;
}
// 二叉树销毁
void BinaryTreeDestory(BTNode* root)
{
    if (root == nullptr)
        return;

    BinaryTreeDestory(root->_left);
    BinaryTreeDestory(root->_right);
    delete root;
}

//int _dfs(BTNode* root, int n)
//{
//    if (root == nullptr)
//        return n;
//
//    n++;
//    n = _dfs(root->_left, n);
//    n = _dfs(root->_right, n);
//    return n;
//}
 二叉树节点个数
//int BinaryTreeSize(BTNode* root)
//{
//    return _dfs(root, 0);
//}

// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
    if (!root)
        return 0;
    return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;
}

//int __dfs(BTNode* root, int n)
//{
//    if (root == nullptr)
//        return n;
//
//    if (!root->_left && !root->_right)
//        n++;
//    n = __dfs(root->_left, n);
//    n = __dfs(root->_right, n);
//    return n;
//}
 二叉树叶子节点个数
//int BinaryTreeLeafSize(BTNode* root)
//{
//    return __dfs(root, 0);
//}

// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
    if (!root)
        return 0;
    else if (!root->_left && !root->_right)
        return 1;
    return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}

// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
    // 不断向下寻找 直到第k层 然后分类返回
    // 如果是空返回0 反之节点存在 返回1
    if (!root)
        return 0;
    else 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)
        return nullptr;
    else if (root->_data == x)
        return root;
    BinaryTreeFind(root->_left, x);
    BinaryTreeFind(root->_right, x);
}
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root)
{
    if (!root)
        return;
    cout << root->_data << ' ';
    BinaryTreePrevOrder(root->_left);
    BinaryTreePrevOrder(root->_right);
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
    if (!root)
        return;
    BinaryTreeInOrder(root->_left);
    cout << root->_data << ' ';
    BinaryTreeInOrder(root->_right);
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
    if (!root)
        return;
    BinaryTreePostOrder(root->_left);
    BinaryTreePostOrder(root->_right);
    cout << root->_data << ' ';
}
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
    // 层序遍历:利用队列先进先出的性质 每一次出队列都带上下一层的左右节点即可
    queue<BTNode*> q;
    if (root)
        q.push(root);
    while (!q.empty())
    {
        BTNode* front = q.front();
        cout << front->_data << ' ';
        q.pop();
        if (front->_left)
            q.push(front->_left);
        if (front->_right)
            q.push(front->_right);
    }
    cout << endl;
}
// 判断二叉树是否是完全二叉树
// 完全二叉树是由满二叉树而引出来的
// 若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数(即1~h-1层为一个满二叉树)
// 第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
int BinaryTreeComplete(BTNode* root)
{
    // 层序遍历:利用队列先进先出的性质 每一次出队列都带上下一层的左右节点即可
    queue<BTNode*> q;
    if (root)
        q.push(root);
    bool flag = false;
    while (!q.empty())
    {
        BTNode* front = q.front();
        q.pop();
        if (!front) {
            flag = true;
            continue;
        }
        if (flag)
            return false;
        q.push(front->_left);
        q.push(front->_right);
    }
    return true;
}


三、难点讲解

1、层序遍历

利用队列先进先出的性质,每一次出队列都带上下一层的左右节点,直到队列为空,遍历结束。

2、完全二叉树检验

☆☆☆ 完全二叉树的检验可以复用层序遍历

完全二叉树的检验核心思路是:带二叉树走一遍层序遍历,如果遍历到一个空节点,将flag置为true,如果遍历到一个非空节点而且flag==true,说明一定不是完全二叉树,返回false。如果能走完全过程,返回true。

实例1:

输出:true
解释:最后一层前的每一层都是满的(即,节点值为 {1} 和 {2,3} 的两层),且最后一层中的所有节点({4,5,6})尽可能靠左。

实例2:

输出:false
解释:值为 7 的节点不满足条件「节点尽可能靠左」。

可参考:958. 二叉树的完全性检验 - 力扣(LeetCode)

四、测试函数

int main()
{
    const char* str = "ABD##E#H##CF##G##";
    int a = 0;
    auto e = BinaryTreeCreate(str, strlen(str), &a);
    cout << BinaryTreeSize(e) << endl;
    cout << BinaryTreeSize(e) << endl;
    cout << BinaryTreeLeafSize(e) << endl;
    cout << BinaryTreeLevelKSize(e, 3) << endl;
    cout << BinaryTreeFind(e, 'N') << endl;
    BinaryTreePrevOrder(e);
    cout << endl;
    BinaryTreeInOrder(e);
    cout << endl;
    BinaryTreePostOrder(e);
    cout << endl;
    BinaryTreeLevelOrder(e);
    cout<<BinaryTreeComplete(e);
    return 0;
}

五、运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值