数据结构与算法学习笔记-二叉树的顺序存储表示法和实现(C语言)
目录
前言
1.数组和结构体相关的一些知识
1.数组
2.结构体数组
2.二叉树的顺序存储表示法和实现
1.定义
2.初始化
3.先序遍历二叉树
4.中序遍历二叉树
5.后序遍历二叉树
6.完整代码
前言
二叉树的非递归的表示和实现。
1.数组和结构体相关的一些知识
1.数组
在C语言中,可以将数组作为参数传递给函数。当数组作为参数传递时,实际上传递给函数的是数组的地址,而不是数组的副本。这意味着,在函数内部对数组进行的修改会影响到原始数组。
例如在下面的代码中,我们把数组名作为参数传递给modifyArray函数,在函数中修改数组的值,main函数打印原来的数组,会发现原来的数组也被修改。
#include <stdio.h>
#include <stdlib.h>void modifyArray(int *s,int size){for (int i = 0; i < size; i++) {s[i] = s[i] * 10;}printf("\n");
}int main(int argc, const char *argv[]) {int arr[5] = {1,2,3,4,5};int length = sizeof(arr) / sizeof(arr[0]);printf("修改之前的数组:\n");for (int i = 0; i < length;i++) {printf("%d\t",arr[i]);}modifyArray(arr,length);printf("\n修改之前的数组:\n");for (int i = 0; i < length;i++) {printf("%d\t",arr[i]);}printf("\n");return 0;
}
当然上述的函数我们还可以写成数组的形式。
void modifyArray(int s[],int size){for (int i = 0; i < size; i++) {s[i] = s[i] * 10;}printf("\n");
}
2.结构体数组
在上述的代码中,我们使用数组操作基本数据类型非常的方便。当时当我们需要自定义数据类型的时候,上述的代码就不满足我们的需求了。例如我们需要表示学生数组的时候,因为每个学生都有自己的属性,姓名,年龄等等,这个时候我们就需要使用结构体数组。
在数据结构中,我们有时候需要使用数组表示一些数据类型,因此有时候我们需要把数组声明为全局函数。代码实例如下:
#include <stdio.h>
#include <stdlib.h>// 学生结构体
typedef struct {char name[50]; // 姓名int age; // 年龄
} Student;int main() {// 创建一个包含3个学生对象的数组并初始化Student students[3] = {{"张三", 20},{"李四", 21},{"王五", 22}};// 输出学生信息printf("学生信息如下:\n");for (int i = 0; i < 3; i++) {printf("学生姓名:%s\n", students[i].name);printf("学生年龄:%d\n", students[i].age);}return 0;
}
2.二叉树的顺序存储表示法和实现
图1.完全二叉树
图2.普通二叉树
我们使用一组连续的存储空间表示树的结构。按照从上到下、从左到右的顺序存储完全二叉树的的节点,对于一般二叉树上的点,我们使用0表示不存在该节点。
对于图1来说,内存中的存储结构如下图3所示。
图3.完全二叉树的存储结构
如果不是二叉树,假如我们使用0表示结点不存在,图2所示的存储结构如图4所示。
图4.普通二叉树
下面我们看看如果使用代码来实现。
1.定义
我们使用数组实现二叉树的顺序存储
#define MAX_TREE_SIZE 100typedef char TElemType;
typedef int Status;typedef TElemType SqBiTree[MAX_TREE_SIZE];
2.初始化
初始化时候,将数组中的元素全部设为"\0"
// 初始化二叉树
Status initSqBiTree(SqBiTree tree) {for (int i = 0; i< MAX_TREE_SIZE; i++) {tree[i] = '\0';}// 将二叉树所有元素初始化为空return 1; // 初始化成功
}
3.先序遍历二叉树
遍历二叉树之前我们观察下根节点、左子树节点、右子树节点的规律。
根节点的下标为a[0].左子树上的节点的下标依次为1,3,...2*i+1,右子树上的节点的下标依次为2,4,...2*i+2
// 前序遍历二叉树
void preOrderTraverse(SqBiTree tree, int node_index) {if (node_index < MAX_TREE_SIZE && tree[node_index] != '\0') {// 访问根节点printf("%c ", tree[node_index]);// 递归遍历左子树preOrderTraverse(tree, 2 * node_index + 1);// 递归遍历右子树preOrderTraverse(tree, 2 * node_index + 2);}
}
4.中序遍历二叉树
// 中序遍历二叉树
void inOrderTraverse(SqBiTree tree, int node_index) {if (node_index < MAX_TREE_SIZE && tree[node_index] != '\0') {// 递归遍历左子树inOrderTraverse(tree, 2 * node_index + 1);// 访问根节点printf("%c ", tree[node_index]);// 递归遍历右子树inOrderTraverse(tree, 2 * node_index + 2);}
}
5.后序遍历二叉树
// 后序遍历二叉树
void postOrderTraverse(SqBiTree tree, int node_index) {if (node_index < MAX_TREE_SIZE && tree[node_index] != '\0') {// 递归遍历左子树postOrderTraverse(tree, 2 * node_index + 1);// 递归遍历右子树postOrderTraverse(tree, 2 * node_index + 2);// 访问根节点printf("%c ", tree[node_index]);}
}
6.完整代码
#include <stdio.h>#define MAX_TREE_SIZE 100typedef char TElemType;
typedef int Status;typedef TElemType SqBiTree[MAX_TREE_SIZE];// 初始化二叉树
Status initSqBiTree(SqBiTree tree) {for (int i = 0; i< MAX_TREE_SIZE; i++) {tree[i] = '\0';}// 将二叉树所有元素初始化为空return 1; // 初始化成功
}// 前序遍历二叉树
void preOrderTraverse(SqBiTree tree, int node_index) {if (node_index < MAX_TREE_SIZE && tree[node_index] != '\0') {// 访问根节点printf("%c ", tree[node_index]);// 递归遍历左子树preOrderTraverse(tree, 2 * node_index + 1);// 递归遍历右子树preOrderTraverse(tree, 2 * node_index + 2);}
}// 中序遍历二叉树
void inOrderTraverse(SqBiTree tree, int node_index) {if (node_index < MAX_TREE_SIZE && tree[node_index] != '\0') {// 递归遍历左子树inOrderTraverse(tree, 2 * node_index + 1);// 访问根节点printf("%c ", tree[node_index]);// 递归遍历右子树inOrderTraverse(tree, 2 * node_index + 2);}
}// 后序遍历二叉树
void postOrderTraverse(SqBiTree tree, int node_index) {if (node_index < MAX_TREE_SIZE && tree[node_index] != '\0') {// 递归遍历左子树postOrderTraverse(tree, 2 * node_index + 1);// 递归遍历右子树postOrderTraverse(tree, 2 * node_index + 2);// 访问根节点printf("%c ", tree[node_index]);}
}int main(int argc, const char *argv[]) {SqBiTree tree;// 初始化二叉树initSqBiTree(tree);// 构造一个简单的二叉树,根节点为'A',左子树为'B',右子树为'C'tree[0] = 'A';tree[1] = 'B';tree[2] = 'C';tree[3] = 'D';tree[4] = 'E';tree[5] = '\0';tree[6] = '\0';// 输出初始化后的二叉树printf("前序遍历结果为:");preOrderTraverse(tree, 0);printf("\n");printf("中序遍历结果为:");inOrderTraverse(tree, 0);printf("\n");printf("后序遍历结果为:");postOrderTraverse(tree, 0);printf("\n");return 0;
}// 后序遍历二叉树
void postOrderTraverse(SqBiTree tree, int node_index) {if (node_index < MAX_TREE_SIZE && tree[node_index] != '\0') {// 递归遍历左子树postOrderTraverse(tree, 2 * node_index + 1);// 递归遍历右子树postOrderTraverse(tree, 2 * node_index + 2);// 访问根节点printf("%c ", tree[node_index]);}
}int main(int argc, const char *argv[]) {SqBiTree tree;// 初始化二叉树initSqBiTree(tree);// 构造一个简单的二叉树,根节点为'A',左子树为'B',右子树为'C'tree[0] = 'A';tree[1] = 'B';tree[2] = 'C';tree[3] = 'D';tree[4] = 'E';tree[5] = '\0';tree[6] = '\0';// 输出初始化后的二叉树printf("前序遍历结果为:");preOrderTraverse(tree, 0);printf("\n");printf("中序遍历结果为:");inOrderTraverse(tree, 0);printf("\n");printf("后序遍历结果为:");postOrderTraverse(tree, 0);printf("\n");return 0;
}
在main函数中,我们构建了一个图2所示的二叉树,控制台打印信息如下:
相关文章:

数据结构与算法学习笔记-二叉树的顺序存储表示法和实现(C语言)
目录 前言 1.数组和结构体相关的一些知识 1.数组 2.结构体数组 2.二叉树的顺序存储表示法和实现 1.定义 2.初始化 3.先序遍历二叉树 4.中序遍历二叉树 5.后序遍历二叉树 6.完整代码 前言 二叉树的非递归的表示和实现。 1.数组和结构体相关的一些知识 1.数组 在C语…...
如何在Windows和Linux中杀死Python进程
在开发和运行Python脚本的过程中,有时我们需要强制结束正在运行的Python进程。这可能是因为脚本运行出现了不可预见的错误,或者我们需要停止一个长时间执行的任务。无论原因如何,了解如何在不同操作系统中正确、安全地终止Python进程都是一项…...

零基础怎么快速进行单细胞分析?
近一段时间正在努力学习单细胞相关的理论知识,发现单细胞测序和普通的真核细胞的转录组非常相似。两者之间的最大的区别在于,一个测的是单个细胞的表达,一个测的是一堆细胞的表达之和。所以从这里就可以理解,为什么网上很多教程都…...
力扣数据库题库学习(5.10日)--1965. 丢失信息的雇员
1965. 丢失信息的雇员 问题链接🐷 思路分析 先看问题的描述 编写解决方案,找到所有 丢失信息 的雇员 id。当满足下面一个条件时,就被认为是雇员的信息丢失:雇员的 姓名 丢失了,或者雇员的 薪水信息 丢失了返回这些…...

漫威争锋Marvel Rivals怎么搜索 锁区怎么搜 游戏搜不到怎么办
即将问世的《漫威争锋》(Marvel Rivals)作为一款万众期待的PvP射击游戏新星,荣耀携手漫威官方网站共同推出。定档5月11日清晨9时,封闭Alpha测试阶段将正式揭开序幕,持续时间长达十天之久。在此首轮测试窗口,…...

SpringBoot实现统一返回值+全局异常处理
在这里首先感谢的就是程序员老罗,从他的项目里面学到了这些东西。 首先就是去创建一个SpringBoot项目,这里我就不多做赘述了 封装一个统一返回对象 package com.example.demo.vo;public class ResponseVO<T> {private String status;private In…...

windows连接CentOS数据库或Tomcat报错,IP通的,端口正常监听
错误信息 数据库错误: ERROR 2003 (HY000): Cant connect to MySQL server on x.x.x.x (10060) Tomcat访问错误: 响应时间过长 ERR_CONNECTION_TIMED_OUT 基础排查工作 【以下以3306端口为例,对于8080端口来说操作是一样的,只需…...

超详细的胎教级Stable Diffusion使用教程(一)
这套课程分为五节课,会系统性的介绍sd的全部功能和实操案例,让你打下坚实牢靠的基础 一、为什么要学Stable Diffusion,它究竟有多强大? 二、三分钟教你装好Stable Diffusion 三、小白快速上手Stable Diffusion 四、Stable dif…...
流媒体服务器(20)—— mediasoup 之媒体流score评分计算(一)
目录 前言 正文 《流媒体服务器》专栏总览丨蓄力计划_开源流媒体服务器对比-CSDN博客 前言 mediasoup 有一套评估媒体传输通道优劣的机制,主要是通过 score 评分来判断的。今天就先介绍一下这个机制的大体逻辑,后面的文章再详细介绍具体计算的算法。 正文 mediasoup 的…...

用keras识别狗狗
一、需求场景 从照片从识别出狗狗 from keras.applications.resnet50 import ResNet50 from keras.preprocessing import image from keras.applications.resnet50 import preprocess_input, decode_predictions import numpy as np# 加载预训练的ResNet50模型 model ResNet5…...

Sass语法介绍-变量介绍
02 【Sass语法介绍-变量】 sass有两种语法格式Sass(早期的缩进格式:Indented Sass)和SCSS(Sassy CSS) 目前最常用的是SCSS,任何css文件将后缀改为scss,都可以直接使用Sassy CSS语法编写。 所有有效的 CSS 也同样都是有效的 SCSS。 Sass语…...

可调恒流电子负载的基础认识
可调恒流电子负载是模拟真实负载的电子设备,它可以模拟各种不同类型和功率的负载。这种设备的主要功能是接收电源输入,然后以恒定的电流输出,以便对电源或电池进行测试和校准。 首先,我们需要了解什么是恒流,恒流是指在…...
开源模型应用落地-模型记忆增强-概念篇(一)
一、前言 语言模型的记忆是基于其训练数据。具体而言,对于较长的文本,模型可能会遗忘较早的信息,因为它的记忆是有限的,并且更容易受到最近出现的内容的影响。模型无法跨越其固定的上下文窗口,而是根据当前上下文生成回应。 提升模型记忆能力有多种方法,比如改进模型的结…...

SAPUI5基础知识1 - 概览,库,支持工具,自学教程
1. SAPUI5 概览 1.1 SAPUI5 SAPUI5是一种用于构建企业级Web应用程序的开发框架。它是由SAP开发的,基于HTML5、CSS3和JavaScript技术。 SAPUI5提供了一套丰富的UI控件和工具,使开发人员能够快速构建现代化、可扩展和可定制的应用程序。 它还提供了数据…...
常见的获取dom元素的方法
获取 DOM 元素是前端开发中非常常见的操作。以下是几种常用的方法来获取 DOM 元素,以及它们的适用场景和示例: 1. getElementById 用于获取具有指定 id 属性的元素。 示例 let element document.getElementById(myId); 2. getElementsByClassName …...

走进CHEN MEI HUA的设计哲学:书写东方女性力量与态度的时尚篇章
在时尚的舞台中央,品牌不止是商品,更是故事的讲述者、文化的传承者。CHEN MEI HUA,一个源自中国上海的高端女装品牌,以其独特的设计理念及文化内核,成为了时尚界一颗耀眼的明珠。今天,让我们一起走进CMH的世…...
ESrally单机向量检索性能测试全流程
ESrally单机向量检索性能测试全流程 测试方案的尝试 准备测试 ES 的向量检索性能,Vespa 方案由于下载依赖库存在网络问题无法执行成功,终止;开源工具 ann-benchamrk 是一个用于评估近似最近邻(ANN)搜索库的性能测试工具,这个本是最佳选择,但是也由于需要 pip 安装几十…...

小红书释放被封手机号 无限注册
前几年抖音也可以释放被封手机号 那时候都不重视 导致现在被封手机号想释放 基本不可能的 或者就是最少几百块 有专业的人帮你通过某些信息差释放 本教程是拆解 小红书被封手机号怎么释放,从今年开始,被封的手机号无法注销了 所以很困扰 那么本教程来…...
Docker快速启动清单
以下容器均使用 Docker version 24.0.2 版本测试使用,这里需要注意一下,高版本的Docker不支持镜像V1版本,不知道怎么操作才可以让它支持,所以推荐使用低版本 如果觉得不直观,或者觉得有点乱,可以访问以下网…...

京东手势验证码-YOLO姿态识别+Bézier curve轨迹拟合
这次给老铁们带来的是京东手势验证码的识别。 目标网站:https://plogin.m.jd.com/mreg/index 验证码如下图: 当第一眼看到这个验证码的时候,就头大了,这玩意咋识别??? 静下心来细想后的一个方案…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...
LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》
🧠 LangChain 中 TextSplitter 的使用详解:从基础到进阶(附代码) 一、前言 在处理大规模文本数据时,特别是在构建知识库或进行大模型训练与推理时,文本切分(Text Splitting) 是一个…...