目录

构造链式二叉树

创建一颗二叉树

二叉树的遍历

前序遍历

中序遍历

后序遍历

层序遍历

判断二叉树是否为完全二叉树

节点个数以及高度

二叉树节点个数

二叉树叶子节点个数

二叉树的高度

二叉树第k层节点个数

二叉树查找值为x的节点

二叉树的创建和销毁

创建

销毁

结语


构造链式二叉树

上一篇博客介绍了堆,堆是用数组来实现的,通过控制数组下标来实现各种功能,那这一篇就通过链式二叉树来了解一下二叉树吧。

链式二叉树,和之前的链表似的,只不过一个节点有两条链


创建一颗二叉树

为了方便介绍二叉树,先来 “手搓” 一个二叉树,通过这个简单的二叉树来了解二叉树的性质,但这并不是创建二叉树的方式。

这就是这棵树的结构


二叉树的遍历

学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。

遍历的方式分为:前序遍历、中序遍历和后序遍历:

        1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。
        2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。
        3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。
        简单来说:这里的前中后是针对根节点来说的,抛开这三种遍历顺序,都是按照根、左树、右树的顺序来遍历的。
        前序就是先访问根,再左树和右树;
        中序就是先访问左树,再访问根,最后访问右树;
        后序就是先访问左树和右树,再访问根。

前序遍历

这三种遍历方式都是用递归实现的,为了能看清遍历过程,我们使用打印的方式,只要是空树就打印 “#”,不是就打印对应的数据。

先打印一下前序遍历

图也可以这样看,下面是默认的空树

这就是完整的递归展开图

中序遍历

因为中序遍历和后序遍历的递归展开图大同小异,画法差不多,所以可以自己思考一下怎样去画。

后序遍历

层序遍历

层序遍历通常是借助一个队列来实现的,层序遍历是先访问第一层,再第二层,直到最后一层。

接下来就是得有个队列,由于是用C语言写的,库里没有队列这个数据结构,所以只能拿原来写的队列。

把之前写的队列添加到这里面,再写上队列的头文件。

还有一个问题是,上面讲的思想是把一个节点入队列和出队列,但是队列的每个元素是整型,还需要做一些修改,需要加一个前置声明,为了把队列中的每个元素都变成BTNode*。


判断二叉树是否为完全二叉树

判断二叉树是不是完全二叉树就可以用层序遍历的方式来判断

队列销毁的时候一定要在返回之前,不然返回了,队列没有销毁就会造成内存泄漏,虽然不会报错,但还是会存在隐患。

二叉树还是上面的二叉树,所以这不是一个完全二叉树,改一下左右子树就可以看到完全二叉树的结果了。


节点个数以及高度

二叉树节点个数

这一小部分想要得到的都是节点个数之类的,那么就要用到分治的思想

既然想得到整个二叉树的节点个数,每一部分都可以看作是一个左子树,一个右子树,加一个根,那么节点个数就可以认为是:

左子树的节点个数+右子树节点个数+1(根节点)

这个代码还可以简化成这样

二叉树叶子节点个数

同样是用分治的思想,把左子树的叶子节点个数和右子树的节点个数相加就是整颗二叉树的节点个数;叶子节点的特征就是它的左子树和右子树都是空的,这就可以拿来当作判断条件。

二叉树的高度

同样可以使用分治的思想,只不过不是把左右子树相加了,高度是什么呢,是左右两个子树高度的较大值,比如下面这张图:

左树的高度是2,右树的高度是3,再加上根节点的那一层,应该高度是4,所以要分治求出两个子树的较大值后再加一才是整个树的高度。

这只是一种写法,也可以把+1写到定义的两个局部变量后;这里建议还是定义两个局部变量,如果不这样写,下面这种也可以。

       这种每次函数栈帧会开辟一块新的空间,不仅时间和空间都会有一定的浪费,所以还是不建议这样写。

二叉树第k层节点个数

这一部分比较麻烦的就是如何找到第k层,随着递归的深入,想要直到本次递归在第几层也很麻烦。

那想想可不可使用全局变量,建议还是不要这样,第一点,全局变量并不好;第二点,它并不能解决这个问题,每次递归就+1很容易就会出bug。

那这里就介绍另一种方法。

用k表示要找第几层的节点个数,那这个值就得>=1。

二叉树查找值为x的节点

函数的返回类型为BTNode*,所以找到了要把那个节点带回去,如果找到那个节点就打印返回的节点对应的data,如果找不到就返回NULL。

用同样的思想,先看看根节点是不是x,如果是就直接返回了,如果不是就去左树和右树里找,如果在左树中找到了就直接返回了,那就不管右树里有没有了;如果左树找不到,再去右树找;最后左树和右树都没找到,那x就不存在,直接返回NULL就可以了。

同样的问题,这里找到的返回值最好保存在一个变量中,要不然返回的时候还得再找一遍。


二叉树的创建和销毁

创建

创建的方法可以看一下这道题,输入一个前序遍历字符串来创建二叉树

输入一个字符串,定义一个i,把两个变量的地址传入函数

因为是个字符串,要把typedef的int改为char,BuyNode函数不用改。为什么i也要传入地址呢。递归创建二叉树,每放入一个数据,字符串就要往后挪,数组下标就要移动,所以要传入地址。

每放入一个数据都要BuyNode,因为题目说前序遍历的字符串,所以先创建根,再创建左子树和右子树。

最后返回根节点。

销毁

销毁可以有三个方向,前序,中序还有后序,前序就是先释放根节点,再释放左右子树,但是释放了根就找不到左右子树了;所以就可以使用后序的方法,先把左右子树都释放了,再释放根。

为了看出释放的顺序可以加一行

可以看到释放的顺序就是后序。


结语

二叉树的部分知识就介绍到这里,因为高阶的数据结构并不适合用C语言来实现,所以数据结构还远远没有结束。

数据结构初阶——二叉树相关推荐

  1. 二叉树前中后序遍历+刷题【中】【数据结构/初阶/C语言实现】

    文章目录 1. 二叉树基础操作 1.1 二叉树遍历 1.1.1 前序遍历 前序遍历(Pre-Order Traversal) 1.1.2 中序遍历 中序遍历(In-Order Traversal) 1 ...

  2. 数据结构初阶最终章------>经典八大排序(C语言实现)

    前言:   正如标题所言,本篇博客是数据结构初阶的最终章节.但不是数据结构的最终章节!事实上,诸如AVL 树,红黑树这样高阶复杂的数据结构使用C语言非常麻烦,这些数据结构我会放在后续的C++的博客中去 ...

  3. 数据结构初阶(4)(OJ练习【判断链表中是否有环、返回链表入口点、删除链表中的所有重复出现的元素】、双向链表LinkedList【注意事项、构造方法、常用方法、模拟实现、遍历方法、顺序表和链表的区别)

    接上次博客:数据结构初阶(3)(链表:链表的基本概念.链表的类型.单向不带头非循环链表的实现.链表的相关OJ练习.链表的优缺点 )_di-Dora的博客-CSDN博客 目录 OJ练习 双向链表--Li ...

  4. 【数据结构初阶】链表(下)——带头双向循环链表的实现

    目录 带头双向循环链表的实现 1.带头双向循环链表的节点类型 2.创建带头双向循环链表的节点 3.向带头双向循环链表中插入数据 <3.1>从链表尾部插入数据 <3.2>从链表头 ...

  5. 数据结构初阶:二叉树

    二叉树 链表和数组都是线性结构,而树是非线性的结构. 树是依靠分支关系定义出的一种层次结构.社会亲缘关系和组织结构图都可以用树来形象地表示. 1. 树 1.1 树的定义 树是 n ( n ≥ 0 ) ...

  6. 树与二叉树(二叉树前传、数据结构初阶、C语言)

    文章目录 前言 一.树的概念及结构 (一).树的概念 (二).树的相关概念 (三).树的表示 二.二叉树的概念及结构 (一).二叉树的概念 (二).满二叉树和完全二叉树 (三).二叉树的性质 (四). ...

  7. 数据结构之初阶二叉树

    要努力,但不要急.繁花锦簇,硕果累累都需要过程! 目录 前言: 1.树 1.树的概念: 2.树的相关概念: 3.树的表示: 4.小结: 2.二叉树 1.概念: 2.特殊的二叉树: 3.二叉树的性质: ...

  8. 数据结构初阶——链式二叉树

    目录 树概念及结构 树的概念 树的表示 二叉树概念及结构 概念 特殊二叉树 二叉树的性质 二叉树链式结构及实现 二叉树的简单创建 二叉树的前序遍历 二叉树中序遍历与二叉树后序遍历 求二叉树节点个数 求 ...

  9. 数据结构初阶之二叉树——概念篇

    目录 一. 树的概念及结构 1. 树的概念 2. 树的相关概念 3. 树的表示 4. 实际运用 二. 二叉树概念及结构 1. 概念 2. 完全二叉树和满二叉树 3. 二叉树的性质 三. 练习 四. 练 ...

  10. 【数据结构初阶】第八篇——二叉树的链式结构(二叉树的前、中和后序遍历+层序遍历+链式结构的实现+相关简单的递归问题)

    ⭐️本篇博客我要来和大家一起聊一聊数据结构中的二叉树的链式结构的实现及相关的一些问题的介绍 ⭐️博客代码已上传至gitee:https://gitee.com/byte-binxin/data-str ...

最新文章

  1. 前阿里程序员吐槽女友败家:开酒店必须400元起步,工资只有自己的1/3
  2. Python使用matplotlib函数subplot可视化多个不同颜色的折线图、自定义数据点的形状、自定义折线图的颜色
  3. iPad 3将获得Retina视网膜显示技术
  4. UVa11205 The Broken Pedometer
  5. 2021中考高考成绩查询,2021中考
  6. 理性分散投资 收益袋袋平安
  7. Elasticsearch 的使用,看这一篇就够了!
  8. java 串的顺序存储_算法入门之串的顺序存储表示
  9. Linux内核跟踪eBPF:bpftrace一行教程
  10. nginx命令和配置
  11. VC获得本机网络连接状态
  12. 一键切换网卡ip v1.0
  13. Android设置网络图片为手机背景图片的方法
  14. VTK图像处理之访问图像像素值
  15. oracle 密码解锁
  16. 星秒入选毕马威(KPMG)汽车科技新锐企业榜
  17. 商米机V2和V1内置打印机说明
  18. 虚幻4 UE4 蓝图C++混合编程
  19. OA项目之项目简介会议发布
  20. 漫谈程序员系列:怎么告别“混日子”

热门文章

  1. 【考研·收藏】考研数学常用希腊字母表(数学符号及读法大全)
  2. 集美大学校园网绑定/认证报错异常及解决方案
  3. 固态硬盘启动计算机时间,固态硬盘10秒开机的技巧:提升SSD性能 延长寿命
  4. 打印出从1到1000的罗马数字
  5. JS 更合理的随机分组
  6. 下拉列表dropdown取消默认点击隐藏及修复需要二次点击的方法
  7. wpsppt设置页码和总页数_wps的ppt页码怎么设置
  8. 较新颖的智能优化算法
  9. 手游外挂入侵(一)某助手加速器实现原理探究
  10. android获取手机唯一识别号