数据结构初阶:二叉树(四)
概述:本篇博客主要介绍链式结构二叉树的实现。
目录
1.实现链式结构二叉树
1.1 二叉树的头文件(tree.h)
1.2 创建二叉树
1.3 前中后序遍历
1.3.1 遍历规则
1.3.1.1 前序遍历代码实现
1.3.1.2 中序遍历代码实现
1.3.1.3 后序遍历代码实现
1.4 二叉树结点的个数
1.5 二叉树叶子结点个数
1.6 二叉树第k层结点个数
1.7 二叉树的深度/高度
编辑
1.8 查找值为x的结点
1.9 二叉树的销毁
2. 小结

1.实现链式结构二叉树
1.1 二叉树的头文件(tree.h)
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>//定义链式结构二叉树
//二叉树结点的结构
typedef char BTDataType;
typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;//前序遍历
void preOrder(BTNode* root);
//中序遍历
void InOrder(BTNode* root);
//后序遍历
void postOrder(BTNode* root);//二叉树结点个数
int BinaryTreeSize(BTNode* root);
//void BinaryTreeSize(BTNode* root,int* psize);//二叉树叶子结点个数
int BinaryTreeLeafSize(BTNode* root);//二叉树第k层结点个数
int BinaryTreeLevelKSize(BTNode* root, int k);//二叉树的深度/高度
int BinaryTreeDepth(BTNode* root);//二叉树查找值为x的结点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);//二叉树销毁
void BinaryTreeDestroy(BTNode** root);//层序遍历
void LevelOrder(BTNode* root);//判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root);
1.2 创建二叉树
用链表来表示一颗二叉树,即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址,其结构如下:
//定义链式结构二叉树
//二叉树结点的结构
typedef char BTDataType;
typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left; // 指向当前结点左孩子struct BinaryTreeNode* right; // 指向当前结点右孩子
}BTNode;
二叉树的创建方式比较复杂,为了更好走进二叉树的学习中,我们先手动构建一颗链式二叉树。
#include"Tree.h"
BTNode* buyNode(char x)
{BTNode* node = (BTNode*)malloc(sizeof(BTNode));node->data = x;node->left = node->right = NULL;return node;
}
BTNode* creatBinaryTree()
{BTNode* nodeA = buyNode('A');BTNode* nodeB = buyNode('B');BTNode* nodeC = buyNode('C');BTNode* nodeD = buyNode('D');BTNode* nodeE = buyNode('E');BTNode* nodeF = buyNode('F');nodeA->left = nodeB;nodeA->right = nodeC;nodeB->left = nodeD;nodeC->left = nodeE;nodeC->right = nodeF;return nodeA;
}
回顾二叉树的概念,二叉树分为空树和非空二叉树,非空二叉树由根结点根结点的左子树、根结点的右子树组成的。

根结点的左子树和右子树分别又是由子树结点、子树结点的左子树、子树结点的右子树组成的,因此二叉树定义式递归式的,后续链式二叉树的操作基本都是按照该概念实现的。
1.3 前中后序遍历
二叉树的操作离不开树的遍历,我们先来看一下二叉树的遍历有哪些方式。

1.3.1 遍历规则
按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历:
1)前序遍历(Preorder Traversal 亦称先序遍历):访问根结点的操作发生在遍历其左右子树之前
访问顺序为:根结点、左子树、右子树
2)中序遍历(Inorder Traversal):访问根结点的操作发⽣在遍历其左右子树之中(间)
访问顺序为:左子树、根结点、右子树
3)后序遍历(Postorder Traversal):访问根结点的操作发生在遍历其左右子树之后
访问顺序为:左子树、右子树、根结点
1.3.1.1 前序遍历代码实现
void preOrder(BTNode* root)
{if(root == NULL){printf("NULL ");return;}printf("%c ", root->data);preOrder(root->left);preOrder(root->right);
}
逻辑概述:
这段 代码定义了一个先序遍历二叉树的函数 `preOrder`。函数的参数是一个指向二叉树节点的指针 `root`。
如果 `root` 为空,函数会输出 `NULL` 并返回。否则,函数会先输出当前节点的数据,然后对左子树和右子树分别递归调用 `preOrder` 函数进行先序遍历。
在代码中,`printf("%c ", root->data);` 用于输出当前节点的数据,假设 `data` 是字符类型。


1.3.1.2 中序遍历代码实现
void InOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}InOrder(root->left);printf("%c ", root->data);InOrder(root->right);
}
逻辑概述:
这段代码是一个二叉树的中序遍历函数。其功能是:如果根节点为空,输出"NULL "并返回;否则,先对左子树进行中序遍历,然后输出根节点的数据,最后对右子树进行中序遍历。其实现过程与常见的二叉树中序遍历的逻辑一致。

1.3.1.3 后序遍历代码实现
void postOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}postOrder(root->left);postOrder(root->right);printf("%c ", root->data);
}
逻辑概述:
这段代码定义了一个二叉树的后序遍历函数 `postOrder` 。函数的作用是:如果根节点为空,输出 `"NULL "` 并返回;否则,先对左子树进行后序遍历,再对右子树进行后序遍历,最后输出根节点的数据。这符合二叉树后序遍历的逻辑,即先遍历左子树,再遍历右子树,最后访问根节点。

1.4 二叉树结点的个数
int BinaryTreeSize(BTNode* root)
{if (root == NULL){return 0;}if (root->left == NULL && root->right == NULL){return 1;}return 1 + BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}
逻辑概述:
这段代码定义了一个计算二叉树节点个数的函数 `BinaryTreeSize` 。
函数的逻辑是:如果根节点为空,返回 0;如果根节点的左右子树都为空,返回 1;否则,返回 1 加上左子树的节点个数和右子树的节点个数。其中,左子树和右子树的节点个数通过递归调用 `BinaryTreeLeafSize` 函数来计算。

1.5 二叉树叶子结点个数
//二叉树叶子结点个数
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);
}
逻辑概述:
这段代码定义了一个计算二叉树叶子结点个数的函数`BinaryTreeLeafSize`。
函数的逻辑是:如果根节点为空,返回0;如果根节点的左右子树都为空,说明该节点为叶子节点,返回1;否则,通过递归调用函数本身,分别计算左子树和右子树的叶子节点个数,并将它们相加后返回。

1.6 二叉树第k层结点个数
// 计算二叉树第 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);
}
逻辑概述:
这段代码的功能是计算二叉树中第
k层的节点个数。如果根节点为空,返回0。如果k等于1,说明当前根节点就是第k层的节点,返回1。否则,通过递归调用函数本身,分别计算左子树和右子树中第k - 1层的节点个数,并将它们相加后返回。

1.7 二叉树的深度/高度
//二叉树的深度/高度
int BinaryTreeDepth(BTNode* root)
{if (root == NULL){return 0;}int leftDep = BinaryTreeDepth(root->left);int rightDep = BinaryTreeDepth(root->right);return 1 + (leftDep > rightDep ? leftDep : rightDep);
}
逻辑概述:
这段代码定义了一个计算二叉树深度(高度)的函数 `BinaryTreeDepth` 。
函数的逻辑是:如果根节点为空,返回 0 。然后分别计算左子树和右子树的深度,记为 `leftDep` 和 `rightDep` 。最后,二叉树的深度为 1 加上 `leftDep` 和 `rightDep` 中的较大值。
1.8 查找值为x的结点
//二叉树查找值为x的结点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BTNode* leftFind = BinaryTreeFind(root->left, x);if (leftFind){return leftFind;}BTNode* rightFind = BinaryTreeFind(root->right, x);if (rightFind){return rightFind;}return NULL;
}
逻辑概述:
这段代码定义了一个在二叉树中查找值为`x`的节点的函数`BinaryTreeFind`。
函数的执行过程如下:
- 如果根节点为空,直接返回`NULL`,表示未找到。
- 如果根节点的值等于`x`,则返回根节点。
- 然后在左子树中递归查找值为`x`的节点,如果找到则返回该节点。
- 如果在左子树中未找到,再在右子树中递归查找值为`x`的节点,如果找到则返回该节点。
- 如果在整个二叉树中都未找到值为`x`的节点,则最终返回`NULL`。

1.9 二叉树的销毁
//二叉树销毁
void BinaryTreeDestroy(BTNode** root)
{if (*root == NULL){return;}BinaryTreeDestroy(&((*root)->left));BinaryTreeDestroy(&((*root)->right));*root == NULL;
}

2. 小结
以上便是本篇博客的所有内容了,如果这篇博客能给大家带来知识,还请大家多多点赞。

相关文章:
数据结构初阶:二叉树(四)
概述:本篇博客主要介绍链式结构二叉树的实现。 目录 1.实现链式结构二叉树 1.1 二叉树的头文件(tree.h) 1.2 创建二叉树 1.3 前中后序遍历 1.3.1 遍历规则 1.3.1.1 前序遍历代码实现 1.3.1.2 中序遍历代码实现 1.3.1.3 后序遍历代…...
配置Intel Realsense D405驱动与ROS包
配置sdk使用 Ubuntu20.04LTS下安装Intel Realsense D435i驱动与ROS包_realsense的驱动包-CSDN博客 中的方法一 之后不通过apt安装包,使用官方的安装步骤直接clone https://github.com/IntelRealSense/realsense-ros/tree/ros1-legacy 从这一步开始 执行完 这一步…...
Python爬虫实战:基于 Python Scrapy 框架的百度指数数据爬取研究
一、引言 1.1 研究背景 在当今信息时代,市场调研和趋势分析对于企业和研究机构至关重要。百度指数能够精准反映关键词在百度搜索引擎上的热度变化情况,为市场需求洞察、消费者兴趣分析等提供了极具价值的数据支持。通过对百度指数数据的爬取和分析,企业可以及时调整营销策略…...
【Easylive】consumes = MediaType.MULTIPART_FORM_DATA_VALUE 与 @RequestPart
【Easylive】项目常见问题解答(自用&持续更新中…) 汇总版 consumes MediaType.MULTIPART_FORM_DATA_VALUE 的作用 1. 定义请求的数据格式 • 作用:告诉 Feign 和 HTTP 客户端,这个接口 接收的是 multipart/form-data 格式的…...
【最新版】沃德代驾源码全开源+前端uniapp
一.系统介绍 基于ThinkPHPUniapp开发的代驾软件。系统源码全开源,代驾软件的主要功能包括预约代驾、在线抢单、一键定位、在线支付、车主登记和代驾司机实名登记等。用户可以通过小程序预约代驾服务,系统会估算代驾价格并推送附近代驾司机供用户选择&…...
前端频繁调用后端接口问题思考
针对前端频繁调用后端接口的问题,以下是一套分步解决方案,结合Java后端技术栈: 1. 实时数据场景:WebSocket/SSE 适用场景:实时股票行情、即时聊天、监控仪表盘 // Spring WebSocket 配置示例 Configuration EnableW…...
Linux:权限相关问题
文章目录 shell命令以及运行的原理Linux权限执行权限更改目录权限缺省权限粘滞位 shell命令以及运行的原理 操作系统分为内核和外壳程序,xshell是外壳程序,外壳程序包括我们windows桌面上的图形化界面,本质都是翻译给核心处理,再显…...
AI数字人:元宇宙舞台上的闪耀新星(7/10)
摘要:AI数字人作为元宇宙核心角色,提升交互体验,推动内容生产变革,助力产业数字化转型。其应用场景涵盖虚拟社交、智能客服、教育、商业营销等,面临技术瓶颈与行业规范缺失等挑战,未来有望突破技术限制&…...
【Linux】冯诺依曼体系结构及操作系统架构图的具体剖析
目录 一、冯诺依曼体系结构 1、结构图 2、结构图介绍: 3、冯诺依曼体系的数据流动介绍 4、为什么在该体系结构中要存在内存? 二、操作系统架构图介绍 1、操作系统架构图 2、解析操作系统架构图 3、为什么要有操作系统? 前些天发现了一…...
算法训练营第一天|704.二分查找、27.移除元素、977.有序数组的平方
数组理论基础 1.数组是存放在连续内存空间上的相同类型数据的集合。 2.数组的元素是不能删除的,只能覆盖。 3.不同语言不一样,在C中,二维数组是连续分布的 704.二分查找 题目 思路与解法 第一想法: 简单的二分查找,…...
c++ 互斥锁
为练习c 线程同步,做了LeeCode 1114题. 按序打印: 给你一个类: public class Foo {public void first() { print("first"); }public void second() { print("second"); }public void third() { print("third"…...
3.1 Agent定义与分类:自主Agent、协作Agent与混合Agent的特点
随着人工智能技术的快速发展,智能代理(Agent)作为一种能够感知环境、自主决策并采取行动的计算实体,已成为人工智能领域的重要研究对象和应用工具。特别是在大模型(Large Models)的赋能下,Agent…...
什么是CAN的非破坏仲裁?
CAN总线的非破坏性仲裁是一种在多个设备同时发送数据时,通过标识符(ID)优先级来决定哪个设备可以优先发送数据的机制。其核心思想是:当多个设备同时发送数据时,ID值较小的数据具有更高的优先级,能够优先…...
Vite vs Webpack 优势对比
Vite vs Webpack 优势对比 核心优势图解 #mermaid-svg-jeTCEp1bu9QruHjL {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-jeTCEp1bu9QruHjL .error-icon{fill:#552222;}#mermaid-svg-jeTCEp1bu9QruHjL .error-text{…...
中波红外相机的应用领域及介绍
科技日新月异,无人机技术在众多领域已显露其卓越性能。当中波红外相机与无人机携手合作,安防视频监控和精细巡检便迎来了颠覆性的变革。本文旨在深入剖析无人机搭载中波红外相机的技术优势、广阔应用前景及实际案例,以此彰显其不可估量的潜力…...
【C++】vector扩容缩容
vector扩容缩容 1 扩容 一般来说,主要是重新分配内存 2 缩容 resize 缩小后,vector 的容量(capacity())可能保持不变,需要显式调用 shrink_to_fit() 来释放内存。 验证代码: #include <vector>…...
240423 leetcode exercises
240423 leetcode exercises jarringslee 文章目录 240423 leetcode exercises[33. 搜索旋转排序数组](https://leetcode.cn/problems/search-in-rotated-sorted-array/)🔁先找旋转点 再分段二分🔁利用布尔变量进行一次二分 [LCR 009. 乘积小于 K 的子数…...
重装系统 之 Dell戴尔服务器 PowerEdge R750xs + window server2012r2 || 2016
因要求需要给新服务器装个 win server2012或者2016系统 XXX使用U盘制作PE系统U盘安装系统不行,适合普通win8,win10,win11U盘制作PE系统U盘安装win10系统教程U盘制作PE系统U盘安装win10系统教程https://mp.weixin.qq.com/s/t0W8aNJaHPAU8T78nh…...
7-1 三种语言的单词转换
编写程序实现:首先从键盘输入若干个中文与英文单词的偶对,以空行作结束标记;再输入若干个英文与丹麦文单词的偶对,以空行作结束标记。然后输入一个中文单词,输出对应的丹麦文单词;若不存在该单词࿰…...
深度学习--卷积神经网络调整学习率
文章目录 前言一、学习率1、什么学习率2、什么是调整学习率3、目的 二、调整方法1、有序调整1)有序调整StepLR(等间隔调整学习率)2)有序调整MultiStepLR(多间隔调整学习率)3)有序调整ExponentialLR (指数衰减调整学习率)4)有序调整…...
Apache中间件解析漏洞与安全加固
Apache作为全球使用最广泛的Web服务器,其灵活性和模块化设计使其成为开发者的首选。然而,其解析机制和配置不当可能导致严重的安全风险。本文将从漏洞原理、攻击案例和安全配置三个维度,结合真实场景,解析…...
TORL:解锁大模型推理新境界,强化学习与工具融合的创新变革
在大语言模型(LLMs)推理能力不断提升的当下,如何让模型更高效地解决复杂计算和推理任务成为关键。本文介绍的TORL(Tool-Integrated Reinforcement Learning)框架给出了全新方案。它通过强化学习让大模型自主运用计算工…...
Maven 依赖坐标与BOM统一管理
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
华为OD机试真题——通过软盘拷贝文件(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
2025 A卷 200分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C、C语言、GO六种语言的最佳实现方式! 本文收录于专栏:《2025华为OD真题目录全流程解析/备考攻略/经验…...
participant中participantid的来源和用途
ParticipantQos中的wire_protocol(WireProtocolConfigQos类型)成员中存在participant_id成员: DomainParticipantImpl::DomainParticipantImpl(...) {...participant_id_ qos_.wire_protocol().participant_id; } 如果用户不指定&…...
【论文阅读25】-滑坡时间预测-PFTF
本文提出了一种前瞻性失稳时间预测方法(PFTF),可用于实时或拟实时预测滑坡、冰崩等地质灾害的失稳时间。该方法基于改进的反速度法(Inverse Velocity Method),通过多窗口平滑、迭代更新、以及自动识别加速起…...
解决AWS中ELB的目标群组中出现不正常数
当如下图中不正常数>0且小于等于目标总数时,我们需要更改相应的配置,这是针对那些没有检查方式的实例,从而采取反向配置方式 1、切换到运行健康检查,然后进行编辑各个检查指标 2、编辑如下 3、切换到属性进行编辑如下...
【TeamFlow】4.3.4 长度单位
以下是针对长度单位的实现方案,包含完整的文件结构和详细实现: 文件结构更新 src/ └── units/└── base/├── length.rs # 基础长度单位└── length/├── metric.rs # 公制单位├── imperial.rs # 英制单位├── astronomical.r…...
【Qt/C++】QPrinter关于QInternal::Printer的解析
1. 问题分析 QInternal::Printer在Qt框架中并不是一个直接暴露给用户的API。相反,它是一个枚举值,用于标识QPaintDevice的类型。在Qt中,QPaintDevice是一个抽象类,用于任何可以进行绘制的设备,如窗口、图像、打印机等…...
方案精读:华为智慧园区解决方案【附全文阅读】
随着数字化发展,园区面临转型需求。华为智慧园区解决方案应运而生,其基于物联网、大数据、云计算等技术,构建数字化使能平台,涵盖综合安防、人员与车辆管理、绿色能源、资产管理等多领域应用场景,解决传统园区在安全、效率、能耗等方面的痛点。通过实现系统互联、数据融合…...

