二叉树及其遍历
文章目录
- 二叉树
- 树的定义
- 二叉树的定义
- 遍历
- 先序遍历
- 中序遍历
- 后序遍历
- 层次遍历
- 定义队列
- 层次创建二叉树
- 层次遍历
二叉树
树是一种非线性的数据结构,由若干个节点组成,节点之间存在一种父子关系,具有层次结构。二叉树是一种特殊的树结构,每个节点最多有两个子节点。树结构可以用来实现各种算法,例如二叉查找树、平衡二叉树、堆等。
树的定义
树(Tree) 是n(n>=0)个结点的有限集。n=0时称为空树。在任意一颗非空树中:
- 有且仅有一个特定的称为根(Root)的结点;
- 当n>1时,其余结点可分为
m(m>0)个互不相交的有限集T1、T2、…、Tn,其中每一个集合本身又是一棵树,并且称为根的子树。
此外,树的定义还需要强调以下两点:
n>0时根结点是唯一的,不可能存在多个根结点,数据结构中的树只能有一个根结点。m>0时,子树的个数没有限制,但它们一定是互不相交的。
二叉树的定义
二叉树是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成。

从定义和图例中可以看出,二叉树每个节点最多只会有两棵子树,且左右子树是有顺序的,次序不能随意颠倒。当一个节点既没有左子树也没有右子树,则该节点为叶子节点。
代码实现
结构体定义树
typedef struct Tree{int val; //数据域struct Tree *left; // 左子树struct Tree *right; // 右子树
}Tree,*tree;
遍历
二叉树作为一种存储结构,将数据存入之后,则需要遍历对数据进行对应的处理。而二叉树的遍历分为四种:先(前)序遍历、中序遍历、后序遍历、层次遍历。

先序遍历
先序遍历是指从根节点开始,经过左子树,最后再遍历右子树,遍历顺序为:根节点->左子树->右子树。
代码实现
首先使用先序递归的创建一颗二叉树
// 创建新节点
Tree newNode(int val){Tree root = (Tree) malloc(sizeof (tree));root->val = val;root->left = NULL;root->right = NULL;return root
}
Tree CreateBiTree(int* len){//创建一颗节点数为len的二叉树if((*len)<=0){return NULL;}int val; //创建一个数据接收参数。printf("请输入插入数值:");// 为根节点数据域赋值scanf("%d",&val);//创建一个根节点Tree root = newNode(val);(*len)--;root->left = CreateBiTree(len); //递归创建左子树root->right = CreateBiTree(len); //递归创建右子树//创建完成后返回根节点return root;
}
再进行先序遍历
//先序遍历
void preorder(Tree root){if(root==NULL){return ;}// 首先输出根节点的值printf("节点的值:%d\n",root->val);//先递归遍历左子树preorder(root->left);//递归遍历右子树preorder(root->right);
}
运行结果

中序遍历
中序遍历是指从左子树开始,再访问根节点,最后遍历右子树,遍历顺序为:左子树->根节点->右子树。
代码实现
利用先序递归创建一颗二叉树,并使用中序遍历二叉树
//中序遍历
void inorder(Tree root){//如果节点为NULL,退出遍历if(root==NULL){return ;}//先递归遍历左子树inorder(root->left);// 输出根节点的值printf("节点的值:%d\n",root->val);//递归遍历右子树inorder(root->right);
}
运行结果

后序遍历
后序遍历是指从左子树开始,再遍历右子树,最后访问根节点,遍历顺序为:左子树->右子树->根节点。
代码实现
// 后序遍历
void postorder(Tree root){//如果节点为NULL,退出遍历if(root==NULL){return ;}//先递归遍历左子树postorder(root->left);//再递归遍历右子树postorder(root->right);//输出根节点的值printf("节点的值:%d\n",root->val);
}
运行结果

为什么后序遍历和中序遍历的结果相同呢?
因为创建二叉树的时候使用的是前序递归,所以创建出来的二叉树都在根节点的左子树上,其右子树为空,此时这种情况被称为斜二叉树,并且也被称之为二叉树退化成单链表。这样创建出来的二叉树是很浪费空间且不规范的。
所以先序递归创建的二叉树是不可取的。此时就用到层次创建二叉树,层次创建是用到最多的创建方式,也是较为直观的一种创建方式。
层次遍历
层次遍历是指从根节点开始,然后一层一层向下遍历。
代码实现
一把是利用队列来实现层次创建及遍历二叉树
定义队列
// 定义队列
struct Queue {struct Tree *Tree;struct Queue *next;
};// 初始化队列
void initQueue(struct Queue **head, struct Queue **tail) {*head = *tail = NULL;
}// 入队
void enQueue(struct Queue **head, struct Queue **tail, struct Tree *Tree) {struct Queue *node = (struct Queue*)malloc(sizeof(struct Queue));node->Tree = Tree;node->next = NULL;if (*head == NULL) {*head = *tail = node;} else {(*tail)->next = node;*tail = node;}
}// 出队
struct Tree* deQueue(struct Queue **head, struct Queue **tail) {if (*head == NULL) {return NULL;}struct Tree *Tree = (*head)->Tree;if (*head == *tail) {*head = *tail = NULL;} else {*head = (*head)->next;}return Tree;
}
层次创建二叉树
// 创建二叉树
struct Tree* createTree(int *arr, int size) { //arr为数据数组,size为层数if (size == 0) {return NULL;}// 创建根节点struct Tree *root = (struct Tree*)malloc(sizeof(struct Tree));root->val = arr[0];root->left = NULL;root->right = NULL;// 初始化队列struct Queue *head, *tail;initQueue(&head, &tail);enQueue(&head, &tail, root);int i = 1;// 层次遍历创建二叉树while (i < size) {struct Tree *node = deQueue(&head, &tail);// 左子树if (i < size && arr[i] != -1) { //当数据为-1时证明该处为空节点node->left = (struct Tree*)malloc(sizeof(struct Tree));node->left->val = arr[i];node->left->left = NULL;node->left->right = NULL;enQueue(&head, &tail, node->left);}i++;// 右子树if (i < size && arr[i] != -1) {node->right = (struct Tree*)malloc(sizeof(struct Tree));node->right->val = arr[i];node->right->left = NULL;node->right->right = NULL;enQueue(&head, &tail, node->right);}i++;}return root;
}
层次遍历
// 层次遍历
void levelOrder(struct Tree* root) {if (root == NULL) {return;}struct Queue *head, *tail; // 定义队头与队尾initQueue(&head, &tail);enQueue(&head, &tail, root);while (head != NULL) {struct Tree *node = deQueue(&head, &tail);printf("%d ", node->val);if (node->left != NULL) {enQueue(&head, &tail, node->left);}if (node->right != NULL) {enQueue(&head, &tail, node->right);}}
}
main函数
// 测试代码
int main() {// 层次遍历序列,其中-1表示空节点int arr[] = {1, 2, 3, 4, -1, -1, 5};int size = sizeof(arr) / sizeof(int);// 创建二叉树struct Tree* root = createTree(arr, size);// 打印二叉树levelOrder(root);return 0;
}
运行结果

层次遍历已经实现,接着使用层次创建二叉树,并实现先中后序遍历
运行结果分别为:
先序遍历

中序遍历

后序遍历

相关文章:
二叉树及其遍历
文章目录 二叉树树的定义二叉树的定义遍历先序遍历中序遍历后序遍历层次遍历定义队列层次创建二叉树层次遍历 二叉树 树是一种非线性的数据结构,由若干个节点组成,节点之间存在一种父子关系,具有层次结构。二叉树是一种特殊的树结构ÿ…...
java 版本企业电子招投标采购系统源码之登录页面
信息数智化招采系统 服务框架:Spring Cloud、Spring Boot2、Mybatis、OAuth2、Security 前端架构:VUE、Uniapp、Layui、Bootstrap、H5、CSS3 涉及技术:Eureka、Config、Zuul、OAuth2、Security、OSS、Turbine、Zipkin、Feign、Monitor、…...
第五章 使用RAID与LVM磁盘阵列技术
第五章 使用RAID与LVM磁盘阵列技术 一、RAID磁盘冗余阵列 1、部署磁盘阵列 (1)、RAID0、1、5、10方案技术对比 RAID级别最少硬盘可用容量读写性能安全性特点02nn低追求最大容量和速度,任何一块盘损坏,数据全部异常。12n/2n高追…...
LeetCode 560. 和为 K 的子数组
LeetCode 560. 和为 K 的子数组 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 。 示例 1: 输入:nums [1,1,1], k 2 输出:2示例 2: 输入:nums [1,2,3], k 3 …...
后端要一次性返回我10万条数据
问题描述 面试官:后端一次性返回10万条数据给你,你如何处理?我:歪嘴一笑,what the f**k! 问题考察点 看似无厘头的问题,实际上考查候选人知识的广度和深度,虽然在工作中这种情况很少遇到... …...
汽车智能化「出海」红利
在高阶智能座舱中,车载导航产品作为与用户体验息息相关的模块之一,同样也进入了升级迭代周期。 基于高精度地图渲染、高精度定位算法、AR等技术的车道级导航、AR导航等产品快速上车,但同时随着人机交互多模发展以及3D沉浸式用户体验需求趋势下…...
Windows10资源管理器使用
文章目录 前言二、关联菜单操作1.分组展示2.添加选择复选框3.使用窗格模式4.功能区折叠二、“文件夹选项”对话框操作1.访问模式调整2.状态栏控制总结前言 目前Windows系统中的使用较多当属Windows10,资源管理器属于Windows系统中一个常用工具。本文总结了Windows 10 专业版下…...
【视频教程解读】Window上安装和使用autogluon V0.7
1.使用conda安装的python环境 教程使用的是极简版miniconda,由于我们的电脑中安装了anaconda,所以不需要进行进一步安装。python版本为3.9,博客里面有anaconda和python版本的对应关系。注意查看版本autogluon V0.4需要3.8或者3.9和3.10,pip版…...
10、Java继承与多态 - 内部类的概念与分类 1
10、Java继承与多态 - 内部类的概念与分类 1 什么是内部类? 如果一个事物的内部包含另一个事物,那么这就是一个内部包含另一个类,称作内部类; 例如:身体和心脏的关系,又如 -> 汽车和发动机的关系&#x…...
Java SE 面试题
文章目录 Java SE 面试题基本知识请简要介绍 Java SE。请解释 Java 的垃圾回收机制。请解释 Java 中的访问修饰符。 面向对象请解释封装、继承和多态。请解释接口和抽象类的区别。 集合框架请解释 ArrayList 和 LinkedList 的区别。请解释 Set 和 Map 接口。 异常处理请解释 Ja…...
Linux 之十九 编译工具链、.MAP 文件、.LST 文件
.map 文件和 .lst 文件是嵌入式开发中最有用的俩调试辅助文件。现在主要从事 RISC-V 架构,开始与 GCC 打交道,今天就重点学习一下 GCC 的 .map 文件、.lst 文件,并辅助以 ARMCC 和 IAR 作为对比。 编译工具链 .map 文件和 .lst 文件都是由编…...
小 C 的数学(math)
祝大家劳动节快乐!!小手动起来 言归正传┏ (゜ω゜)☞ 题目描述 小 C 想要成为一名 OIer,于是他提前学习数学,为 OI 做好铺垫。这一天,他的数学老师给了一道题:给定正整数 a,以及给定一个区间 …...
应用运行环境实时洞察,亚马逊云科技Cisco AppDynamics展优势
Cisco AppDynamics(APM)产品,现已正式上线亚马逊云科技Marketplace(中国区域)。可以通过亚马逊云科技Marketplace(中国区域)网站,灵活便捷地部署该解决方案,以便充分利用云原生APM(应用性能管理…...
C++程序设计——lambda表达式
一、问题引入 在C98中,如果想对一个数据集合中的元素进行排序,可以使用sort()方法,但如果待排序元素为自定义类型,就需要用户自己定义排序时的比较规则。 随着C语法的发展,人们开始觉得其编写比较复杂,每次…...
Unity 高级程序员应该具备怎样的能力?要怎样成长为 Unity 高级程序员?
如何从零基础小白成长为 Unity 高级程序员?【全篇学习内容免费!快来白嫖】 高能预警,下文包含从零基础新手到高级程序员一站式技术学习、学习方法、心态等内容,供各个阶段的同学进行参考。 从零基础到高级程序员 上干货 话不多说…...
禁止触摸屏触控板手指缩放,需要这样处理
要禁止触摸屏的手指缩放,可以使用如下的CSS 只要在页面上使用css样式touch-action: none,就能禁止web在手机或平板上的缩放了。 <html style"touch-action: none;">注意: 使用 touch-action: none作用于html元素上࿰…...
opencv cuda版本windows编译
目录 1. 编译准备2. 编译3. 遇到的问题及解决方案3.1 boostdesc_bgm.i,vgg_generated_48.i等文件的缺失3.2 fatal error: features2d/test/test_detectors_regression.impl.hpp: 没有那个文件或目录 1. 编译准备 编译工具是cmakevisual studio2022,首先安装这两个工…...
python哲学
进入python编辑器模式下,输入import this 会打印python之禅(The Zen of Python) Beautiful is better than ugly. 优美胜于丑陋。 Explicit is better than implicit. 明了胜于晦涩。 Simple is better than complex. 简单胜过复杂。 Complex is better than co…...
(2023)用AIGC写iOS项目单元总结
尝试开发的项目 项目功能 用 ChatGPT 开发了一个视频播放器。需要它编写的功能包括: ☆ 本地文件,在线 URL 播放,暂停 ☆ 点击空白区域弹出操作菜单,再点击消失 ☆ 手动横竖屏切换 ☆ 播放速度调整,限定 0.5, 1.0, …...
k8s扩容node节点会影响上面已存在的pod吗?
理论上不影响 扩容 Kubernetes 集群中的节点不会影响已经运行的 Pod,因为 Pod 是在节点上运行的,而不是在集群中运行的。当您添加新的节点时,Kubernetes 调度器会在新节点上启动新的 Pod,而已经运行的 Pod 会继续在它们当前的节点…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...
数据结构:泰勒展开式:霍纳法则(Horner‘s Rule)
目录 🔍 若用递归计算每一项,会发生什么? Horners Rule(霍纳法则) 第一步:我们从最原始的泰勒公式出发 第二步:从形式上重新观察展开式 🌟 第三步:引出霍纳法则&…...
React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?
系列回顾: 在上一篇《React核心概念:State是什么?》中,我们学习了如何使用useState让一个组件拥有自己的内部数据(State),并通过一个计数器案例,实现了组件的自我更新。这很棒&#…...
