【初阶数据结构】掌握二叉树遍历技巧与信息求解:深入解析四种遍历方法及树的结构与统计分析

在这里插入图片描述

初阶数据结构相关知识点可以通过点击以下链接进行学习一起加油!
时间与空间复杂度的深度剖析深入解析顺序表:探索底层逻辑深入解析单链表:探索底层逻辑深入解析带头双向循环链表:探索底层逻辑深入解析栈:探索底层逻辑
深入解析队列:探索底层逻辑深入解析循环队列:探索底层逻辑树与二叉树:从零开始的奇幻之旅理解堆的特性与应用:深入探索完全二叉树的独特魅力

本篇将介绍掌握二叉树的遍历和信息获取方法,有助于我们更好地理解树的结构与统计分析,为接下来学习AVL树与红黑树等高阶数据结构打下基础。对于最后面关于二叉树的特性,需要理解掌握在遇到相关题目可以直接套用。

请添加图片描述
Alt

🌈个人主页:是店小二呀
🌈C语言笔记专栏:C语言笔记
🌈C++笔记专栏: C++笔记
🌈初阶数据结构笔记专栏: 初阶数据结构笔记

🌈喜欢的诗句:无人扶我青云志 我自踏雪至山巅
请添加图片描述

文章目录

  • 一、快速搭建二叉树
  • 二、二叉树组成结构
  • 三、二叉树的遍历
    • 3.1 三种常见遍历(前序/中序/后序遍历)
    • 3.2 层序遍历
  • 四、求二叉树相关信息
    • 4.1 二叉树节点个数
    • 4.2 二叉树叶子节点个数
    • 4.3 求这个棵树的高度
    • 4.4 二叉树第k层节点个数
    • 4.5 二叉树查找值为x的节点
    • 4.5 单值二叉树
    • 4.6 相同的树
    • 4.7 树的销毁(后序)
  • 五、二叉树的性质

一、快速搭建二叉树

为了方便我们更快地学习二叉的基本操作,这里直接手动搭建一颗二叉树。不仅如此,在做二叉树相关题目时,由于部分原因做题平台不支持普通用户使用调试功能,可以快速搭建二叉树在本地编译器上进行调试相关操作

typedef int BTDataType;
typedef struct BinaryTreeNode
{BTDataType _data;struct BinaryTreeNode* _left;struct BinaryTreeNode* _right;
}BTNode;BTNode* BuyNode(BTDataType x)
{BTNode* tmp = (BTNode*)malloc(sizeof(BTNode));if (tmp == NULL){// 处理内存分配失败的情况// 可以选择报错、退出程序或者其他适当的处理方式exit(EXIT_FAILURE)};  // 举例:退出程序tmp->_data = x;tmp->_left = NULL;tmp->_right = NULL;return tmp;
}BTNode* CreatBinaryTree()
{BTNode* node1 = BuyNode(1);BTNode* node2 = BuyNode(2);BTNode* node3 = BuyNode(3);BTNode* node4 = BuyNode(4);BTNode* node5 = BuyNode(5);BTNode* node6 = BuyNode(6);node1->_left = node2;node1->_right = node4;node2->_left = node3;node4->_left = node5;node4->_right = node6;return node1;
}

二、二叉树组成结构

二叉树大致分为两种

  • 空树
  • 非空:根节点,的左子树,右子树(左右子树可能为空树)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这里插入图片描述
从概念中可以看出来,根据不同节点可以划分多个子树,对此二叉树定义是递归式的,因此后续基本操作都是按照概念实现的。

三、二叉树的遍历

学习二叉树的结构,最简单的方式就是遍历,遍历是二叉树上最重要的运算之一,也是二叉树上进行其他运算的基础。二叉树遍历按照某种特定的规则,依次对二叉树中的节点进行对应的操作,并且每个节点只操作一次。

在这里插入图片描述

3.1 三种常见遍历(前序/中序/后序遍历)

根据规定,访问顺序左子树是先于右子树,导致了二叉树遍历有三种递归式结构前序/中序/后序的遍历,被访问节点必是某子树的根。根据英文缩写可以通过N、L、R表示根、左子树、右子树,对此NLR、LNR和LRN称为先根遍历、中根遍历和后根遍历。

在这里插入图片描述

根据例子更好的理解其中的含义,不然很难get到其中的真谛。尝试下前序/中序/后序,写出访问顺序(空也会访问,用N代表)

在这里插入图片描述

前序:123NNN45NN6NN
中序:N3N2N1N5N4N6N
后序:NN3N2NN5NN641

过程解析:

达到1号节点为根,访问左子树;达到2号节点为根;访问左子树;达到3号节点为根;访问左子树;达到为空位置返回,访问根(3号),访问右子树;达到空位置,以3号为根子树访问完;以2号为根左子树访问完,访问根(2号);以此类推直到遍历完毕(按照这种方式,剩下两种遍历也是很好掌握的)

在这里插入图片描述

3.2 层序遍历

除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历

在这里插入图片描述

void LevelOrder(BTNode* root)
{// 0. 声明队列queue<TreeNode*> q;// 1. 将根节点加入队列q.push(root);// 2. 遍历队列中每个节点while (!q.empty()) {TreeNode* cur = q.front();q.pop();// 3. 记录当前节点值vec.push(cur->val);// 4. 将左右孩子放入队列q.push(cur->left);q.push(cur->right);}
}

这里使用C++语法直接调用库里面的queue容器,直接主要是分享思路,语法看不懂没有关系。

在这里插入图片描述

使用场景:判断是否为完全二叉树(C++代码)。

// 判断是否为完全二叉树
bool isCompleteTree(TreeNode* root) {if (root == nullptr) {return true;}queue<TreeNode*> q;q.push(root);bool foundNull = false;while (!q.empty()) {TreeNode* currentNode = q.front();q.pop();if (currentNode == nullptr) {foundNull = true;} else {if (foundNull) {return false;}q.push(currentNode->left);q.push(currentNode->right);}}return true;
}

大致思路:完全二叉树特性是从左到右是连续的,该特性保证了最后一个位置为空,那么判断是否为完全二叉树只需要在遇到空节点之后不会再出现非空节点即可。可以使用层序遍历(层序遍历也是适用于普通二叉树)如果队列出空,但是队列不为空说明不是完全二叉树.。

四、求二叉树相关信息

4.1 二叉树节点个数

瑕疵版本:使用静态局部变量进行计数

int TreeSize(TreeNode* root)
{static int size = 0;if (root == NULL){return 0;}++size;TreeSize(root->left);TreeSize(root->right);return size;
}

瑕疵版本:使用全局变量进行计数

int size = 0;
void TreeSize(TreeNode* root)
{if (root == NULL)return;++size;TreeSize(root->left);TreeSize(root->right);
}

方法分析:无论是使用静态还是全局变量,使得生命周期不会受到函数栈帧销毁的影响,可以解决求节点个数的问题。问题在于静态还是全局变量只能被定义一次,这就意味着第一次计算出来的结果是正确的,那么第二次的结果会延用上一次变量存储的值,不会清空重新计数,程序结束(以上一次值为基准)导致结果错误。

修正版本:画图分析
在这里插入图片描述

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

过程解析:这里使用分治思想,可以将求整课树节点个数分为求左右子树节点个数加上根节点之和,不断划分,去看最几步过程去递推和归并去发现规律。比如:以3为根节点,得到左右子树为空返回结果为0,返回给2节点的结果就是0 + 0 + 1(1为根节点)返回结果为:以2为根节点左子树的节点个数BinaryTreeSize(root->left)等于BinaryTreeSize(root->left-left) + BinaryTreeSize(root->left->right) + 1(如果觉得这样子很难理解,建议画图去研究递归的过程)。

4.2 二叉树叶子节点个数

在这里插入图片描述

int BinaryTreeLeafSize(TreeNode* root)
{if (root == NULL) return 0;if (root->left == NULL && root->right == NULL) return 1;return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

过程解析这里也是使用了分治的思想,求整棵树叶子节点个数之和分为求左右子树叶子节点个数之后。根据题目要求访问三种情况:空节点返回0,不是空节点,属于叶子节点返回1,不是空节点也不是叶子节点,使用分治等于左右子树叶子之后。

4.3 求这个棵树的高度

在这里插入图片描述

过程解析这里也是使用了分治的思想,求整棵树高度分为求左右子树高度之间最大的高度再+1

瑕疵版本

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

在这里插入图片描述

由于TreeHeight(root->left) > TreeHeight(root->right) 的比较是不会记录结果,需要高的那一份再次递归调用,因此多次递归调用 TreeHeight(root->left)TreeHeight(root->right),造成重复计算。

修正版本:(记录得到目前高度进行比较)

int TreeHeight(TreeNode* root) 
{if (root == NULL) return 0;int leftHeight = TreeHeight(root->left);int rightHeight = TreeHeight(root->right);return max(leftHeight, rightHeight) + 1;
}

4.4 二叉树第k层节点个数

在这里插入图片描述

int TreeLevelK(TreeNode* root, int k)
{assert(k > 0);if (root == NULL)return 0;if (k == 1)return 1;return TreeLevelK(root->left, k-1)+ TreeLevelK(root->right, k-1);
}

过程解析:跟求整棵树节点个数问题是差不多,主要差异在于对于范围的限制,无非添加一个变量(临时变量)进行递归,每一层的k值是不同的,到达一定条件停止返回如果为空返回0,如果为非空返回1,都建立在k>0的前提下。

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

瑕疵版本:在这里插入图片描述

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

过程解析:return 是return 上一层的,不是直接到最外层的。这里导致了没有接受到返回值传出。

修正版本

TreeNode* TreeFind(TreeNode* root, BTDataType x)
{if (root == NULL) return NULL;if (root->data == x) return root;TreeNode* ret1 = TreeFind(root->left, x);if (ret1) return ret1;TreeNode* ret2 =  TreeFind(root->right, x);if (ret2) return ret2;return NULL;
}

4.5 单值二叉树

在这里插入图片描述

bool isUnivalTree(TreeNode* root)
{if(root == NULL) return true;if(root->left && root->left->val != root->val)return false;if(root->right && root->right->val != root->val)return false;return isUnivalTree(root->left) && isUnivalTree(root->right);
}

4.6 相同的树

在这里插入图片描述

bool isSameTree(struct TreeNode* p, struct TreeNode* q) 
{//都为空if(p == NULL && q == NULL) return true;//其中一个为空(前面排除了都为空的情况)if(p == NULL || q == NULL) return false;//都不为空且不相等if(p->val != q->val) return false;return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}

4.7 树的销毁(后序)

在这里插入图片描述

五、二叉树的性质

二叉树的性质

  1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2(i-1)个结点

  2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是2h-1

  3. 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h= log2(n + 1)(ps: 是log以2为底,n+1为对数)

  4. 对任何一棵二叉树, 如果度为0其叶结点个数为 n0, 度为2的分支结点个数为n2,则有 n0 = n2 + 1

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


以上就是本篇文章的所有内容,在此感谢大家的观看!这里是店小二初阶数据结构笔记,希望对你在学习初阶数据结构中有所帮助!
请添加图片描述

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

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

相关文章

【Django+Vue3 线上教育平台项目实战】Celery赋能:优化订单超时处理与自动化定时任务调度

文章目录 前言⭐✨&#x1f4ab;&#x1f525;&#x1f4d6;一、Celery⭐1.基本概念及介绍:✨2.使用步骤&#x1f4ab; 二、订单超时 取消订单&#xff08;Celery&#xff09;&#x1f525;具体实现流程&#x1f4d6; 前言⭐✨&#x1f4ab;&#x1f525;&#x1f4d6; 在构建复…

GIT命令学习 二

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 ☁️运维工程师的职责&#xff1a;监…

开源智能助手平台Dify是什么?

1.背景 对于国内小公司&#xff0c;怎样通过Ai 将内部流程、产品重新做一次&#xff0c;从而提高人效、给客户带来价值&#xff0c;这是老板们在考虑的问题 &#xff1f; 当前市面上的你大模型例如&#xff1a;通义千问、文心一言、kimi、智谱清言、盘古 等&#xff0c;底层能…

JavaWeb服务器-Tomcat(Tomcat概述、Tomcat的下载、安装与卸载、启动与关闭、常见的问题)

Tomcat概述 Tomcat服务器软件是一个免费的开源的web应用服务器。是Apache软件基金会的一个核心项目。由Apache&#xff0c;Sun和其他一些公司及个人共同开发而成。 由于Tomcat只支持Servlet/JSP少量JavaEE规范&#xff0c;所以是一个开源免费的轻量级Web服务器。 JavaEE规范&…

python-网络并发模型

3. 网络并发模型 3.1 网络并发模型概述 什么是网络并发 在实际工作中&#xff0c;一个服务端程序往往要应对多个客户端同时发起访问的情况。如果让服务端程序能够更好的同时满足更多客户端网络请求的情形&#xff0c;这就是并发网络模型。 循环网络模型问题 循环网络模型只能…

逻辑回归损失函数

文章目录 1.基础简析交叉熵损失函数&#xff08;Cross-Entropy Loss&#xff09;对数似然损失函数&#xff08;Log-Likelihood Loss&#xff09; 2.关键步骤3.案例 1.基础简析 逻辑回归&#xff08;Logistic Regression&#xff09;是一种广泛应用于分类问题的统计模型&#x…

C++进阶 继承

目录 继承的概念及定义 继承概念 继承定义 定义格式 继承关系和访问限定符 继承基类成员访问方式的变化 基类和派生类对象赋值转换 继承中的作用域 派生类的默认成员函数 构造函数 拷贝构造函数 赋值运算符重载 析构函数 总结 继承与友元 继承与静态成员 浅谈复杂…

Scott Brinker:消除噪音越来越难?这是一个越来越有效的营销渠道

合作伙伴成为更有效的渠道 对于普通读者来说&#xff0c;我看好生态系统并不奇怪。我一直主张&#xff0c;平台生态系统可以解决不断变化、高度多样化的市场格局中的许多挑战。这也是我在HubSpot和公司的技术合作伙伴生态系统所关注的。 在本月早些时候的文章中&#xff0c;我…

SpringMVC源码深度解析(中)

接上一遍博客《SpringMVC源码深度解析(上)》继续聊。最后聊到了SpringMVC的九大组建的初始化&#xff0c;以 HandlerMapping为例&#xff0c;SpringMVC提供了三个实现了&#xff0c;分别是&#xff1a;BeanNameUrlHandlerMapping、RequestMappingHandlerMapping、RouterFunctio…

AI一站式科研写作利器:PaperPal

文章目录 在线编辑Word 插件 在线编辑 PaperPal是一款面向科研人员的写作工具&#xff0c;支持在线编辑以及Word插件。下面以在线编辑为例&#xff0c;详述PaperPal的润色功能。 进入网页后&#xff0c;点击【新建在线文档】&#xff0c;即可开启润色功能&#xff0c;界面如下…

《昇思25天学习打卡营第24天|基于 MindSpore 实现 BERT 对话情绪识别》

1. BERT 模型概述 BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是一个预训练的语言表示模型&#xff0c;可以应用于多种自然语言处理任务&#xff0c;包括对话情绪识别。BERT 通过双向 Transformer 编码器&#xff0c;能同时考虑句子…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 图像物体的边界(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线…

word 设置目录中英文字母大写改为小写

选中目录右击“字体”&#xff0c;设置“小型大写字母”。

【Vue3】工程创建及目录说明

【Vue3】工程创建及目录说明 背景简介开发环境开发步骤及源码 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的日…

【LeetCode】从中序与后序遍历序列构造二叉树

目录 一、题目二、解法完整代码 一、题目 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7], …

谷粒商城实战笔记-40-前端基础-Vue-计算属性、监听器、过滤器

文章目录 一&#xff0c;计算属性1&#xff0c;用途2&#xff0c;用法2.1 定义View2.2 声明计算属性 3&#xff0c;注意事项 二&#xff0c;监听器1. 使用 watch 监听属性的变化 三&#xff0c;过滤器1&#xff0c;定义局部过滤器2&#xff0c;定义全局过滤器3&#xff0c;使用…

【学习笔记】无人机系统(UAS)的连接、识别和跟踪(六)-无人机直接C2通信

目录 引言 5.4 直接C2通信 5.4.1 概述 5.4.2 A2X直接C2通信服务的授权策略 5.4.3 USS使用A2X直接C2通信服务的C2授权程序 5.4.4 直接C2通信建立程序 引言 3GPP TS 23.256 技术规范&#xff0c;主要定义了3GPP系统对无人机&#xff08;UAV&#xff09;的连接性、身份识别…

bs4模块使用(一)

1. 安装BS4 pip install beautifulsoup4 pip install lxml2. 对象种类 bs4将html文档解析成一个树形结构&#xff0c;每个节点都是python对象&#xff0c;大概可分为下面四种&#xff1a; 2.1 Tag 后面再详细介绍&#xff0c;先介绍最重要的两个属性 name soup Beautiful…

数据结构——队列(链式结构)

一、队列链式结构定义 队列的链式存储结构是一种用链表实现的队列,它不像顺序存储结构那样需要预先分配固定大小的空间。链式存储结构的队列由节点组成,每个节点包括数据和指向下一个节点的指针。队列的链式存储结构可以动态地分配内存,更灵活地处理数据。在链式存储结构中…

【java SE语法篇】1.运算符

目录 1. 运算符和表达式2. 算数运算符3. 隐式转换4. 强制转换5. 自增自减运算符6. 赋值运算符7. 扩展运算符8. 关系运算符9. 逻辑运算符9.1 & 和 | 的使用&#xff1a;9.2 ^&#xff08;异或&#xff09;的使用&#xff1a;9.3 !&#xff08;取反&#xff09;的使用&#x…