当前位置: 首页 > news >正文

数据结构之链式结构二叉树的实现(初级版)

本文内容将主会多次用到函数递归知识!!!

本节内容需要借助画图才能更好理解!!!

和往常一样,还是创建三个文件

这是tree.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.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);
// ⼆叉树叶⼦结点个数
int BinaryTreeLeafSize(btnode* root);
// ⼆叉树第k层结点个数
int BinaryTreeLevelKSize(btnode* root, int k);
//⼆叉树的深度/⾼度
int BinaryTreeDepth(btnode* root);
// ⼆叉树查找值为x的结点
btnode* BinaryTreeFind(btnode* root, btdatatype x);
// ⼆叉树销毁
void BinaryTreeDestory(btnode** root);

这是tree.c

​
#include"tree.h"
//先序遍历--根左右
void preorder(btnode* root)
{if (root == NULL){printf("NULL ");return;}printf("%c ", root->data);preorder(root->left);preorder(root->right);
}
//中序遍历--左根右
void InOrder(btnode* root)
{if (root == NULL){printf("NULL ");return;}InOrder(root->left);printf("%c ", root->data);InOrder(root->right);
}
//后序遍历--左右根
void PostOrder(btnode* root)
{if (root == NULL){printf("NULL ");return;}PostOrder(root->left);PostOrder(root->right);printf("%c ", root->data);
}
int BinaryTreeSize(btnode* root)
{if (root == NULL){return 0;}return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}
// ⼆叉树叶⼦结点个数
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);//从上往下索引,索引一层就k-1
}
//⼆叉树的深度/⾼度  ???
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);
}
// ⼆叉树查找值为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;
}
//传二级指针可以这样简单理解,销毁即把指向这一空间的指针(地址)置为NULL,而我们的root是一个一级指针,要将其销毁,则需要将其地址置为NULL,故传二级指针
void BinaryTreeDestory(btnode** root)
{if (*root == NULL){return;}BinaryTreeDestory(&((*root)->right));BinaryTreeDestory(&((*root)->left));free(*root);*root = NULL;
}
​

这是test.c

​
#include"tree.h"
btnode* buynode(btdatatype x)
{btnode* node = (btnode*)malloc(sizeof(btnode));assert(node);node->data = x;node->left = node->right = NULL;return node;
}
//手动构造一棵二叉树
btnode* createtree()
{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;
}
void test()
{btnode* root = createtree();preorder(root);printf("\n");InOrder(root);printf("\n");PostOrder(root);printf("\n");printf("size:%d\n", BinaryTreeSize(root));printf("size:%d\n", BinaryTreeSize(root));printf("leaf size:%d\n", BinaryTreeLeafSize(root));printf("k size:%d\n", BinaryTreeLevelKSize(root, 2));printf("k size:%d\n", BinaryTreeLevelKSize(root, 3));printf("k size:%d\n", BinaryTreeLevelKSize(root, 1));printf("depth:%d\n", BinaryTreeDepth(root));btnode* find = BinaryTreeFind(root, 'A');if (find == NULL){printf("not found!");}else{printf("we've found it!");}BinaryTreeDestory(&root);
}
int main()
{test();return 0;
}​

说明:

1. 遍历规则
按照规则,⼆叉树的遍历有:前序/中序/后序的递归结构遍历:
1)前序遍历(Preorder Traversal 亦称先序遍历):访问根结点的操作发生在遍历其左右子树之前
访问顺序为:根结点、左子树、右子树
2)中序遍历(Inorder Traversal):访问根结点的操作发生在遍历其左右子树之中(间)
访问顺序为:左子树、根结点、右子树
3)后序遍历(Postorder Traversal):访问根结点的操作发生在遍历其左右子树之后

访问顺序为:左子树、右子树、根结点 

图解遍历:
以前序遍历为例:

相关文章:

数据结构之链式结构二叉树的实现(初级版)

本文内容将主会多次用到函数递归知识&#xff01;&#xff01;&#xff01; 本节内容需要借助画图才能更好理解&#xff01;&#xff01;&#xff01; 和往常一样&#xff0c;还是创建三个文件 这是tree.h #pragma once #include<stdio.h> #include<stdlib.h> …...

day01-MybatisPlus

目录 1.快速入门 1.2.快速开始 1.2.1引入依赖 1.2.2.定义Mapper 1.2.3.测试 1.3.常见注解 1.3.1.TableName 1.3.2.TableId 1.3.3.TableField 1.4.常见配置 2.核心功能 2.1.条件构造器 2.1.1.QueryWrapper 2.1.2.UpdateWrapper 2.1.3.LambdaQueryWrapper 2.2.自…...

Postgresql源码(137)执行器参数传递与使用

参考 《Postgresql源码&#xff08;127&#xff09;投影ExecProject的表达式执行分析》 0 总结速查 prepare p_04(int,int) as select b from tbl_01 where a $1 and b $2为例。 custom计划中&#xff0c;在表达式计算中使用参数的值&#xff0c;因为custom计划会带参数值&…...

韩国恋爱游戏:阿西, 美女室友竟然…?百度网盘下载

​ 故事情节/出场人物 [阿西, 美女室友竟然…&#xff1f;]是一款 FMV 真人视频恋爱游戏&#xff0c;你将以第一人称与5位美女室友一起体验别样合租生活。 在本作中&#xff0c;您将扮演合租公寓的房东男主 吴宥万(直译:牛奶男)&#xff0c;一直独来独往的你&#xff0c;生活…...

一个运维牛人对运维规则的10个总结

一个运维牛人对运维规则的10个总结 在运维领域&#xff0c;经验和流程往往决定了系统的稳定性与可靠性。一个运维人&#xff0c;总结出了以下10条运维规则&#xff0c;涵盖了从基础管理到高级策略的全面内容&#xff0c;旨在帮助运维人员更好地应对各种挑战&#xff0c;确保系…...

Istio基本概念及部署

一、Istio架构及组件 Istio服务网格在逻辑上分为数据平面和控制平面。 控制平面&#xff1a;使用全新的部署模式&#xff1a;Istiod&#xff0c;这个组件负责处理Sidecar注入&#xff0c;证书颁发&#xff0c;配置管理等功能&#xff0c;替代原有组件&#xff0c;降低复杂度&…...

基于 Python 的 Django 框架开发的电影推荐系统

项目简介&#xff1a;本项目是基于 Python 的 Django 框架开发的电影推荐系统&#xff0c;主要功能包括&#xff1a; 电影信息爬取&#xff1a;获取并更新电影数据。数据展示&#xff1a;提供电影数据的列表展示。推荐系统&#xff1a;基于协同过滤算法实现个性化推荐。用户系…...

离线数仓开发SQL编写和调试的最佳实践(如何又快又好完成任务,学会几条就不用当很辛苦的牛马)

目录 在开发阶段对数据进行抽样 理论基础 实践应用 使用Hive进行数据采样 使用Spark进行数据采样 采用CTE模块化设计 逐步验证 逐步验证案例实践: 验证sales_data CTE: 验证ranked_sales CTE: 验证top_sales CTE: 结论 用Doris或Impala等更快查询的代替Hive …...

PostgreSQL 增量备份:保护你的数据资产

全文目录&#xff1a; 开篇语&#x1f4dc; 前言&#x1f4da; 增量备份概述&#x1f511; 增量备份的优势 &#x1f6e0;️ PostgreSQL 增量备份实施步骤&#x1f31f; 环境准备&#x1f680; 第一步&#xff1a;全量备份⏳ 第二步&#xff1a;定期增量备份&#x1f504; 第三…...

字节青训-寻找最大葫芦

问题描述 在一场经典的德州扑克游戏中&#xff0c;有一种牌型叫做“葫芦”。“葫芦”由五张牌组成&#xff0c;其中包括三张相同牌面值的牌 aa 和另外两张相同牌面值的牌 bb。如果两个人同时拥有“葫芦”&#xff0c;我们会优先比较牌 aa 的大小&#xff0c;若牌 aa 相同则再比…...

el-checkbox勾选一个变成了勾选所有

问题&#xff1a; el-checkbox完成后勾选一个选项变成了所有选项都勾选了。非model值不正确&#xff0c;我的model值绑定的是数组&#xff0c;但是还是勾选一个变成了勾选多个。 解决 因为勾选的内容比较简单&#xff0c;且值不需要入库&#xff0c;所以我最开始定义的option为…...

ExpandingCard扩展卡片

文章目录 演示效果分析思路核心代码总结 源码 演示效果 分析思路 使用flex布局&#xff0c;每个卡片的宽度都由flex进行灵活调整交互可以增加和删除active&#xff0c;来实现宽度扩增和恢复还需要使用transition进行动画过渡&#xff0c;使得平滑切换 核心代码 首先创建一个…...

移远通信推出八款天线新品,覆盖5G、4G、Wi-Fi和LoRa领域

近日&#xff0c;全球领先的物联网整体解决方案供应商移远通信宣布&#xff0c;再次推出八款高性能天线新品&#xff0c;进一步丰富其天线产品阵容&#xff0c;更好地满足全球客户对高品质天线的更多需求。具体包括5G超宽带天线YECT005W1A和YECT004W1A、5G天线YECT028W1A、4G天…...

MySQL 9从入门到性能优化-创建触发器

【图书推荐】《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;》-CSDN博客 《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;&#xff08;数据库技术丛书&#xff09;》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) MySQL9数据库技术_夏天又到了…...

UE5 第三人称学习之动画 control rig

这个东西和建模软件里有的是一个东西&#xff0c;然后IK就是你动脚&#xff0c;他帮你算出小腿大腿该怎么动&#xff0c;FK就是你自己动了大腿&#xff0c;摆小腿&#xff0c;然后再摆脚 就是给每一根骨骼搞一个控制器&#xff0c;给他一个容易选中和操作更明显的图形作为控制…...

C++之--初见模板初阶

一、泛型编程 为了实现一个通用的函数&#xff0c;在此之前&#xff0c;我们学过函数重载&#xff0c;使用函数重载虽然可以实现&#xff0c;但是有一下几个不好的地方&#xff1a; 1. 重载的函数仅仅是类型不同&#xff0c;代码复用率比较低&#xff0c;只要有新类型出现时&a…...

Nature|用于无线监测颅内信号的植入式柔性超声波传感器(柔性传感/健康监测/植入式电子/水凝胶)

华中科技大学臧剑锋(Jianfeng Zang)、华中科技大学同济医学院附属协和医院姜晓兵(Xiaobing Jiang)和新加坡南洋理工大学陈晓东(Xiaodong Chen)团队,在《Nature》上发布了一篇题为“Injectable ultrasonic sensor for wireless monitoring of intracranial signals”的论…...

【和AI的《趣味》聊天】01 AI:你找茬是吧(

我&#xff1a; 以下哪个选项是中文&#xff1f; A.Chinese B.英文 AI&#xff1a; 我&#xff1a; 这不对吧&#xff0c;我说的是那个选项的语言是中文 AI&#xff1a; 非常抱歉&#xff0c;我之前的回答有误。您问的是哪个选项的语言是中文&#xff0c;那么答案应该是…...

“发放父作业单”是“过数”用例里面的内容吗

刘京城 2020-4-14 23:01 。。。。(注&#xff1a;这是一个人的昵称&#xff0c;不是省略号) 首先&#xff0c;执行者是同一个&#xff0c;那么思考焦点要关注“过数”用例是不是“发放父作业单”用例的一个步骤&#xff0c;和行为操作的频率无关&#xff0c;而是和责任有关&am…...

Linux补基础之:网络配置

目录 一、检查主机与虚拟机是否能正常通信 二、网络的连接模式 桥接模式 流程 特点 NAT模式 流程 特点 仅主机 流程 特点 三、修改静态IP 四、可能遇到的问题 防火墙 DNS 五、主机名更改 六、登录服务器 实际的大数据管理中&#xff0c;会有由很多服务器构成的…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...