链式二叉树的基本操作(C语言版)
目录
1.二叉树的定义
2.创建二叉树
3.递归遍历二叉树
1)前序遍历
2)中序遍历
3)后序遍历
4.层序遍历
5.计算节点个数
6.计算叶子节点个数
7.计算第K层节点个数
8.计算树的最大深度
9.查找值为x的节点
10.二叉树的销毁

从二叉树的概念中我们知道任何二叉树都难被分为,根,左子树,右子树,而左子树依然能被分为,根,左子树,右子树。右子树也是,所以我们这里可以采用递归的玩法来操作二叉树。
1.二叉树的定义
typedef int BTDataType;
typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;
2.创建二叉树
由于是初学,为了便于观察,我们这里手搓一个二叉树
BTNode* CreateTree()
{BTNode* n1 = (BTNode*)malloc(sizeof(BTNode));assert(n1);BTNode* n2 = (BTNode*)malloc(sizeof(BTNode));assert(n2);BTNode* n3 = (BTNode*)malloc(sizeof(BTNode));assert(n3);BTNode* n4 = (BTNode*)malloc(sizeof(BTNode));assert(n4);BTNode* n5 = (BTNode*)malloc(sizeof(BTNode));assert(n5);BTNode* n6 = (BTNode*)malloc(sizeof(BTNode));assert(n6);BTNode* n7 = (BTNode*)malloc(sizeof(BTNode));assert(n7);n1->data = 1;n2->data = 2;n3->data = 3;n4->data = 4;n5->data = 5;n6->data = 6;n1->left = n2;n1->right = n4;n2->left = n3;n2->right = NULL;n3->left = NULL;n3->right = n7;n4->left = n5;n4->right = n6;n5->left = NULL;n5->right = NULL;n6->left = NULL;n6->right = NULL;n7->left = NULL;n7->right = NULL;n7->data = 7;return n1;}
注意:上述代码并不是创建二叉树的方式,真正创建二叉树方式后序详解重点讲解。
3.递归遍历二叉树
根,左子树,右子树,遍历顺序的不同导致访问的结果也不同,先学习这三种遍历,这里递归较为简单,为我们后面做一些二叉树的oj题目打下基础。
按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历:
1)前序遍历
前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。
// 二叉树前序遍历
void PreOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}printf("%d ", root->data);PreOrder(root->left);PreOrder(root->right);
}
2)中序遍历
中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。
// 二叉树中序遍历
void InOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}InOrder(root->left);printf("%d ", root->data);InOrder(root->right);
}
3)后序遍历
后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。
// 二叉树后序遍历
void PostOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}PostOrder(root->left);PostOrder(root->right);printf("%d ", root->data);
}
4.层序遍历
层序遍历,自上到下,自左到右依次访问数的结点就是层序遍历。
思想(借助一个队列):
1、先将根节点入队,然后开始从队头出数据
2、出队头的数据同时将队头左右子树的结点入队(遇到NULL则不入队)
3、重复第二步,直到队列为空
//层序遍历
void TreeLevelOrder(BTNode* root)
{Queue q;QueueInit(&q);if (root){QueuePush(&q, root);}while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);printf("%d ", front->data);if (front->left)QueuePush(&q, front->left);if (front->right)QueuePush(&q, front->right);}printf("\n");
}
5.计算节点个数
求树的结点总数时,可以将问题拆解成子问题:
1.若为空,则结点个数为0。
2.若不为空,则结点个数 = 左子树结点个数 + 右子树结点个数 + 1(自己)
int TreeSize(BTNode* root)
{return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
6.计算叶子节点个数
子问题拆解:
1.若为空,则叶子结点个数为0。
2.若结点的左指针和右指针均为空,则叶子结点个数为1。
3.除上述两种情况外,说明该树存在子树,其叶子结点个数 = 左子树的叶子结点个数 + 右子树的叶子结点个数。
//叶子节点个数
int TreeLeaSize(BTNode* root)
{if (root == NULL)return 0;return (root->left == NULL && root->right == NULL) ? 1 : TreeLeaSize(root->left) + TreeLeaSize(root->right);
}
7.计算第K层节点个数
这里我们要控制好递归的深度,我们依然把他给转换为子问题思考。
思路:
1、为空和非法时,结点个数为0个
2、为第一层时,结点个数为1个
3、不为空且合法时,第K层的结点个数=第K-1层的左子树结点个数+第K-1层的右子树结点个数
int TreeKLevel(BTNode* root, int k)
{assert(k > 0);if (root == NULL){return 0;}if (k == 1){return 1;}return TreeKLevel(root->left, k - 1) + TreeKLevel(root->right, k - 1);
}
8.计算树的最大深度
我们如何找出最深的那一条途径?这里是一个选择的问题。如果一条途径递归到倒数第二层,左边有一个叶子节点,右边无节点,那么我们应该选择左边作为它的最深途径。
思路:
1.若为空,则深度为0。
2.若不为空,则树的最大深度 = 左右子树中深度较大的值 + 1。
int TreeHeigh(BTNode* root)
{if (root == NULL)return 0;return TreeHeigh(root->left) > TreeHeigh(root->right) ? TreeHeigh(root->left) + 1 :TreeHeigh(root->right) + 1;
}
9.查找值为x的节点
思路:
1.先判断根结点是否是目标结点。
2.再去左子树中寻找。
3.最后去右子树中寻找。
BTNode* TreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}//先去左树找BTNode* lret = TreeFind(root->left, x);if (lret)return lret;//再去右树找BTNode* rret = TreeFind(root->right, x);if (rret)return rret;return NULL;
}
10.二叉树的销毁
void BinaryTressDestory(BTNode* root)
{if (root == NULL)return;BinaryTressDestory(root->left);BinaryTressDestory(root->right);free(root);
}
相关文章:
链式二叉树的基本操作(C语言版)
目录 1.二叉树的定义 2.创建二叉树 3.递归遍历二叉树 1)前序遍历 2)中序遍历 3)后序遍历 4.层序遍历 5.计算节点个数 6.计算叶子节点个数 7.计算第K层节点个数 8.计算树的最大深度 9.查找值为x的节点 10.二叉树的销毁 从二叉树…...
Tcp三次握手四次挥手和SSL/TLS
1.Tcp三次握手四次挥手: 1.1基本概念: TCP(三次握手和四次挥手)是用于建立和终止可靠传输连接的过程。TCP协议是一种面向连接的传输层协议,确保数据在网络上可靠、有序地传输。下面详细解释三次握手和四次挥手的工作机…...
大棚分割数据集,40765对影像,16.9g数据量,0.8米高分二,纯手工标注(arcgis标注)的大规模农业大棚分割数据集。
数据集名称: )“Greenhouse Segmentation Dataset (GSD)” 数据集规模: 包含40,765对用于大棚分割的影像数据,每对影像包括一张原始图像和相应的分割标签图。 数据量: 总数据量约为16.9GB,适合存储在现…...
Jenkins插件安装失败时这么做就搞定啦!
1.网络或墙的问题导致插件下载安装失败 这种错误提示很明显,就是无法连接到插件下载地址,导致插件下载失败。 解决方法 为Jenkins更换源 点击Jenkins主页面左侧列表中【系统管理】—— 下拉找到【管理插件】 选择【高级】选项卡 替换最下方【升级站点…...
优化器与现有网络模型的修改
文章目录 一、优化器是什么二、优化器的使用三、分类模型VGG16四、现有网络模型的修改 一、优化器是什么 优化器(Optimizer)是一个算法,用于在训练过程中调整模型的参数,以便最小化损失函数(Loss Function)…...
kafka 超详细的消息订阅与消息消费几种方式
kafka 消息订阅与消息消费几种方式 本文主要内容 消费者订阅几种方式 订阅多个主题 按正则表达式订阅 消息消费几种方式 按分区消费 按主题消费 不区分 “ 笔者建议一开始学习Kafka最好不要用SpringBoot 集成方式,因为SpringBoot推崇用注解方式,比如KafkaList…...
C++ 第三讲:内存管理
C 第三讲:内存管理 1.C内存分布2.内存管理方式2.1C语言内存管理方式2.2C内存管理方式2.2.1new\delete操作内置类型2.2.2new\delete操作自定义类型 3.operator new与operator delete函数4.new和delete实现原理4.1内置类型4.2自定义类型 5.定位new5.1内存池的基本了解…...
LeeCode打卡第二十九天
LeeCode打卡第二十九天 第一题:岛屿数量(LeeCode第200题): 给你一个由 1(陆地)和 0(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只…...
阿里云专业翻译api对接
最近我们一个商城项目涉及多语言切换,默认中文。用户切换语言可选英语和阿拉伯语言,前端APP和后端返回动态数据都要根据用户选择语言来展示。前端静态内容都做了三套语言,后端商品为了适用这种多语言我们也进行了改造。每一件商品名称&#x…...
基于Spring Boot的能源管理系统+建筑能耗+建筑能耗监测系统+节能监测系统+能耗监测+建筑能耗监测
介绍 建筑节能监测系统是基于计算机网络、物联网、大数据和数据可视化等多种技术融合形成的一套节能监测系统。 系统实现了对建筑电、水、热,气等能源、资源消耗情况的实时监测和预警、动态分析和评估,为用户建立了科学、系统的节能分析方法,…...
大数据新视界 --大数据大厂之 Cassandra 分布式数据库:高可用数据存储的新选择
💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...
ROS第五梯:ROS+VSCode+C++单步调试
解决问题:在ROS项目中进行断点调试。 第一步:创建一个ROS项目或者打开一个现有的ROS项目。 第二步:修改c_cpp_properties.json 增加一段命令: "compileCommands": "${workspaceFolder}/build/compile_commands.json"第三…...
SLA 概念和计算方法
SLA 概念和计算方法 SLA SLA:服务等级协议(简称:SLA,全称:service level agreement) 网站服务可用性的一个保证 9越多代表全年服务可用时间越长服务更可靠,停机时间越短,反之亦然…...
C++比大小游戏
目录 开头程序程序的流程图程序游玩的效果下一篇博客要说的东西 开头 大家好,我叫这是我58。 程序 #include <iostream> #include <Windows.h> using namespace std; int main() {int ir 1;char chparr[2] { 0 };int ip1 0;int ip2 0;int i 1;c…...
PCIe进阶之TL:Memory, I/O, and Configuration Request Rules TPH Rules
1 Memory, I/O, and Configuration Request Rules 下述规则适用于 Memory 请求、IO 请求和配置请求。 除了公共的 header 字段外,所有 Memory 请求、IO 请求和配置请求还包括以下字段: (1)Requester ID[15:0] 和 Tag[9:0],组成了 Transaction ID 。 (2)Last DW BE[3:0]…...
【初阶数据结构】一文讲清楚 “堆” 和 “堆排序” -- 树和二叉树(二)(内含TOP-K问题)
文章目录 前言1. 堆1.1 堆的概念1.2 堆的分类 2. 堆的实现2.1 堆的结构体设置2.2 堆的初始化2.3 堆的销毁2.4 添加数据到堆2.4.1 "向上调整"算法 2.5 从堆中删除数据2.5.1 “向下调整”算法 2.6 堆的其它各种方法接口函数 3. 堆排序3.1 堆排序的代码实现 4. TOP-K问题…...
sqli-lab靶场学习(二)——Less8-10(盲注、时间盲注)
Less8 第八关依然是先看一般状态 http://localhost/sqli-labs/Less-8/?id1 然后用单引号闭合: http://localhost/sqli-labs/Less-8/?id1 这关的问题在于报错是不显示,那没办法通过上篇文章的updatexml大法处理。对于这种情况,需要用“盲…...
Dijkstra算法和BFS算法(单源最短路径)
基于你设计的带权有向图,从某一结点出发,执行Dijkstra算法求单源最短路径。用文字描述每一轮执行的过程 文字描述:用BFS算法求单源最短路径的过程 Dijkstra 算法 BFS算法 广度优先算法...
在WordPress中最佳Elementor主题推荐:专家级指南
对于已经在WordPress和Elementor上有丰富经验的用户来说,选择功能强大且高度灵活的主题,能大大提升网站的表现和定制能力。今天,我们来介绍六款适合用户的专家级Elementor主题:Sydney、Blocksy、Rife Free、Customify、Deep和Laye…...
关于RabbitMQ消息丢失的解决方案
RabbitMQ如何保证消息的可靠性传输 一、消息丢失的原因 1. 生产者端 网络问题: 原因:生产者与RabbitMQ服务器之间的网络连接不稳定或中断,导致消息在传输过程中丢失。解决方案:确保网络连接稳定,监控网络状态&#x…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
