103.【C语言】数据结构之二叉树的三种递归遍历方式

目录

1.知识回顾

2.分析二叉树的三种遍历方式

1.总览

2.前序遍历

3.中序遍历

4.后序遍历

5.层序遍历

3.代码实现

1.准备工作

2.前序遍历函数PreOrder

测试结果

3.中序遍历函数InOrder

测试结果

4.后序遍历函数PostOrder

测试结果

4.底层分析


1.知识回顾

在99.【C语言】数据结构之二叉树的基本知识文章中提到:任何一棵树都由两部分构成:根和子树,子树又由根和子树构成

因此看见二叉树要本能地做出反应:拆成三部分:根,左子树和右子树,直到遇到空树(叶节点)则停止拆分

 

2.分析二叉树的三种遍历方式

1.总览

前序遍历

中序遍历

后序遍历

层序遍历(要借助队列,本文暂时不讲其代码实现)

下面三种遍历方式都基于上面这张图分析

2.前序遍历

定义:按根-->左子树-->右子树的顺序遍历

遍历顺序:

1(根)-->2(根)-->3(根)-->NULL(3的左子树)-->NULL(3的右子树)-->NULL(2的右子树)-->4(根)-->5(根)-->NULL(5的左子树)-->NULL(5的右子树)-->6(根)-->NULL(6的左子树)-->NULL(6的右子树)

备注:图中每个方框都代表一棵子树

3.中序遍历

定义:按左子树-->根-->右子树的顺序遍历

这里有一个易错点也是关键点:中序遍历中第一个访问的一定为空!!!!

虽然1的左节点为2,但不能访问2(即不可访问root->data),按中序遍历的定义,要先访问2的左子树;虽然2的左节点为3,但不能访问3,按中序遍历的定义,先访问3左子树;3的左子树为NULL,其没有子树,因此开始访问根(即3),再访问根的右子树NULL,再回归......

左子树访问完才能访问根

遍历顺序:NULL(3的左子树)-->3-->NULL(3的右子树)-->2(根)-->NULL(2的右子树)-->1(根)-->NULL(5的左子树)-->5(根)-->NULL(5的右子树)-->4(根)-->NULL(6的左子树)-->6(根)-->NULL(6的右子树)

备注:图中每个方框都代表一棵子树  

4.后序遍历

定义:按左子树-->右子树-->根的顺序遍历

和中序遍历一样,也有一个易错点也是关键点:和中序遍历一样,先访问左子树,因此后序遍历中第一个访问的也一定为空!!!!

遍历顺序:NULL(3的左子树)-->NULL(3的右子树)-->3(根)-->NULL(2的右子树)-->2(根)-->NULL(5的左子树)-->NULL(5的右子树)-->5(根)-->NULL(6的左子树)-->NULL(6的右子树)-->6(根)-->4(根)-->1(根)

备注:图中每个方框都代表一棵子树   

5.层序遍历

定义:按的方式遍历(,设n为树的深度,h==1-->h==2-->h==3-->...-->h==n)

遍历顺序:1-->2-->4-->3-->5-->6

h==1为第一层,只有1;h==2为第二层,有2和4;h==3为第三层,有3,5和6;

3.代码实现

1.准备工作

用结构体去定义一个二叉树,其成员变量有:数值域data,结构体指针变量left和right,分别指向其对应的左子树和右子树(写入Tree.h)

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

定义完二叉树后还要开辟空间函数BuyNode和建立树的函数(写入Tree.c)

BTNode* BuyNode(BTDataType x)
{BTNode* node = (BTNode*)malloc(sizeof(BTNode));if (node == NULL){perror("malloc");return NULL;}node->data = x;node->left = NULL;node->right = NULL;return node;
}

建立指定的二叉树,见下图

 

BTNode* CreateTree()
{//写入各个节点的数据域BTNode* node1 = BuyNode(1);BTNode* node2 = BuyNode(2);BTNode* node3 = BuyNode(3);BTNode* node4 = BuyNode(4);BTNode* node5 = BuyNode(5);BTNode* node6 = BuyNode(6);//设置left和right指针node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;//返回根节点的指针return node1;
}

递归返回的条件:遇到空树(NULL)

2.前序遍历函数PreOrder

根-->左子树-->右子树的顺序遍历,

printf("%d ",root->data);-->PreOrder(root->left);-->PreOrder(root->right);

void PreOrder(BTNode* root)
{//先判断是否为空树(叶节点的左节点和右节点均为空树)if (root == NULL){printf("NULL ");return;}//按根-->左子树-->右子树的顺序遍历printf("%d ",root->data);PreOrder(root->left);PreOrder(root->right);
}

注意:一定要先判断是否为空树(叶节点的左节点和右节点均为空树)

测试结果

mainc.c写入以下代码

#include "Tree.h"
int main()
{BTNode* root = CreateTree();PreOrder(root);return 0;
}

和前面的图完全符合

3.中序遍历函数InOrder

:按左子树-->根-->右子树的顺序遍历,

InOrder(root->left);-->printf("%d ", root->data);-->InOrder(root->right);

void InOrder(BTNode* root)
{//先判断是否为空树(叶节点的左节点和右节点均为空树)if (root == NULL){printf("NULL ");return;}//按左子树-->根-->右子树的顺序遍历InOrder(root->left);printf("%d ", root->data);InOrder(root->right);
}

注意:一定要先判断是否为空树(叶节点的左节点和右节点均为空树) 

测试结果

mainc.c写入以下代码

#include "Tree.h"
int main()
{BTNode* root = CreateTree();InOrder(root);return 0;
}

 

 和前面的图完全符合

4.后序遍历函数PostOrder

左子树-->右子树-->根的顺序遍历,

PostOrder(root->left);-->PostOrder(root->right);-->printf("%d ", root->data);

void PostOrder(BTNode* root)
{//先判断是否为空树(叶节点的左节点和右节点均为空树)if (root == NULL){printf("NULL ");return;}//按左子树-->右子树-->根的顺序遍历PostOrder(root->left);PostOrder(root->right);printf("%d ", root->data);
}

注意:一定要先判断是否为空树(叶节点的左节点和右节点均为空树) 

测试结果

mainc.c写入以下代码

#include "Tree.h"
int main()
{BTNode* root = CreateTree();PostOrder(root);return 0;
}

和前面的图完全符合

4.底层分析

每调用一次PreOrder或InOrder或PostOrder函数就压入栈区,返回时出栈

在E41.【C语言】练习:斐波那契函数的空间复杂度的计算及函数调用分析文章中讲过了函数调用的堆栈分析,这里不再赘述

附一张PreOrder的调用图

附一张InOrder的调用图

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

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

相关文章

【kafka03】消息队列与微服务之Kafka 读写数据

Kafka 读写数据 参考文档 Apache Kafka 常见命令 kafka-topics.sh #消息的管理命令 kafka-console-producer.sh #生产者的模拟命令 kafka-console-consumer.sh #消费者的模拟命令 创建 Topic 创建topic名为 chen,partitions(分区)为3&#xff0…

SAP开发语言ABAP开发入门

1. 了解ABAP开发环境和基础知识 - ABAP简介 - ABAP(Advanced Business Application Programming)是SAP系统中的编程语言,主要用于开发企业级的业务应用程序,如财务、物流、人力资源等模块的定制开发。 - 开发环境搭建 - 首先需…

[护网杯 2018]easy_tornado

这里有一个hint点进去看看,他说md5(cookie_secretmd5(filename)),所以我们需要获得cookie_secret的value 根据题目tornado,它可能是tornado的SSTI 这里吧filehash改为NULL. 是tornado的SSTI 输入{{handler.settings}} (settings 属性是一个字典&am…

【k8s深入学习之 Scheme】全面理解 Scheme 的注册机制、内外部版本、自动转换函数、默认填充函数、Options等机制

参考 【k8s基础篇】k8s scheme3 之序列化_基于schema进行序列化-CSDN博客【k8s基础篇】k8s scheme4 之资源数据结构与资源注册_kubernetes 的scheam-CSDN博客 Scheme的字段总览 type Scheme struct {// gvkToType 允许通过给定的版本和名称来推断对象的 Go 类型。// map 键是…

PySide6 QSS(Qt Style Sheets) Reference: PySide6 QSS参考指南

Qt官网参考资料: QSS介绍: Styling the Widgets Application - Qt for Pythonhttps://doc.qt.io/qtforpython-6/tutorials/basictutorial/widgetstyling.html#tutorial-widgetstyling QSS 参考手册: Qt Style Sheets Reference | Qt Widge…

python控制鼠标,键盘,adb

python控制鼠标,键盘,adb 听说某系因为奖学金互相举报,好像拿不到要命一样。不禁想到几天前老墨偷走丁胖子的狗,被丁胖子逮到。他面对警察的问询面不改色坚持自我,反而是怒气冲冲的丁胖子被警察认为是偷狗贼。我觉得这…

前端Vue项目整合nginx部署到docker容器

一、通过Dockerfile整合nginx方法: 1,使用Vue CLI或npm脚本构建生产环境下的Vue项目。 npm run build or yarn build2,构建完成后,项目目录中会生成一个dist文件夹,里面包含了所有静态资源文件(HTML、CSS…

ChatGPT的应用场景:开启无限可能的大门

ChatGPT的应用场景:开启无限可能的大门 随着人工智能技术的快速发展,自然语言处理领域迎来了前所未有的突破。其中,ChatGPT作为一款基于Transformer架构的语言模型,凭借其强大的语言理解和生成能力,在多个行业和场景中展现出了广泛的应用潜力。以下是ChatGPT八个最具代表…

Wireshark抓取HTTPS流量技巧

一、工具准备 首先安装wireshark工具,官方链接:Wireshark Go Deep 二、环境变量配置 TLS 加密的核心是会话密钥。这些密钥由客户端和服务器协商生成,用于对通信流量进行对称加密。如果能通过 SSL/TLS 日志文件(例如包含密钥的…

【dvwa靶场:File Upload系列】File Upload低-中-高级别,通关啦

目录 一、low级别,直接上传木马文件 1.1、准备一个木马文件 1.2、直接上传木马文件 1.3、访问木马链接 1.4、连接蚁剑 二、medium级别:抓包文件缀名 2.1、准备一个木马文件,修改后缀名为图片的后缀名 2.2、上传文件,打开burpSuite&…

【深度学习|目标跟踪】StrongSort 详解(以及StrongSort++)

StrongSort详解 1、论文及源码2、DeepSort回顾3、StrongSort的EMA4、StrongSort的NSA Kalman5、StrongSort的MC6、StrongSort的BOT特征提取器7、StrongSort的AFLink8、未完待续 1、论文及源码 论文地址:https://arxiv.org/pdf/2202.13514 源码地址:https…

10、PyTorch autograd使用教程

文章目录 1. 相关思考2. 矩阵求导3. 两种方法求jacobian 1. 相关思考 2. 矩阵求导 假设我们有如下向量: y 1 3 x 1 5 [ w T ] 5 3 b 1 3 \begin{equation} y_{1\times3}x_{1\times5}[w^T]_{5\times3}b_{1\times3} \end{equation} y13​x15​[wT]53​b13​​…

【AI】Sklearn

长期更新,建议关注、收藏、点赞。 友情链接: AI中的数学_线代微积分概率论最优化 Python numpy_pandas_matplotlib_spicy 建议路线:机器学习->深度学习->强化学习 目录 预处理模型选择分类实例: 二分类比赛 网格搜索实例&…

软件质量保证——软件测试流程

笔记内容及图片整理自XJTUSE “软件质量保证” 课程ppt,仅供学习交流使用,谢谢。 对于软件测试中产品/服务/成果的质量,需要细化到每个质量特性上,因此出现了较为公认的软件质量模型,包括McCall质量模型、ISO/IEC 9126…

代码美学2:MATLAB制作渐变色

效果: %代码美学:MATLAB制作渐变色 % 创建一个10x10的矩阵来表示热力图的数据 data reshape(1:100, [10, 10]);% 创建热力图 figure; imagesc(data);% 设置颜色映射为“cool” colormap(cool);% 在热力图上添加边框 axis on; grid on;% 设置热力图的颜色…

从0开始学PHP面向对象内容之常用设计模式(组合,外观,代理)

二、结构型设计模式 4、组合模式(Composite) 组合模式(Composite Pattern)是一种结构型设计模式,它将对象组合成树形结构以表示”部分–整体“的层次结构。通过组合模式,客户端可以以一致的方式处理单个对…

femor 第三方Emby应用全平台支持v1.0.54更新

femor v1.0.54 版本更新 mpv播放器增加切换后台和恢复时隐藏状态栏的功能修复服务器首页因为连接超时异常的问题 获取路径:【femor 历史版本收录】

如何搭建一个小程序:从零开始的详细指南

在当今数字化时代,小程序以其轻便、无需下载安装即可使用的特点,成为了连接用户与服务的重要桥梁。无论是零售、餐饮、教育还是娱乐行业,小程序都展现了巨大的潜力。如果你正考虑搭建一个小程序,本文将为你提供一个从零开始的详细…

nrm镜像管理工具使用方法

nrm(NPM Registry Manager)是一款专门用于管理 npm 包镜像源的命令行工具。在使用 npm 安装各种包时,默认会从官方的 npm 仓库(registry)获取资源,但有时候由于网络环境等因素,访问官方源可能速…

OpenCV截取指定图片区域

import cv2 img cv2.imread(F:/2024/Python/demo1/test1/man.jpg) cv2.imshow(Image, img) # 显示图片 #cv2.waitKey(0) # 等待按键x, y, w, h 500, 100, 200, 200 # 示例坐标 roi img[y:yh, x:xw] # 截取指定区域 cv2.imshow(ROI, roi) cv2.waitKey(0) cv…