数据结构——二叉树链式结构的实现(上)
二叉树概念
再看二叉树基本操作前,再回顾下二叉树的概念,
二叉树是:
1. 空树
2. 非空:根节点,根节点的左子树、根节点的右子树组成的。
从概念中可以看出,二叉树定义是递归式的
二叉树构成:根 左子树 右子树构成的。
前序遍历是 :根 左子树 右子树
中序遍历是 :左子树 根 右子树
后序遍历是:左子树 右子树 根
根据上面的插图 前序遍历应该是: 1 2 3 N N N 4 5 N N 6 N N
那么你能试着说出中序和后序吗?
中序和后序如下图所示,你看你写对了吗?
我们学习普通链式二叉树的增删查改是没有意义的,因为我们现在学习普通链式二叉树是为了以后的搜索二叉树和AVL 红黑树打基础的,还有就是很多二叉树的题,都是出在普通链式二叉树结构。
这是一个普通的搜索二叉树,二叉树的左子树比根小,右子树比根大。
如果搜索二叉树走中序遍历,就是个有序二叉树。
二叉树的构建
在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在大家对二叉树结构掌握还不够深入,为了降低大家学习成本,此处手动快速创建一棵简单的二叉树,快速进入二叉树操作学习,等二叉树结构了解的差不多时,我们反过头再来研究二叉树真正的创建方式。(注意:下述代码并不是创建二叉树的方式 )
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct BinaryTree
{struct BinaryTree* _left;struct BinaryTree* _right;int val;
}BTNode;BTNode* buynode(int x)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));if (newnode == NULL){perror("malloc fail");exit(-1);}newnode->val = x;newnode->_left = NULL;newnode->_right = NULL;return newnode;
}
int main()
{BTNode* newnode1 = buynode(1);BTNode* newnode2 = buynode(2);BTNode* newnode3 = buynode(3);BTNode* newnode4 = buynode(4);BTNode* newnode5 = buynode(5);BTNode* newnode6 = buynode(6);newnode1->_left = newnode2;newnode2->_left = newnode3;newnode1->_right = newnode4;newnode4->_left = newnode5;newnode4->_right = newnode6;return 0;
}
二叉树的遍历
学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。
前序遍历
void PreOrder(BTNode* root)
{if (root == NULL){printf(" NULL ");return;}printf("%d ", root->val);PreOrder(root->_left);PreOrder(root->_right);
}
是不是觉得很简单?我们先运行下结果
跟我们之前预测的一模一样,为了更好的了解前序遍历,我画一下递归图。
中序遍历
就是把代码换个顺序就变成了中序遍历,为了深刻理解递归过程,建议像上面一样,自己画个递归过程理解。
void InOrder(BTNode* root)
{if (root == NULL){printf(" NULL ");return;}InOrder(root->_left);printf("%d ", root->val);InOrder(root->_right);
}
运行结果
后序遍历
void PostOrder(BTNode* root)
{if (root == NULL){printf(" NULL ");return;}PostOrder(root->_left);PostOrder(root->_right);printf("%d ", root->val);
}
运行结果
前序 中序 后序遍历结果
求节点个数以及高度等
二叉树的节点个数
很多人可能都是想这么求节点个数的,但其实是错误的方法,因为size是局部变量 出了作用域就销毁了 根本求不出正确节点个数。
那么我们加上static 让它变成静态变量呢?
可以求出正确答案,因为静态变量在静态区,全局变量也在静态区,相当于一个全局变量,出了作用域并不会被销毁,而且只会走一次初始化,因此答案是正确的。
但有一个问题,如果我要再次调用这个函数求节点个数呢?
答案就会是错误的,因为静态变量只会走一次初始化。
解决办法也有,就是在前面把size设为全局变量 再次调用时归为0即可 答案还是6,但这种方法太low了。
正确的求节点个数代码
//节点个数
int Treesize(BTNode* root)
{return root == NULL ? 0 : 1 + Treesize(root->_left) + Treesize(root->_right);
}
思路:比如学校里面要统计在校人数,校长不可能一个个问每个人+1+1+1......,而是布置任务,给辅导员或者班主任,班主任或者辅导员会布置给班长去统计各班学生个数,班长汇报给辅导员或班主任,班主任或者辅导员汇报给校长,校长最后在汇报结果加上自己,就是学校在校总人数。
二叉树的叶子节点个数
叶子节点就是度为0的节点。
首先要判断根为不为空
再判断根节点的左右结点存不存在即可。
//叶子结点
int Treeleafsize(BTNode* root)
{if (root == NULL){return 0;}if (root->_left == NULL && root->_right == NULL){return 1;}return Treeleafsize(root->_left) + Treeleafsize(root->_right);
}
二叉树第k层的节点个数
//第K层结点个数
int TreeKlevelsize(BTNode* root, int k)
{assert(k > 0);if (root == NULL){return 0;}if (k == 1){return 1;}return TreeKlevelsize(root->_left, k - 1) + TreeKlevelsize(root->_right, k-1);
}
完整代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
typedef struct BinaryTree
{struct BinaryTree* _left;struct BinaryTree* _right;int val;
}BTNode;BTNode* buynode(int x)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));if (newnode == NULL){perror("malloc fail");exit(-1);}newnode->val = x;newnode->_left = NULL;newnode->_right = NULL;return newnode;
}void PreOrder(BTNode* root)
{if (root == NULL){printf(" NULL ");return;}printf("%d ", root->val);PreOrder(root->_left);PreOrder(root->_right);
}
void InOrder(BTNode* root)
{if (root == NULL){printf(" NULL ");return;}InOrder(root->_left);printf("%d ", root->val);InOrder(root->_right);
}
void PostOrder(BTNode* root)
{if (root == NULL){printf(" NULL ");return;}PostOrder(root->_left);PostOrder(root->_right);printf("%d ", root->val);
}//节点个数
int Treesize(BTNode* root)
{return root == NULL ? 0 : 1 + Treesize(root->_left) + Treesize(root->_right);
}//叶子结点
int Treeleafsize(BTNode* root)
{if (root == NULL){return 0;}if (root->_left == NULL && root->_right == NULL){return 1;}return Treeleafsize(root->_left) + Treeleafsize(root->_right);
}
//第K层结点个数
int TreeKlevelsize(BTNode* root, int k)
{assert(k > 0);if (root == NULL){return 0;}if (k == 1){return 1;}return TreeKlevelsize(root->_left, k - 1) + TreeKlevelsize(root->_right, k-1);
}
int main()
{BTNode* newnode1 = buynode(1);BTNode* newnode2 = buynode(2);BTNode* newnode3 = buynode(3);BTNode* newnode4 = buynode(4);BTNode* newnode5 = buynode(5);BTNode* newnode6 = buynode(6);newnode1->_left = newnode2;newnode2->_left = newnode3;newnode1->_right = newnode4;newnode4->_left = newnode5;newnode4->_right = newnode6;PreOrder(newnode1);printf("\n");InOrder(newnode1);printf("\n");PostOrder(newnode1);printf("\n");printf("Treesize:%d\n", Treesize(newnode1));printf("Treeleafsize:%d\n", Treeleafsize(newnode1));printf(" TreeKlevelsize:%d\n", TreeKlevelsize(newnode1,3));return 0;
}
相关文章:

数据结构——二叉树链式结构的实现(上)
二叉树概念 再看二叉树基本操作前,再回顾下二叉树的概念, 二叉树是: 1. 空树 2. 非空:根节点,根节点的左子树、根节点的右子树组成的。 从概念中可以看出,二叉树定义是递归式的 二叉树构成࿱…...
数据结构内容概览
0. 绪论 绪论01——复杂度度量 绪论02——复杂度分析 绪论03——递归分析 绪论04——算法分析 绪论05——动态规划 算法设计与优化——前n项和计算 算法设计优化——对于任意非负整数,统计其二进制展开中数位1的总数 算法设计优化——Fibonacci数 算法设计优化——…...
当Linux系统运行时间长了之后,会出现磁盘空间不足提示,需要及时进行清理
Linux系统(CentOS 7)的磁盘空间不足时,可以采取以下步骤进行清理: 查找并删除大文件: 使用du和find命令可以找到并删除大文件。例如,要查找/目录下大于100MB的文件,可以运行: find /…...

【Flask 系统教程 4】Jinjia2模版和语法
Jinjia2 模板 模板的介绍 Jinja2 是一种现代的、设计优雅的模板引擎,它是 Python 的一部分,由 Armin Ronacher 开发。Jinja2 允许你在 HTML 文档中嵌入 Python 代码,以及使用变量、控制结构和过滤器来动态生成内容。它的语法简洁清晰&#…...

与 Apollo 共创生态:七周年大会心得
与 Apollo 共创生态:七周年大会心得 前言 4月19日,百度Apollo迎来七周年,历经七年的不懈追求与创新,Apollo开放平台已陆续推出了13个版本,汇聚了来自全球170多个国家与地区的16万名开发者及220多家合作伙伴。作为一名…...

『FPGA通信接口』DDR(4)DDR3内存条SODIMMs读写测试
文章目录 前言1.MIG IP核配置2.测试程序3.DDR应用4.传送门 前言 不论是DDR3颗粒还是DDR3内存条,xilinx都是通过MIG IP核实现FPGA与DDR的读写。本文区别于DDR颗粒,记录几个与颗粒配置不同的地方。关于DDR的原理与MIG IP的简介,请查看前面文章&…...
Element UI 快速入门指南
Element UI 快速入门指南 Element UI 是一个基于 Vue.js 的组件库,提供了丰富的 UI 组件和工具,可以帮助开发人员快速构建现代化的 Web 应用程序。本文将介绍如何快速入门使用 Element UI,并展示一些常用的组件和功能。 安装 Element UI 使…...

CentOS常用命令有哪些?
目录 一、CentOS常用命令有哪些? 二、不熟悉命令怎么办? 场景一:如果是文件操作,可以使用FileZilla工具来完成 场景二:安装CentOS桌面 一、CentOS常用命令有哪些? CentOS 系统中有许多常用命令及其用法…...
cmd查看局域网内所有设备ip
说明:最近碰到一个新问题,就是有一个安卓设备,安装了一个app导致死机了,app设置了开机重启,所以,无论重启还是关机,都是进来就白屏, 这可把人愁坏了,直接死循环了 无论…...
5.3作业
这个声明定义了一个名为 s 的数组,数组包含 10 个元素,每个元素都是一个函数指针。(1)C (2)D (3)C (4)DE (5)C8 11 14(1)int IsFull(sequeue *seqn) { return ((seqn->frnt ((seqn->rear 1) % N)) ? 1 : 0); } (2)int IsEmpty(sequ…...

java-Spring-mvc-(请求和响应)
目录 📌HTTP协议 超文本传输协议 请求 Request 响应 Response 🎨请求方法 GET请求 POST请求 📌HTTP协议 超文本传输协议 HTTP协议是浏览器与服务器通讯的应用层协议,规定了浏览器与服务器之间的交互规则以及交互数据的格式…...

亚马逊测评工作室如何轻松实现高收益,跨境电商揭秘汇率差赚钱术
随着跨境电商在国内市场的持续繁荣,众多电商卖家纷纷将目光投向了这一充满活力的领域。面对国内市场的激烈竞争,许多卖家选择向外拓展,寻求更广阔的发展空间。其中,亚马逊成为了众多卖家的不二选择,毕竟老外的市场还是…...
unity中 UnityWebRequest.Post和 UnityWebRequest uwr = new UnityWebRequest两种方法有什么区别
在Unity中,UnityWebRequest.Post 和 UnityWebRequest uwr new UnityWebRequest(...) 是两种不同的方式来创建和发送HTTP POST请求,但它们之间有一些关键的区别和用法上的差异。 1. UnityWebRequest.Post (静态方法) UnityWebRequest.Post 是一个静态方…...
Java学习-练习试用Java实现求素数
以下是使用Java语言试着编写的求1-100内的素数的程序: public class PrimeNumbers {public static void main(String[] args) {System.out.println("Prime numbers between 1 and 100 are:");for (int i 2; i < 100; i) {if (isPrime(i)) {System.ou…...
最近学习发现一个background-blend-mode,这是CSS的一个新成员吧!这里分享记录一下
介绍 background-blend-mode CSS 属性定义该元素的背景图片,以及背景色如何混合。 混合模式应该按background-image CSS 属性同样的顺序定义。如果混合模式数量与背景图像的数量不相等,它会被截取至相等的数量。在所有的元素中。在SVG,它适…...

虚幻引擎5 Gameplay框架(二)
Gameplay重要类及重要功能使用方法(一) 配置LOG类及PlayerController的网络机制 探索验证GamePlay重要函数、类的执行顺序与含义 我们定义自己的日志,专门建立一个存放自己日志的类,这个类继承自BlueprintFunctionLibrary 然后…...

云原生Kubernetes: K8S 1.29版本 部署Sonarqube
一、实验 1.环境 (1)主机 表1 主机 主机架构版本IP备注masterK8S master节点1.29.0192.168.204.8 node1K8S node节点1.29.0192.168.204.9node2K8S node节点1.29.0192.168.204.10已部署Kuboard (2)master节点查看集群 1&…...

读天才与算法:人脑与AI的数学思维笔记19_深度数学
1. 深度数学 1.1. 组合与选择,是发明新事物的两个不可或缺的条件 1.1.1. 保尔瓦雷里(Paul Valry) 1.2. 利用以往的数学定理证明过程训练算法,以发现新的定理 1.3. 谷歌设在伦敦的总部整体有一种现代牛津大学的感觉,…...

Springboot+Vue项目-基于Java+MySQL的旅游网站系统(附源码+演示视频+LW)
大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:Java毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计 &…...
Element UI 简介
Element UI是一个基于Vue.js的组件库,提供了一套丰富的可复用的组件,包括按钮、表单、弹框、表格、菜单等等。它的设计风格简洁大方,易于使用,能够帮助开发者快速构建现代化的Web应用。 在Element UI中,有许多常用的组…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...