二叉树详解

目录

一、二叉树的实现

        1.1 二叉树的前序遍历

        1.2 二叉树的中序遍历 

        1.3 二叉树的后续遍历

        1.4 二叉树的节点个数

         1.5 二叉树叶子节点个数

        1.6  二叉树查找值为x的节点

        1.7 二叉树第k层节点个数

        1.8 二叉树的高度

                 1.9 二叉树的销毁

二、代码展示

        BTNode.h

        BTNode.c

最后


一、二叉树的实现

        前面我们已经说过了二叉树的定义与概念,现在我们讨论的是如何实现二叉树。

         在二叉树中我们不仅无法确定其具体的孩子数,也无法确定其具体节点数。那该如何实现,那不就是无从下手吗?非也,咱们想不到,自有人会想到,这里,我们实现的思路为:左孩子、右兄弟表示法。即:根左边指向它的左孩子,右边指向它左孩子的兄弟也就是右孩子,这样不就表示出来了。可借助以下代码理解:

typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;

        运用此方法,我们可较为方便的表示出各个节点之间的关系。我们现在能用到这样的方法就是因为:我们是站在巨人的肩膀上。

        了解了二叉树的大逻辑后,我们现在要开始研究二叉树的细枝末节了。

        1.1 二叉树的前序遍历

                我们在用代码实现前,我们要先明白,什么是遍历?什么是前序遍历?

                所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问 题。 遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础。

                所谓的前序遍历即:二叉树沿着:根,左子树,右子树的顺序进行遍历。 

                我们已明白其实现逻辑,现在开始用代码实现吧!

void BinaryTreePrevOrder(BTNode* root)
{if (root == NULL){return;//此处也可打印N}printf("%d", root->data);//按照前序遍历顺序:根BinaryTreePrevOrder(root->left);//左子数BinaryTreePrevOrder(root->right);//右子数
}

         

        上面帮助大家理解以下此代码。总之:记住顺序:根,左子树,右子树。 

        1.2 二叉树的中序遍历 

        在理解了前序遍历后,中序遍历也可以理解。中序遍历和前序遍历并无本质区别,只是顺序变换了一下,即:左子树,根,右子树。代码实现如下:

void BinaryTreeInOrder(BTNode* root)
{if (root == NULL){return;}BinaryTreeInOrder(root->left);printf("%d  ", root->data);BinaryTreeInOrder(root->right);//无不一样之处,只是交换了顺序
}

        1.3 二叉树的后续遍历

        后续遍历的遍历顺序为:左子树,右子树,根。其余思路还是一致。代码实现如下:

void BinaryTreePostOrder(BTNode* root)
{if (root == NULL){return;}BinaryTreePostOrder(root->left);BinaryTreePostOrder(root->right);printf("%d  ", root->data);
}

        1.4 二叉树的节点个数

                接下来,我们学习如何求二叉树的节点个数。

                假如,你们学校有一个校长,两个院长,四个辅导员,八个班长。校长接到通知,要求统计在校师生人数,你觉得,校长会怎么干?是哪一个小本本,一个一个统计:计算机学院多少人,软件学院多少人,还是把他的左膀右臂——两个院长叫过来。答案显然易见,肯定会摇人,院长见校长这么想,肯定也会叫导员,层层外包,最后,班长成苦命的打工人。

                统计节点个数的思路与上文类似,都是层层分封然后加上自己即可。代码实现如下:

int BinaryTreeSize(BTNode* root)
{if (root == NULL){return 0;}return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

         1.5 二叉树叶子节点个数

                此问题我们可不可以运用上题的思路解决,当然可以。实现代码如下:

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);
}

                这里的实现思路只不过换成只要是叶节点就放回一。

        1.6  二叉树查找值为x的节点

                相信有一部分人看到此题,说:“简单”。然后写出以下代码:

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}return BinaryTreeFind(root->left,x);return BinaryTreeFind(root->right,x);
}

                这个代码乍一看,大逻辑好像是对的,其实不然,如果,左子树,能够找到,那最好了。但,右子树和部分左子树根本找不到。为啥?一个函数是不是只有一个返回值,结构体可以有多个。既然只有一个,那么注定只能放回一个,其余的哪怕是找到了也会没找到,无法得用。

                优化后代码如下:

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BTNode*p1 = BinaryTreeFind(root->left,x);if (p1){return p1;}BTNode* p2 = BinaryTreeFind(root->right,x);//分别用指针记录,找到才返回if (p2){return p2;}return NULL;
}

        1.7 二叉树第k层节点个数

                求第k层高度,各位读者有没有思路。这里的难点为:如何找到该层。只要能找到,统计节点,那都会,对吧。

                这里提供一种想法,仅供参考:每一次使k--,叫k的值和一比。如果等于一,则到了要找的层,不为一就继续,没有就返回0。代码实现思路如下:

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);
}

        1.8 二叉树的高度

                我们在这里想,如何求出二叉树的高度呢?是不是可以转换成左子树和右子树谁更高的问题。谁高就加一,对吧。来先看以下代码:

int TreeHight(BTNode* root)
{if (root == NULL){return 0;}return TreeHight(root->left) > TreeHight(root->right) ?TreeHight(root->left) + 1 : TreeHight(root->right) + 1;
}

                这代码,从逻辑和结果上来看,没啥问题。但,复杂度太高。

                

                 咱们的想法是运用递归实现,本题中的代码,没有一个记录的,本次用完,别人想用,就忘记了,就要重新调。读者可能认为是2倍的关系。其实不然,我用故事来解释一下:

                当班长把统计的人数告诉导员时候,导员说:知道了,你回去吧。走到半路,接到电话,导员说:你在来一下,我给院长汇报时忘记了。班长去汇报,回来。又去为啥:院长统计时又忘记了,又去,又回来,没完没了了,可用下图表示:

                从此图可以看出复杂度是很高的,越是底层,干的就越多。所以,我们可做以下优化:

int TreeHight(BTNode* root)
{if (root == NULL){return 0;}int left = TreeHight(root->left);int right = TreeHight(root->right);return left > right ?left + 1 : right + 1;
}

                 1.9 二叉树的销毁

                        二叉树的销毁其实传不传二级指针都行,不传的化,只需在调用后,手动置空即可。

void TreeDestory(BTNode* root)
{if (root == NULL)return;TreeDestory(root->left);TreeDestory(root->right);free(root);
}

二、代码展示

        BTNode.h

#pragma once
#include<stdio.h>typedef char BTDataType;typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;// 二叉树销毁
void BinaryTreeDestory(BTNode** root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
//求二叉树高度
int TreeHight(BTNode* root);

        BTNode.c

#include"BTNode.h"//二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root)
{if (root == NULL){return;//此处也可打印N}printf("%d", root->data);//按照前序遍历顺序:根BinaryTreePrevOrder(root->left);//左子数BinaryTreePrevOrder(root->right);//右子数
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{if (root == NULL){return;}BinaryTreeInOrder(root->left);printf("%d  ", root->data);BinaryTreeInOrder(root->right);//无不一样之处,只是交换了顺序
}
//二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{if (root == NULL){return;}BinaryTreePostOrder(root->left);BinaryTreePostOrder(root->right);printf("%d  ", root->data);
}
// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{if (root == NULL){return 0;}return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
// 二叉树叶子节点个数
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);
}
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BTNode*p1 = BinaryTreeFind(root->left,x);if (p1){return p1;}BTNode* p2 = BinaryTreeFind(root->right,x);//分别用指针记录,找到才返回if (p2){return p2;}return NULL;
}
//求二叉树高度
int TreeHight(BTNode* root)
{if (root == NULL){return 0;}int left = TreeHight(root->left);int right = TreeHight(root->right);return left > right ?left + 1 : right + 1;
}
// 二叉树销毁
void TreeDestory(BTNode* root)
{if (root == NULL)return;TreeDestory(root->left);TreeDestory(root->right);free(root);
}

最后

        以上,便是我所有说的二叉树的大部分内容了,剩下的部分会在明天我为大家准备的练习题中进行讲解。如果今天讲出来,不太利于大家的理解。希望大家能把今天讲的知识拿去练习,好好理解巩固一下,我们明天再会!

完!

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

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

相关文章

skynet.newservice简介:服务的启动

skynet是一个轻量级的游戏服务器框架。 简介 在skynet的体系中&#xff0c;服务是一个基础概念。通常&#xff0c;我们使用skynet.newservice来启动一个snlua服务。 那么&#xff0c;当我们写下local addr skynet.newservice("test")这行代码时&#xff0c;系统是怎…

【Java Web】前端利用 form 表单传多项数据,后端 Servlet 取出的各项数据均为空

前端利用 form 表单传多项数据&#xff0c;后端 Servlet 取出的各项数据均为空 文章目录 1.问题引入2.问题解决 1.问题引入 最近在写一个 java web 项目时&#xff0c;遇到一个让我头疼了一下午的问题&#xff1a;前端通过 post 提交的 form 表单数据可以传到后端&#xff0c…

Windows远程连接命令?

Windows操作系统提供了多种远程连接命令&#xff0c;使用户可以通过网络连接到远程计算机&#xff0c;并在远程操作系统上执行操作。远程连接命令可方便实现远程工作、故障排查和系统维护等任务。本文将介绍几种常见的Windows远程连接命令及其基本使用方法。 远程连接命令 Win…

心链2---前端开发(整合路由,搜索页面,用户信息页开发)

心链——伙伴匹配系统 接口调试 说书人&#x1f4d6;&#xff1a;上回书说到用了两种方法查询标签1.SQL查询&#xff0c;2.内存查询&#xff1b;两种查询效率是部分上下&#xff0c;打的是难解难分&#xff0c;是时大地皴裂&#xff0c;天色聚变&#xff0c;老祖斟酌再三最后决…

仪器校准中移液器的使用规范,应当注意哪些细节?

校准行业中&#xff0c;移液器的使用是非常多的&#xff0c;尤其是理化室&#xff0c;经常需要借助到移液器来校准。作为常规的溶液定量转移器具&#xff0c;其在校准过程中的使用也需要遵守规范&#xff0c;既是保证校准结果准确低误差&#xff0c;也是为了规范实验室校准人员…

2024.5.25晚训题解

这套题挺简单的。。。 A题 AC率差不多100% B题 AC率差不多75% C题 AC率也差不多75% D题 AC率 50% E题 AC率 25% 向着top 1%出发 A题题解 Stair, Peak, or Neither? 简单判断题&#xff0c;自己写 #include<bits/stdc.h> using namespace std; int A[5]; int main() {…

llama-factory学习个人记录

框架、模型、数据集准备 1.llama-factory部署 # 克隆仓库 git clone https://github.com/hiyouga/LLaMA-Factory.git # 创建虚拟环境 conda create --name llama_factory python3.10 # 激活虚拟环境 conda activate llama_factory # 安装依赖 cd LLaMA-Factory pip install -…

线性回归模型

目录 1.概述 2.线性回归模型的定义 3.线性回归模型的优缺点 4.线性回归模型的应用场景 5.线性回归模型的未来展望 6.小结 1.概述 线性回归是一种广泛应用于统计学和机器学习的技术&#xff0c;用于研究两个或多个变量之间的线性关系。在本文中&#xff0c;我们将深入探讨…

会声会影调速怎么用 会声会影如何调整音频速度

会声会影是一款功能强大的视频编辑软件&#xff0c;可以帮助我们轻松的实现剪辑。 会声会影的操作简单易懂&#xff0c;界面简洁明快。适合家庭使用&#xff0c; 我们使用会声会影可以在家就能将视频剪辑成好莱坞大片。但是在使用的过程中&#xff0c;仍然会遇到一些操作上的问…

微信小程序预览图片和H5使用canvas实现图片+蒙层+文字

1、效果 2.H5实现 <!--* Author: limingfang* Date: 2024-05-20 10:26:51* LastEditors: limingfang* LastEditTime: 2024-05-21 16:31:11* Description: --> <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8&q…

【小程序 按钮 表单 】

按钮 代码演示 xxx.wxml <view class"boss" hover-class"box"hover-start-time"2000"hover-stay-time"5000">测试文本<view hover-stop-propagation"true">子集</view><view>子集2</view>…

Capture One Studio for Mac:打造完美影像的利器

对于摄影师而言&#xff0c;每一次按下快门都是一次对完美影像的追求。而Capture One Studio for Mac正是这样一款能够帮助你实现这一追求的利器。 Capture One Studio for Mac v16.4.2.1中文直装版下载 首先&#xff0c;Capture One Studio for Mac拥有出色的图像处理能力。它…

Java—二分查找

介绍 二分查找&#xff08;Binary Search&#xff09;是一种在有序数组中查找特定元素的搜索算法。其基本思想是将目标值与数组中间的元素进行比较&#xff1a; 如果目标值等于中间元素&#xff0c;则查找成功。如果目标值小于中间元素&#xff0c;则在数组左半部分继续进行二…

2024年汉字小达人活动4个多月开赛:18道历年选择题和答案、解析

根据近年的安排&#xff0c;2024年第11届汉字小达人比赛还有4个多月就启动&#xff0c;那么孩子们如何利用这段时间有条不紊地备考呢&#xff1f;我的建议是两手准备&#xff1a;①把小学1-5年级的语文课本上的知识点熟悉&#xff0c;重点是字、词、成语、古诗。②把历年真题刷…

VTK 数据处理:特征边提取

VTK 数据处理&#xff1a;特征边提取 VTK 数据处理&#xff1a;特征边提取原理实例 1&#xff1a;边界边提取实例 2&#xff1a;模型特征边提取实例 3&#xff1a;利用 vtkFeatureEdges 提取的边界补洞实例 4&#xff1a;利用 vtkFillHolesFilter 补洞 VTK 数据处理&#xff1a…

全局平均池化笔记

全局平均池化&#xff08;Global Average Pooling, GAP&#xff09;是一种用于卷积神经网络&#xff08;CNN&#xff09;中的池化操作&#xff0c;其主要作用和优点包括&#xff1a; 减少参数数量&#xff1a;全局平均池化层将每个特征图通过取其所有元素的平均值&#xff0c;压…

初识Spring Boot

初识Spring Boot SpringBoot是建立在Spring框架之上的一个项目,它的目标是简化Spring应用程序的初始搭建以及开发过程。 对比Spring Spring Boot作为Spring框架的一个模块&#xff0c;旨在简化Spring应用程序的初始搭建和开发过程&#xff0c;以下是Spring Boot相对于传统Spri…

[datawhale202405]从零手搓大模型实战:TinyAgent

结论速递 TinyAgent项目实现了一个简单的Agent智能体&#xff0c;主要是实现了ReAct策略&#xff08;推理调用工具的能力&#xff09;&#xff0c;及封装了一个Tool。 项目实现有一定的疏漏。为了正确运行代码&#xff0c;本次对代码Agent部分进行了简单修改&#xff08;完善…

【Linux】Linux的安装

文章目录 一、Linux环境的安装虚拟机 镜像文件云服务器&#xff08;可能需要花钱&#xff09; 未完待续 一、Linux环境的安装 我们往后的学习用的Linux版本为——CentOs 7 &#xff0c;使用 Ubuntu 也可以 。这里提供几个安装方法&#xff1a; 电脑安装双系统&#xff08;不…

关于burp的intruder返回包空白问题

记录一下被自己蠢笑的问题 burp返回包为空怎么办&#xff0c;在查询无果后经过多次试验&#xff0c;确实没有效果 看那三个点还以为加载呢&#xff0c;攻击完了怎么一个显示没有 于是…… 鼠标到三个点&#xff0c;往下一拉 哈哈哈哈哈哈哈&#xff0c;真是被自己给蠢到了