二叉树的递归遍历和非递归遍历
目录
一.二叉树的递归遍历
1.先序遍历二叉树
2.中序遍历二叉树
3.后序遍历二叉树
二.非递归遍历(栈)
1.先序遍历
2.中序遍历
3.后序遍历
一.二叉树的递归遍历
定义二叉树
#其中TElemType可以是int或者是char,根据要求自定
typedef struct BiNode{TElemType data;struct BiNode, *lchild,*rchild;}BiNode,*BiTree;void visit(TElemType data) {printf("%d ", data);
}
1.先序遍历二叉树
void PreOrderTraverse(BiTree T)
{if(T==NULL)return ok;//空二叉树else{visit(T);//访问根节点PreOrderTraverse(T->lchild);//递归遍历左子树PreOrderTraverse(T->rchild);//递归遍历右子树}
}
2.中序遍历二叉树
void InOrderTraverse(BiTree T)
{if(T==NULL)return ok;//空二叉树else{InOrderTraverse(T->lchild);//递归遍历左子树visit(T);//访问根节点InOrderTraverse(T->rchild);//递归遍历右子树}
}
3.后序遍历二叉树
void PostOrderTraverse(BiTree T)
{if(T==NULL)return ok;//空二叉树else{PostOrderTraverse(T->lchild);//递归遍历左子树PostOrderTraverse(T->rchild);//递归遍历右子树visit(T);//访问根节点}
}
遍历的规则,以先序遍历为例:
如果去掉输出语句,从递归角度,三种算法是完全相同的,三种算法访问路径是相同的,只是访问时机不同
第一次经过时访问=先序遍历
第二次经过时访问=中序遍历
第三次经过时访问=后序遍历
二.非递归遍历(栈)
typedef struct BiTNode {char data;struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;typedef struct {BiTree data[MAX_SIZE];int top;
} Stack;void InitStack(Stack** S) {*S = (Stack*)malloc(sizeof(Stack));(*S)->top = -1;
}int StackEmpty(Stack* S) {return (S->top == -1);
}int StackFull(Stack* S) {return (S->top == MAX_SIZE - 1);
}void push(Stack* S, BiTree elem) {if (StackFull(S)) {printf("Stack is full. Cannot push element.\n");return;}S->top++;S->data[S->top] = elem;
}void pop(Stack* S, BiTree* elem) {if (StackEmpty(S)) {printf("Stack is empty. Cannot pop element.\n");return;}*elem = S->data[S->top];S->top--;
}int GetTop(Stack* S, BiTree* elem) {if (StackEmpty(S)) {printf("Stack is empty. Cannot get top element.\n");return 0;}*elem = S->data[S->top];return 1;
}
1.先序遍历
(1)从根结点开始先压左路结点,并访问结点,直到把根结点和左路结点全部压入栈。
(2)若左子树和为空,说明左路和根结点已经全部压栈并且已经访问过了,开始取栈顶元素来访问上一层父节点的右子树。把右子树看成子问题继续进行(1)
(3)依次进行上述(1)和(2)压栈访问和出栈操作,直到栈为空或者右子树为空这说明遍历完毕
void PreOrderTraverse(BiTree T)
{Stack* S;BiTree p, q;InitStack(&S);p = T;while (p || !StackEmpty(S)){if (p){printf("%c", p->data);push(S, p); // 将节点 p 入栈p = p->lchild;}else{pop(S, &q);p = q->rchild;}}free(S); // 释放 Stack 结构体内存
}
2.中序遍历
中序遍历和先序遍历思路类似,区别在于,先序遍历先访问根,在访问左,中序遍历先访问左,在访问根,最后都再访问右
void InOrderTraverse(BiTree T)
{Stack* S;BiTree p, q;InitStack(&S);p = T;while (p || !StackEmpty(S)){if (p){push(S, p);p = p->lchild;}else{pop(S, &q);printf("%c", q->data);p = q->rchild;}}free(S); // 释放 Stack 结构体内存
}
3.后序遍历
后续遍历必须访问完左右子树之后才可以访问父亲结点,所以访问完左子树时,现在得去访问右子树,通过栈找到父亲结点(这是第一次top父亲结点),然后找到父亲结点的右子树进行访问,当把右子树访问完成后,再通过栈找到父亲结点进行访问(这是第二次top父亲结点A)。那么怎么才知道这时是第一次top和第二次top呢?如果不做处理的话这里就会一直认为是第一次top父亲节点,不出栈,就会造成死循环,所以怎样解决呢?
这里创建一个prev结点,用来记录上一次出栈的结点,若上一次出栈的结点为右子树,这说明可以访问根结点了,说明是已经第二次top父亲结点
void PostOrderTraverse(BiTree T)
{Stack* S;BiTree p = T;InitStack(&S);BiTree prev = NULL;while (p || !StackEmpty(S)){while (p){push(S, p);p = p->lchild;}BiTree q;if (GetTop(S, &q) && (q->rchild == NULL || q->rchild == prev)){printf("%c ", q->data);prev = q;//更新q结点pop(S, &p);p = NULL;}else if (q->rchild != NULL){p = q->rchild;}}free(S);
}
相关文章:

二叉树的递归遍历和非递归遍历
目录 一.二叉树的递归遍历 1.先序遍历二叉树 2.中序遍历二叉树 3.后序遍历二叉树 二.非递归遍历(栈) 1.先序遍历 2.中序遍历 3.后序遍历 一.二叉树的递归遍历 定义二叉树 #其中TElemType可以是int或者是char,根据要求自定 typedef struct BiNode{TElemType data;stru…...

JDK17:未来已来,你准备好了吗?
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...
K8s和Docker
Kubernetes(简称为K8s)和Docker是两个相关但又不同的技术。 一、Docker 1、Docker是一种容器化平台,用于将应用程序及其依赖项打包成可移植的容器。 2、Docker容器可以在任何支持Docker的操作系统上运行 好处:提供了一种轻量级…...
使用物理机服务器应该注意的事项
使用物理机服务器应该注意的事项 如今云计算的发展已经遍布各大领域,尽管现在的云服务器火遍全网,但是仍有一些大型企业依旧选择使用独立物理服务器,你知道这是为什么吗?壹基比小鑫来告诉你吧。 独立物理服务器托管业务适合大中…...

py脚本解决ArcGIS Server服务内存过大的问题
在一台服务器上,使用ArcGIS Server发布地图服务,但是地图服务较多,在发布之后,服务器的内存持续处在95%上下的高位状态,导致服务器运行状态不稳定,经常需要重新启动。重新启动后重新进入这种内存高位的陷阱…...
Go语言Web开发入门指南
Go语言Web开发入门指南 欢迎来到Go语言的Web开发入门指南。Go语言因其出色的性能和并发支持而成为Web开发的热门选择。在本篇文章中,我们将介绍如何使用Go语言构建简单的Web应用程序,包括路由、模板、数据库连接和静态文件服务。 准备工作 在开始之前…...

保姆级教程——VSCode如何在Mac上配置C++的运行环境
vscode官方下载: 点击官网链接,下载对应的pkg,安装打开; https://code.visualstudio.com/插件安装 点击箭头所指插件商店按钮,yyds; 下载C/C 插件; 
Qt开发_调用OpenCV(3.4.7)设计完成人脸检测系统
一、前言 近年来,人脸识别技术得到了广泛的应用,它可以在各种场景中实现自动化的人脸检测和识别,例如安防监控、人脸解锁、人脸支付等。 该项目的目标是设计一个简单易用但功能强大的人脸检测系统,可以实时从摄像头采集视频,并对视频中的人脸进行准确的检测和框选。通过…...
Java 中 List 删除元素
fori循环 删除某个元素后,list的大小发生了变化,会导致遍历准确。 这种方式可以用在删除特定的一个元素时使用,但不适合循环删除多个元素时使用 增强for循环 删除元素后继续循环会报错误信息ConcurrentModificationException,但是…...

Redis:StringRedisTemplate简介
(笔记总结自b站黑马程序员课程) 为了在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入json结果中,存入Redis,会带来额外的内存开销。 为了减少内存的消耗,我们可以采用手动序列化的方式&am…...

pytorch-神经网络-手写数字分类任务
Mnist分类任务: 网络基本构建与训练方法,常用函数解析 torch.nn.functional模块 nn.Module模块 读取Mnist数据集 会自动进行下载 %matplotlib inlinefrom pathlib import Path import requestsDATA_PATH Path("data") PATH DATA_PATH / &…...

【群智能算法改进】一种改进的鹈鹕优化算法 IPOA算法[1]【Matlab代码#57】
文章目录 【获取资源请见文章第5节:资源获取】1. 原始POA算法2. 改进后的IPOA算法2.1 Sine映射种群初始化2.2 融合改进的正余弦策略2.3 Levy飞行策略 3. 部分代码展示4. 仿真结果展示5. 资源获取 【获取资源请见文章第5节:资源获取】 1. 原始POA算法 此…...

C++初阶:C++入门
目录 一.iostream文件 二.命名空间 2.1.命名空间的定义 2.2.命名空间的使用 三.C的输入输出 四.缺省参数 4.1.缺省参数概念 4.2.缺省参数分类 4.3.缺省参数注意事项 4.4.缺省参数用途 五.函数重载 5.1.重载函数概念 5.2.C支持函数重载的原理--名字修饰(name Mangl…...
golang操作数据库--gorm框架、redis
目录 1.数据库相关操作(1)非orm框架①引入②初始化③增删改查 (2) io版orm框架 (推荐用这个)①引入②初始化③增删改查④gorm gen的使用 (3) jinzhu版orm框架①引入②初始化③增删改查 2.redis(1)引入(2)初始化①普通初始化②v8初始化③get/set示例 1.数据库相关操作 (1)非orm…...
10 种常用的字符串方法
10 种常用的字符串方法 1.concat() 字符串拼接 const str1 12345678;const str2 abcdefgh;const str3 -【】;‘;console.log(str1.concat(str2,str3))//12345678abcdefgh-【】;‘ 2.includes() 判断字符串中是否包含指定值,返回布尔值…...
CSDN每日一练 |『生命进化书』『订班服』『c++难题-大数加法』2023-09-06
CSDN每日一练 |『生命进化书』『订班服』『c++难题-大数加法』2023-09-06 一、题目名称:生命进化书二、题目名称:订班服三、题目名称:c++难题-大数加法一、题目名称:生命进化书 时间限制:1000ms内存限制:256M 题目描述: 小A有一本生命进化书,以一个树形结构记载了所有生…...

echarts饼图label自定义样式
生成的options {"tooltip": {"trigger": "item","axisPointer": {"type": "shadow"},"backgroundColor": "rgba(9, 24, 48, 0.5)","borderColor": "rgba(255,255,255,0.4)&q…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...

论文阅读:Matting by Generation
今天介绍一篇关于 matting 抠图的文章,抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法,已经有很多的工作和这个任务相关。这两年 diffusion 模型很火,大家又开始用 diffusion 模型做各种 CV 任务了&am…...

算术操作符与类型转换:从基础到精通
目录 前言:从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符:、-、*、/、% 赋值操作符:和复合赋值 单⽬操作符:、--、、- 前言:从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...