✅ 一、为什么要学习二叉树?

1. 📦 组织数据的高效方式

  • 二叉树可以快速插入、删除、查找数据,尤其在平衡时,时间复杂度为 $O(\log n)$。

  • 适合表示分层结构(如组织结构、文件系统、语法树)。

2. 💡 各种高级结构的基础

很多更复杂的数据结构都以二叉树为基础,例如:

  • 堆(Heap):用于实现优先队列

  • 平衡树(如 AVL、红黑树):用于快速搜索和动态数据更新

  • 线段树、区间树、树状数组:用于范围查询

  • 表达式树、Huffman 树:用于编译器、压缩算法等

3. 🧠 算法题中的常客

  • 很多算法竞赛、笔试题会考查二叉树的构造、遍历、查找、平衡、路径计算等问题。

  • 是程序员面试中的高频知识点

4、二叉树的常用功能

功能

说明

✅ 遍历

先序、中序、后序、层序遍历

🔍 搜索

二叉搜索树(BST)可高效查找

📁 分层结构表示

文件系统、组织架构树、语法树

🧮 表达式处理

表达式树支持中缀转后缀、求值

🧠 平衡维护

AVL、红黑树保证查找平衡性

🔧 范围查询

线段树、区间树等支持快速区间操作

🔗 哈夫曼编码

构造最优前缀编码

🔄 结构转换

镜像、翻转、扁平化等结构操作

二叉树是一种既基础又强大的数据结构,学习它不仅是算法的入门,也是迈向更高阶算法和工程应用的必经之路。

下面我们总结一下对于二叉树言的常用接口包括:

二、二叉树的常用实现

1、如何创建二叉树。2、销毁创建的二叉树释放内存。3、计算二叉树的节点个数。4、计算二叉树叶节点的个数。5、计算二叉树第k层的节点个数。6、找到二叉树中指定的节点。7、二叉树的前序,后序,中序。8、层序遍历(利用队列实现)。9、判断是否为完全二叉树。

1、如何创建二叉树

代码实现:

typedef char BTreeDataType;typedef struct BTreeNode
{BTreeDataType _data;struct BTreeNode* _left;struct BTreeNode* _right;
}BTreeNode;BTreeNode* CreateTree(BTreeDataType* str,int* pi){if(*str == '\0'){return NULL;}if(str[*pi] == '#'){(*pi)++;return NULL;}BTreeNode* root = (BTreeNode*)malloc(sizeof(BTreeNode));root->_data = str[*pi];(*pi)++;root->_left = CreateTree(str,pi);root->_right = CreateTree(str,pi);return root;
}

测试函数:

int main(){char str[100] = {0};scanf("%s",str);int i = 0;BTreeNode* root = CreateTree(str,&i);}

输入:ABC##DE#G##F###,注意这里我们构建二叉树是通过“前序遍历的思想”

2、销毁创建的二叉树释放内存

void BTree_Destroy(BTreeNode* root){if(!root){return;}BTree_Destroy(root->_left);BTree_Destroy(root->_right);free(root);root = NULL;
}

3、计算二叉树的节点个数

        利用前序遍历的思想进行二叉树的遍历,统计非空子树即可,可参考二叉树的前序遍历。

int BTreeSize(BTreeNode* root){if(!root){return 0;}return 1+ BTreeSize(root->_left)+BTreeSize(root->_right);
}

4、计算二叉树叶节点的个数

        同样你可以利用前序遍历的思想,但是统计叶节点,需满足左右子树为空才统计

int BTreeLeafSize(BTreeNode* root){if(!root){return 0;}if(!(root->_left) && !(root->_right)){return 1;}return (BTreeLeafSize(root->_left)+BTreeLeafSize(root->_right));
}

5、计算二叉树第k层的节点个数。

        这里我们需要输入k这个参数,首先我们需要找到第k层,当遍历二叉树时,遍历至当前节点的左右子树,则k--,知道k==0时,就是我们的第k层,然后在统计节点个数就行。        

代码实现:

int BTreeLevelKSize(BTreeNode* root,int k){if(!root){return 0;}k--;if(k == 0){return 1;}return (BTreeLevelKSize(root->_left,k)+BTreeLevelKSize(root->_right,k));
}

6、找到二叉树中指定的节点

        只需判断节点值是否为指定值,是就直接返回当前节点,否则继续遍历。

代码实现:

BTreeNode* BTreeFind(BTreeNode* root,int _val){if(!root){return NULL;}if(root->_data == _val){return root;}BTreeNode* node = BTreeFind(root->_left,_val);if(node){return node;}node = BTreeFind(root->_right,_val);if(node){return node;}return NULL;
}

7、二叉树的前序,后序,中序

        这部分内容我们已经实现过很多次了,这里直接给出源码

代码实现:

//前序
void PreOrder(BTreeNode* root){if(!root){printf("NULL");return;}printf("%c ",root->_data);PreOrder(root->_left);PreOrder(root->_right);return;
}
//中序
void InOrder(BTreeNode* root){if(!root){printf("NULL");return;}InOrder(root->_left);printf("%c ",root->_data);InOrder(root->_right);return;
}
//后序
void PostOrder(BTreeNode* root){if(!root){printf("NULL");return;}PostOrder(root->_left);PostOrder(root->_right);printf("%c ",root->_data);return;
}

8、层序遍历(利用队列实现)

        这里我们需要使用到队列的思想,“先进先出”当前节点不为空,我们把当前节点放入队列中,然后再输出该节点,然后将该节点的左右子节点放入队列,然后再删除左节点,再把左节点的左右子节点再放入,当节点为空时不再放入,当队列为空时不在放出,不断重复放入放出。就是层序遍历。

思维导图:

代码实现:

//队列的声明
typedef struct Queue
{QueueDataType btnode;struct Queue* next;}Queue;typedef struct my_Queue{Queue* _head;Queue* _tail;
}my_Queue;//队列初始化
my_Queue* Queue_Init(){my_Queue* pq = (my_Queue*)malloc(sizeof(my_Queue));pq->_head = pq->_tail = NULL;return pq;
}
//队列的摧毁
void QueueDestroy(my_Queue* pq){assert(pq);Queue* Cur = pq->_head;while (Cur){Queue* Del = Cur;Cur = Cur->next;free(Del);}pq->_head = pq->_tail = NULL;return;
}
//插入元素
void QueuePush(my_Queue* pq,QueueDataType _val){assert(pq);Queue* NewNode = (Queue*)malloc(sizeof(Queue));NewNode->btnode = _val;NewNode->next = NULL;if(pq->_head == NULL){pq->_tail = NewNode;pq->_head = NewNode;  }else{pq->_tail->next = NewNode;pq->_tail = NewNode;}
}
// 删除元素
void QueuePop(my_Queue* pq){assert(pq);if(pq->_head == NULL){return;}else{Queue* Cur = pq->_head;pq->_head = (pq->_head)->next;free(Cur);}if(pq->_head == NULL){pq->_tail = NULL;}return;
}// 返回队列开头元素
QueueDataType QueueFront(my_Queue* pq){assert(pq);if(pq->_head){return pq->_head->btnode;}return NULL;
}//判断队列是否为空
bool IsQueueEmpty(my_Queue* pq){assert(pq);return !pq->_head;
}

队列的构建以及常用函数的实现:参考栈与队列的实现

//层序遍历
void BTree_LevelOrder(BTreeNode* root){if(!root){printf("NULL");return;}my_Queue* BTqueue = Queue_Init();QueuePush(BTqueue,root);while (!IsQueueEmpty(BTqueue)){QueueDataType Front = QueueFront(BTqueue);printf("%c ",Front->_data);QueuePop(BTqueue);if(Front->_left){QueuePush(BTqueue,Front->_left);};if(Front->_right){QueuePush(BTqueue,Front->_right);}}QueueDestroy(BTqueue);BTqueue = NULL;return;
}

9、判断是否为完全二叉树。

        完全二叉树的概念是 除最后一层外,其他层都是满的,且最后一层从左到右连续填满

这里我们需要利用层序遍历的思想去判断是否为完全二叉树。

思维导图:

代码实现:

bool IsCompleteTree(BTreeNode* root){if(!root){return true;}my_Queue* BTqueue = Queue_Init();QueuePush(BTqueue,root);bool null_seen = false;while (!IsQueueEmpty(BTqueue)){QueueDataType Front = QueueFront(BTqueue);QueuePop(BTqueue);if(Front == NULL){null_seen = true;}else{if(null_seen){QueueDestroy(BTqueue);BTqueue = NULL;return false;}QueuePush(BTqueue,Front->_left);QueuePush(BTqueue,Front->_right); }}QueueDestroy(BTqueue);BTqueue = NULL;return true;
}

10、测试函数如下:

//测试函数
int main(){char str[100] = {0};scanf("%s",str);int i = 0;BTreeNode* root = CreateTree(str,&i);PreOrder(root);printf("\n");printf("%d ",BTreeSize(root));printf("%d ",BTreeLeafSize(root));printf("%d ",BTreeLevelKSize(root,3));BTreeNode* target = BTreeFind(root,'D');printf("%c ",target->_data);BTree_LevelOrder(root);if(IsCompleteTree(root)){printf("yes\n");}else{printf("No\n");}
}

好了,关于二叉树的c语言相关的内容就分享到这了,后续有关二叉树的内容我们利用c++实现。

谢谢大家的点赞和收藏!👍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/89979.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/89979.shtml
英文地址,请注明出处:http://en.pswp.cn/web/89979.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java注解家族--`@ResponseBody`

ResponseBody ResponseBody是 Spring 框架中的一个注解,在基于 Spring 的 Web 开发中扮演着重要角色,以下是对它的详细总结: 1.定义与基本功能 定义:ResponseBody注解用于将 Controller 方法的返回值,通过适当的 HttpM…

react-window 大数据列表和表格数据渲染组件之虚拟滚动

简介 React Window 是一个高效的 React 组件库,专为渲染大数据列表和表格数据而设计。它通过”虚拟化”技术(也称为”窗口化”或”列表虚拟化”)解决了在 React 应用中渲染大量数据时的性能问题。与传统方法不同,React Window 只…

Eltable tree形式,序号列实现左对齐,并且每下一层都跟上一层的错位距离拉大

要的是如图所示效果序号加个class-name写样式然后给eltable加indent属性就可以了,我设置的25

FOC算法中SIMULINK一些常用模块(2)-Permanent Magnet Synchronous Machine模块

一,介绍这三个模块一起介绍了,由左到右,分别是电源模块,驱动模块和电机模块。主要介绍一下电机模块二,DC Voltage SourceDC Voltage Source 模块是用于表示直流电压源的基本组件,可以提供恒流直压&#xff…

RPG62.制作敌人攻击波数二:攻击ui

1。经典创建userwidget,使用xmbtextblock,结构如下。然后设置动画与音频,上下的参数是一样的,转到图表打开BP_SurvialGameMode2.再创建一个widget,结构如下新添的动画打开XMBGameModeBase,创建构造函数AXMB…

DL00691-基于深度学习的轴承表面缺陷目标检测含源码python

DL00691-基于深度学习的轴承表面缺陷目标检测含源码python

Word 中为什么我的图片一拖就乱跑,怎么精确定位?

核心原因:文字环绕方式 (Text Wrapping) 问题的根源在于图片的**“文字环绕”**设置。 默认状态:“嵌入型” (In Line with Text) 当您插入一张图片时,Word默认会把它当作一个巨大的文字字符来处理。这就是为什么您拖动它时,它会像…

Linux物理地址空间入门:从硬件到内核内存的基石

目录 一、物理地址空间是什么? 二、物理地址空间的构成:不仅仅是内存 三、Linux内核如何管理物理地址空间 (1)物理内存的碎片化问题 (2)物理地址的分区管理 (3)物理地址与内核…

【2025最新版】PDFelement全能PDF编辑器

工具https://pan.quark.cn/s/a56d17fd05dd强大全能的PDF编辑神器PDFelementPro 全能PDF工具套装 PDF阅读器 PDF创建器 PDF编辑器 PDF注释器 PDF转换器 OCR识别工具 表单填写和创建 数据提取 批量处理 更多详情万兴PDF专业版特性。格式转换:PDFelement轻松…

基于单片机汽车驾驶防瞌睡防疲劳报警器自动熄火设计

(一)系统功能设计 51单片机汽车驾驶防疲劳防瞌睡报警器自动熄火15 本系统由STC89C52单片机、蜂鸣器、ADXL345重力加速度传感器、继电器控制、按键、指示灯及电源组成。 1、通过按键点亮led灯,代表车辆启动和熄火。 2、车辆启动后,…

OpenCV中的卷积高斯模糊与中值模糊

目录 一、卷积高斯模糊 (Gaussian Blur) 1. 原理与数学基础 2. OpenCV函数实现 3. 关键参数说明 4. 代码示例 5. 特点与应用 二、中值模糊 (Median Blur) 1. 原理与数学基础 2. OpenCV函数实现 3. 关键参数说明 4. 代码示例 5. 特点与应用 三、两种模糊方法对比分析…

macbookpro m1 max本儿上速搭一个elasticsearch+kibana环境

一、找个目录,新建一个: docker-compose.yml version: "3.9" services:elasticsearch:image: docker.elastic.co/elasticsearch/elasticsearch:8.13.0 # 与 Kibana 版本一致container_name: elasticsearchenvironment:- discovery.typesingle-node- xpa…

部署zabbix企业级分布式监控

一. 监控系统的功能概述监控、从中文的字义来看,有两个内容,一是检测,二是控制。重点在第一个字眼,即检测、预防的意思。监控,对应的英文单词是 Monitoring。在计算机领域,可以将其分为5种监控类型。应用性…

【重学MySQL】redolog binlog

目录 Buffer Pool是什么? redo log(Innodb独有) 为什么需要redolog? 类比的方式巧记redolog binlog(Server层独有) binlog是干啥的? 为什么有了 binlog, 还要有 redo log&…

企业信息化建设技术底座建设解决方案

1、企业数字化底座与数字化综述2、企业数字化底座与数字化总体架构3、企业数字化底座与数字化规划设计4、企业数字化底座与数字化建设运营5、企业数字化底座与数字化未来展望篇幅有限以下只展示部分截图:

Spring Cloud Alibaba 之 Nacos

Spring Cloud Alibaba 之 Nacos . Nacos官方文档: https://nacos.io/docs/latest/overview/?spm5238cd80.47ee59c.0.0.770fcd36HoVbU6 1.什么是Nacos Nacos(Dynamic Naming and Configuration Service)是阿里巴巴开源的一款动态服务发现、…

Car Kit重构车机开发体验,让车载应用开发驶入快车道

在智能座舱成为汽车行业“新四化”核心战场的今天,开发者们正面临这样的挑战:如何让手机应用快速适配车机场景?如何实现手机与车机无感流转?如何在保障驾驶安全的前提下提供沉浸式交互体验? HarmonyOS SDK 车服务&…

ruoyi-flowable-plus Excel 导入数据 Demo

📁 项目结构简述 ruoyi-flowable-plus 是基于 RuoYi 的扩展项目,使用: 后端:Spring Boot MyBatis Flowable前端:Vue.js 📥 Excel 导入功能 Demo 以导入用户数据为例,展示完整导入流程。 …

kafka 日志索引 AbstractIndex

AbstractIndexAbstractIndex 是 Kafka 日志(Log)子系统中一个至关重要的基础类。它为 Kafka 的各种索引文件(如偏移量索引 .index 和时间戳索引 .timeindex)提供了一个统一的、抽象的框架。这个类的设计目标是实现极高的读写性能和…

重学前端008 --- 响应式网页设计 CSS 无障碍 Quiz

文章目录meta 总结html 页面结构img 尺寸子选择器 >a 锚点仅屏幕阅读器可见li 元素的悬停设置小屏幕防止溢出meta 总结 <head><!-- 基础字符编码声明 --><meta charset"UTF-8"><!-- 视口设置&#xff0c;响应式设计必备 --><meta nam…