【数据结构】二叉树的链式实现
树是数据结构中非常重要的一种,在计算机的各方个面都有他的身影
此篇文章主要介绍二叉树的基本操作
目录
- 二叉树的定义:
- 二叉树的创建:
- 二叉树的遍历:
- 前序遍历:
- 中序遍历:
- 后序遍历:
- 二叉树节点个数:
- 二叉树叶子结点个数:
- 二叉树第k层节点个数:
- 二叉树查找值为x的节点:
- 二叉树的销毁:
二叉树的定义:
这里我们使用char
,因为二叉树的创建我们会使用递归创建,需要传入一个字符串进行操作
typedef char BTDataType;typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;
二叉树的创建:
我们通过前序遍历的数组"123###45##6##"
构建二叉树
这里讲一下我使用递归做题时的一些做题感受方法:
- 首先写出递归的结束条件,这是每个递归都不可以缺少的
- 利用分治的思想(将一个问题分成几个相同的子问题)
- 把你的递归想象是可以完成你既定的任务
- 写出你调用这个递归需要本次进行的工作
- 完成后可以画出一个递归展开图进行验证
接下来我会仔细带着大家仔细领悟,熟能生巧,同学们一定不要气馁
先解释一下这个函数传参的意义:
BTNode* BinaryTreeCreate(BTDataType* a, int* pi)
a就是我们传参的字符数组
pi是我们字符数组的下标,为什么需要下标的地址呢,因为形参的改变不会影响实参
BTNode* BinaryTreeCreate(BTDataType* a, int* pi)
{if (a[*pi] == '#'){(*pi)++;return NULL;}BTNode* root = (BTNode*)malloc(sizeof(BTNode));if (root == NULL){perror("malloc fail");return;}root->data = a[(*pi)++];root->left = BinaryTreeCreate(a, pi);root->right = BinaryTreeCreate(a, pi);return root;
}
- 做递归时截止条件是必不可少的,我们选择使用叶子节点是否为空作为判断标准。
- 我们将这个问题从创建一个完整二叉树分成先创建一个节点并连接他的左右节点的问题·
- 我们现在需要完成此时函数需要完成的任务,此次函数的目的是创造一个二叉树,我们需要对
root->val
进行赋值,再将root
的左右子树进行连接 - 此时观察整个函数,我们发现我们已经生成了一个
root
节点,也进行了赋值,root
的左右节点也都分别使用BinaryTreeCreate(a, n, pi)
这个函数进行连接,我们已经把此函数当做可以完成既定任务的,不需要过多纠结,此时我们在加一个返回值root
,就完成了此次函数的创建
二叉树的递归图:
大家也可以自己动手画一下递归展开图
二叉树的遍历:
前序遍历:
有了以上的思路就可以很简单的实现了
void BinaryTreePrevOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}printf("%c ", root->data);BinaryTreePrevOrder(root->left);BinaryTreePrevOrder(root->right);
}
代码也很简洁
- NULL结束条件
- 分治:前序是根左右的遍历,故我们先遍历根,在遍历左子树右子树
- 没有返回值,不需要return
就像下图这样,将这个程序当成可以完成任务的函数。printf("%c ", root->data);//进行本次的任务BinaryTreePrevOrder(root->left);//遍历左子树BinaryTreePrevOrder(root->right);//遍历左子树
中序遍历:
与前序遍历一致
void BinaryTreePrevOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}BinaryTreePrevOrder(root->left);printf("%c ", root->data);BinaryTreePrevOrder(root->right);
}
后序遍历:
void BinaryTreePrevOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}BinaryTreePrevOrder(root->left);BinaryTreePrevOrder(root->right);printf("%c ", root->data);
}
二叉树节点个数:
int BinaryTreeSize(BTNode* root)
{if (root == NULL){return 0;}return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
- 结束条件为
NULL
- 分治:将这个问题当成当前节点+左子树节点与右子树节点
- return 当前节点+左子树节点与右子树节点
二叉树叶子结点个数:
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;}return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}
1.结束条件有两个,当为NULL
或为目标层数时为结束
2. 分治:这个的分治并不像上边的简单了,我们需要root的第k层转化为root->左子树的k-1层与root->right的k-1层,将K
也作为函数传参,每次减1
3. 返回第k层节点个数
二叉树查找值为x的节点:
我们先来看这样一段代码,相信有许多小伙伴在遇到
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BinaryTreeFind(root->left, x);BinaryTreeFind(root->right, x);return NULL;
}
乍一看好像没什么问题,不就是前序遍历嘛,
不然,实则我们并没有记录找到的地址,像下图一样
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BTNode* ret1 = BinaryTreeFind(root->left, x);if (ret1){return ret1;}BTNode* ret2 = BinaryTreeFind(root->right, x);if (ret2){return ret2;}return NULL;
}
- 结束为
NULL
或目标值 - 分治:当前节点+左子树+右子树进行前序遍历
- 记录
ret
值并返回
二叉树的销毁:
使用后序遍历,因为前序与中序需要记录当前被销毁的左右节点地址
void BinaryTreeDestory(BTNode* root)
{if (root == NULL){return;}BinaryTreeDestory(root->left);BinaryTreeDestory(root->right);free(root);
}
持续更新中…
相关文章:

【数据结构】二叉树的链式实现
树是数据结构中非常重要的一种,在计算机的各方个面都有他的身影 此篇文章主要介绍二叉树的基本操作 目录 二叉树的定义:二叉树的创建:二叉树的遍历:前序遍历:中序遍历:后序遍历: 二叉树节点个数…...

八、QLayout 用户基本资料修改(Qt5 GUI系列)
目录 一、设计需求 二、实现代码 三、代码解析 四、总结 一、设计需求 在很多应用程序中会有用户注册或用户编辑信息等界面。本文就设计一个用户信息编辑界面。要求包含用户名、姓名、性别、部门、年龄、头像、个人说明等信息。 二、实现代码 #ifndef DIALOG_H #define D…...
tomcat、java、maven
JDK|JRE Tomcat官网介绍的更清楚 Java 环境安装 安装 wget https://builds.openlogic.com/downloadJDK/openlogic-openjdk/8u392-b08/openlogic-openjdk-8u392-b08-linux-x64.tar.gz tar -xf openlogic-openjdk-8u392-b08-linux-x64.tar.gz mv openlogic-openjdk…...
IDEA好用插件
CodeGlance Pro 右侧代码小地图 Git Commit Template git提交信息模板 IDE Eval Reset 无限试用IDEA Maven Helper 图形化展示Maven项 One Dark theme 好看的主题 SequenceDiagram 展示方法调用链 Squaretest 生成单元测试 Translation 翻译 Lombok lombok插件…...

面试官:CSS3新增了哪些新特性?
面试官:CSS3新增了哪些新特性? 一、是什么 css,即层叠样式表(Cascading Style Sheets)的简称,是一种标记语言,由浏览器解释执行用来使页面变得更美观 css3是css的最新标准,是向后兼…...
Vite5 + Vue3 + Element Plus 前端框架搭建
为了开发一套高效使用的 Vite5 + Vue3 + Element Plus 前端框架,你可以按照以下步骤进行。话不多说,先上演示地址:Vue Shop Vite。 1, 安装开发环境 开发之前,确保你的电脑已经安装了 Node.js(建议使用最新稳定版 LTS),然后安装 Vite CLI。在命令行中运行以下命令: …...

STM32 内部 EEPROM 读写
STM32 的某些系列 MCU 自带 EEPROM。笔者使用的 STM32L151RET6 自带 16 KB 的 EEPROM,可以用来存储自定义的数据。在芯片选型时,自带 EEPROM 也可以作为一个考量点,省去了在外接 EEPROM 的烦恼。 下面简单介绍下 STM32 内部 EEPROM 的读写流…...
androidStudio sync failed GradlePropertiesModel (V2)
大家在增加模块的时候经常遇到吧?重启后就好了。 Cannot get GradlePropertiesModel (V2) for project ‘GradleProject{path’:app’}’ 然而,今天开机以后,无论如何,点击gradle的大象图标(Sync Project with Gradle Files)&…...

结构方程模型(SEM)
结构方程模型(Structural Equation Modeling)是分析多变量间因果关系的利器,在众多学科领域具有巨大应用潜力。我们前期推出的《基于R语言结构方程模型》课程通过结构方程原理介绍、结构方程全局和局域估计、模型构建和调整、潜变量分析、复合…...
基于UDP的网络编程
UDP服务端 #ifdef _WIN32 #define _WINSOCK_DEPRECATED_NO_WARNINGS #define close closesocket #include <winsock2.h> #else #include <arpa/inet.h> #include <netdb.h> #include <netinet/in.h> #in…...
vue判断组件有没有传入的slot有就渲染slot没有就渲染内部节点
GPT4国内站点:海鲸AI 在 Vue 中,你可以使用 $slots 对象来检查是否有特定的插槽内容被传递给组件。Vue 3 中的 $slots 是一个对象,其中包含了所有插槽的引用。如果插槽没有内容,对应的插槽属性将会是 undefined。 下面是一个例子…...

MS713/MS713T:CMOS 低压、4Ω四路单刀单掷开关,替代ADG713
产品简述 MS713/MS713T 是一款单芯片 CMOS 4 路可选择开关,具有低 功耗、高开关速度、低导通阻抗、低漏电和高带宽特性。其工作 电压范围是 1.8V 到 5.5V ,可以广泛应用在电池供电仪器仪表、新 一代的模数转换和数模转换系统中。其高带宽特性可用在 …...

Android 内容生成pdf文件
1.引入itext7 implementation com.itextpdf:itext7-core:7.1.13上面比较大,可以直接下载需要集成的jar包 implementation files(libs\\layout-7.1.13.jar) implementation files(libs\\kernel-7.1.13.jar) implementation files(libs\\io-7.1.13.jar) implementatio…...
Javaweb-日程管理
094.日程管理第二期_准备数据库和实体类_哔哩哔哩_bilibili navicat 下载 学生认证: Navicat 教育版 - 学生许可证 | Navicat navicat连接mysql 使用navicat连接mysql数据库创建数据库、表、转储sql文件,导入sql数据_哔哩哔哩_bilibili...

SwiftUI之深入解析如何创建一个灵活的选择器
一、前言 在 Dribbble 上找到的设计的 SwiftUI 实现时,可以尝试通过一些酷炫的筛选器扩展该项目以缩小结果列表。筛选视图将由两个独立的筛选选项组成,两者都有一些可选项可供选择。但是,在使用 UIKit 时,总是将这种类型的视图实…...

【模拟量采集1.2】电阻信号采集
【模拟量采集1.2】电阻信号采集 1 怎么测?2 测输入电阻电压即转为测模拟电压值,这里需要考虑选用怎样的辅助电阻?3 实际电路分析3.1 在不考虑 VCC-5V 电压的纹波等情况时(理想化此时输入的 VCC 就是稳定的 5V)3.2 若考…...

c++牛客总结
一、c/c语言基础 1、基础 1、指针和引用的区别 指针是一个新的变量,指向另一个变量的地址,我们可以通过这个地址来修改该另一个变量; 引用是一个别名,对引用的操作就是对变量本身进行操作;指针可以有多级 引用只有一…...

ts相关笔记(基础必看)
推荐一下小册 TypeScript 全面进阶指南,此篇笔记来源于此,记录总结,加深印象! 另外,如果想了解更多ts相关知识,可以参考我的其他笔记: vue3ts开发干货笔记TSConfig 配置(tsconfig.…...

Docker随笔
OverView 为什么需要Docker 如果我需要部署一个服务,那么我需要提前部署其他应用栈,不同的应用栈会依赖于不用的操作系统和环境。这样做会产生一些负面影响: 不同版本依赖较长的部署时间不同的Dev/Test/Prod环境 这时我们需要一个工具去解…...

uni-app 前后端调用实例 基于Springboot
锋哥原创的uni-app视频教程: 2023版uniapp从入门到上天视频教程(Java后端无废话版),火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版),火爆更新中...共计23条视频,包括:第1讲 uni…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...

PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...