【数据结构】五、普通二叉树的基本功能实现

目录

一、引言

二、二叉树中的一些名词

三、二叉树的作用

二叉树的优点:

✨二叉树的应用场景:

四、C代码实现

1、结构体定义

2、✨树的遍历方式✨

3、✨树的创建✨

4、✨数据的查找

5、求二叉树的深度

一、引言

二叉树是一种常见的数据结构,它由节点组成,每个节点最多有两个子节点。二叉树在计算机科学中有广泛的应用,如搜索、排序、树状结构的表示等。

关于二叉树的知识点和代码都比较多,因此我会分几个篇幅介绍,本章将介绍普通二叉树的基本操作,包括结构体,遍历二叉树,创建二叉树,数据查找,判断树的深度等,代码的逻辑以递归为主。🥰

二、二叉树中的一些名词

  • 树的深度:空树深度为0,树的根节点深度为1,每往下一层深度加一;

  • 叶子节点:左右子树为0的节点称为叶子节点,很多情况下只有叶子节点存放有效数据

  • 满二叉树:只有最深的一层有叶子节点;

  • 完全二叉树:可以理解为从上到下,从左到右依次给节点编号,节点之间的编号必须是连续的,不能中断

三、二叉树的作用

树作为我们新学习的数据结构,我们首先要知道它有什么优势,在什么情况下使用,而不能像无头苍蝇一样只学会了怎么用,但是又从来没有使用过,到最后忘得一干二净。要合理使用二叉树,我们应该先了解一下它的优点有哪些:

二叉树的优点:

1、搜索效率高:对于有序的二叉树,搜索操作的时间复杂度为O(\log n),比顺序搜索快得多(因为我们只需要朝左节点或右节点访问,选择一次数据就少一半)。

2、插入和删除操作相对简单:在某些情况下,二叉树的插入和删除操作比其他数据结构更容易实现。

✨二叉树的应用场景:

最常见的是海量数据并发查询,二叉树复杂度是O(\log n)。二叉排序树就既有链表的好处,也有数组的好处, 在处理大批量的动态的数据是比较有用

此外还有哈夫曼编码,用于压缩存储,提高数据传输的效率、红黑树等等都需要使用到二叉树,以后有机会再进行分享~

四、C代码实现

1、结构体定义
typedef struct BinTree{
    ElemType data;           //数据域
    struct BinTree *lchile; //左右子树
    struct BinTree *rchile;
    char* flag;            //Huffman编码,这个暂时用不上
}BinTree;
2、✨树的遍历方式✨

树有四种遍历方式,分别是前序遍历,中序遍历,后序遍历和层序遍历,其遍历顺序入下图:

前序遍历:

前序遍历是从根节点开始一直朝左子树访问到底,若左子树为空则返回访问右子树

中序遍历:

节点左边的节点一定在左子树,节点右边的节点一定在右子树

后序遍历:

层序遍历(使用队列)

㊙️截图来自b站up主:鱼C-小甲鱼,小污龟的数据结构的视频讲的还是挺好的,推荐大家去康康

1)使用递归实现:

用递归实现遍历其代码基本相同,根据需要的顺序改变递归函数的顺序即可。

//二叉树先序遍历算法 - 根 左 右
int PreOrderTraverse(BinTree* T) {
    if (T == NULL) {       //结束递归的条件
        return 1;
    }
    else {
        visit(T);       //访问该节点
        PreOrderTraverse(T->lchile);        //遍历递归左子树
        PreOrderTraverse(T->rchile);        //遍历递归右子树
    }
}

//二叉树中序遍历算法 - 左 根 右
int InOrderTraverse(BinTree* T) {
    if (T == NULL) { 
        return 1;
    }
    else {
        InOrderTraverse(T->lchile);     //遍历递归左子树
        visit(T);       //访问该节点
        InOrderTraverse(T->rchile);     //遍历递归右子树
    }
}

//二叉树后序遍历算法 - 左 右 根
int PostOrderTraverse(BinTree* T) {
    if (T == NULL) {
        return 1;
    }
    else {
        PostOrderTraverse(T->lchile);       //遍历递归左子树
        PostOrderTraverse(T->rchile);       //遍历递归右子树
        visit(T);       //访问根节点
    }
}

当然还有很多方法实现树的遍历,比如借用队列,栈来遍历也是很好的方法(这就成功把前面的知识应用起来了)但是篇幅有限,我们会在下一篇文章中讲解。

2)使用栈先序遍历

3)使用队列层序遍历

3、✨树的创建✨
/*
* @brief 通过字符数组递归创建一棵树
* @param 节点地址,节点字符串
* @return None
*/
void Tree_Creative_ARR(BinTree** root,char* str,int* i)
{
    if (*root == NULL) return;
    char c;
    c = str[*i];
    if (c == ' ')
    {
        *root = NULL;
    }
    else
    {
        *root = (BinTree*)malloc(sizeof(BinTree));
        (*root)->data = c;
        memset((*root)->flag, 0, 5);
        (*i)++;
        Tree_Creative_ARR(&(*root)->lchile, str, i);
        (*i)++;
        Tree_Creative_ARR(&(*root)->rchile, str, i);
    }
    return;
}

//调用:需要一个值为0的int指针
int i = 0;
Tree_Creative_ARR(&T,str,&i);   
  • 这里使用前序遍历的方法输入二叉树的数据;

  • 空格表示空子树,因此在遇到叶子节点时后面要跟上两个空格,比如上面先序遍历的图其字符串应该为abdh()()i()()e()j()()cf()k()()g()() ;

  • 通过这种方法创建的二叉树是一个普通(无序)二叉树;(有序二叉树后面也会讲到)

4、✨数据的查找

对于普通二叉树,其数据存放是无序的,需要使用遍历的方法查找

/*
* @brief 在二叉树中查找
* @param 根节点,要查找的数据
* @return 该节点的指针
*/
BinTree* Tree_Find(BinTree* root, ElemType x)
{
    if (root == NULL) return NULL;
    if (root->data == x)return root;

    BinTree* t;
    t = Tree_Find(root->lchile, x);
    if (t != NULL)return t;
    t = Tree_Find(root->rchile, x);
    if (t != NULL)return t;
    return NULL;
}
5、求二叉树的深度
//输出树的深度(根的深度为1)
int Tree_Depth(BinTree* T)
{
    int n, m;
    if (T == NULL)
        return 0; //如果是空树,深度为0,递归结束
    else
    {
        n = Tree_Depth(T->lchile); //递归计算左子树的深度记为n
        m = Tree_Depth(T->rchile); //递归计算右子树的深度记为m
        if (m > n)
            return (m + 1); 
        else
            return (n + 1);
    }
}

由于树特殊的结构类型,在配合栈或队列时食用效果更佳!这将会在下一篇文章中介绍🥰

最后感谢你观看完我的文章,如果文章对你有帮助,可以点赞收藏评论,这是对作者最好的鼓励!不胜感激🥰

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值