C++数据结构:二叉树的前序、中序、后序遍历的非递归实现

news2025/1/17 15:22:20

目录

一. 前序遍历的非递归实现

二. 中序遍历的非递归实现

三. 后序遍历的非递归实现


一. 前序遍历的非递归实现

我们知道,前序遍历的访问顺序为:根节点 -> 左子树 -> 右子树。如图1.1所示的二叉树,我们要通过非递归实现前序遍历,其思路与递归实现并没有太大差别,可将非递归前序遍历这个大问题拆分为两个小问题:

  • 访问左路节点
  • 访问左路节点的每个右子树(子问题)
图1.1  二叉树

为此,我们需要一个栈做辅助,同时将遍历访问的节点的数据存入一个vector数组中。对于每一颗子树,将其左路节点节点地址入栈并将节点中的数据存入vector中。当左路节点全部入栈之后,取栈顶节点地址,通过top()->right访问右子树,解决下一个子问题。在循环遍历的过程中,我们使用cur记录当前访问的节点的地址,如果cur不为nullptr或栈不为空,那么继续循环,否则遍历结束,终止循环。图1.2以1.1所示的二叉树为例,展示了二叉树前序遍历的非递归实现逻辑。

图1.1 二叉树前序遍历的非递归实现逻辑

代码段1:(二叉树前序遍历的非递归实现)

template<class T>
struct TreeNode   //二叉树节点
{
	struct TreeNode* _left;
	struct TreeNode* _right;
	T _val;

	TreeNode(const T& val)
		: _left(nullptr)
		, _right(nullptr)
		, _val(val)
	{ }
};

//二叉树前序遍历非递归实现函数
template<class T>
std::vector<T> PrevOrderNonRecursion(TreeNode<T>* root)
{
	std::vector<T> v;   //存储遍历访问的数据
	std::stack<TreeNode<T>*> st;   //存储遍历到的节点的地址

	TreeNode<T>* cur = root;

	while (cur || !st.empty())
	{
		//1.遍历访问左侧路径的节点
		while (cur)
		{
			st.push(cur);
			v.push_back(cur->_val);

			cur = cur->_left;
		}

		//2.获取栈顶节点,解决右子树子问题
		TreeNode<T>* top = st.top();
		st.pop();

		cur = top->_right;
	}

	return v;
}

二. 中序遍历的非递归实现

中序遍历的实现思路与前序遍历类似,主要区别在于:

  • 前序遍历是在遍历左树的时候访问节点,并经节点中的数据尾插到vector中。
  • 后续遍历是在从栈中删除的点时,将栈顶节点中的数据尾插到vector中。

这样就可以保证每次访问节点之前,保证当前被访问的节点的左子树为空或者左子树中的所有节点都已经被访问。

代码段2:(非递归实现中序遍历)

//二叉树中序遍历非递归实现函数
template<class T>
std::vector<T> InOrderNonRecursion(TreeNode<T>* root)
{
	std::vector<T> v;
	std::stack<TreeNode<T>*> st;

	TreeNode<T>* cur = root;

	while (cur || !st.empty())
	{
		//遍历左侧路径上的节点,依次入栈
		while (cur)
		{
			st.push(cur);
			cur = cur->_left;
		}

		//取出栈顶节点,然后访问,该节点的左子树要么为空,要么已被访问过了
		TreeNode<T>* top = st.top();
		st.pop();
		v.push_back(top->_val);

		//解决右子树子问题
		cur = top->_right;
	}

	return v;
}

三. 后序遍历的非递归实现

后序遍历的非递归实现也是依靠stack栈这一数据结构来实现的,与前序和中序遍历不同的是,后序遍历由于最后访问根节点,不能在栈顶拿出节点之后,直接访问节点数据存入vector,而是应当保证根节点的左子树和右子树中所有节点都被访问过后,在去访问这个根节点。

为了判断是否对某个栈顶节点进行访问,引入一个新变量prev,记录前一个被访问到的节点,若满足以下两种情况之一,则对该栈顶节点进行访问:

  1. 该节点的右子节点为nullptr。
  2. 该节点的右子节点与之前访问的节点prev相同。

如果不满足条件,那么先去访问栈顶节点的右子树,之后再访问这个栈顶节点。

代码段3:(后序遍历的非递归实现)

template<class T>
std::vector<T> PostOrderNonRecursion(TreeNode<T>* root)
{
	std::vector<T> v;
	std::stack<TreeNode<T>*> st;

	TreeNode<T>* cur = root;  //当前节点
	TreeNode<T>* prev = nullptr;  //前一个访问的节点

	while (cur || !st.empty())
	{
		//遍历左侧路径
		while (cur)
		{
			st.push(cur);
			cur = cur->_left;
		}

		TreeNode<T>* top = st.top();
		//如果栈顶节点的右子节点为空,或刚刚遍历的节点prev是右子节点,那么访问,否则不放问,去走右子树
		if (top->_right == nullptr || top->_right == prev)
		{
			//访问节点
			v.push_back(top->_val);
			st.pop();
			prev = top;
		}
		else
		{
			cur = top->_right;
		}
	}

	return v;
}

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

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

相关文章

车载网络 - Autosar网络管理 - 网络管理简介

一、什么是CAN网络管理及它的作用 现在的车辆是由大量的ECU节点组成的&#xff0c;为了能使各ECU能够正确并及时地进行CAN通信&#xff0c;需要有一套机制来统一协调总线上各节点的休眠唤醒&#xff0c;这套机制就是CAN网络管理&#xff08;NM&#xff09;。 网络管理的目的是保…

系统集成项目管理工程师 笔记(第四章:项目管理一般知识)

文章目录 4.1.2 项目目标 1764.1.3 项目的特点 1784.1.9 项目干系人 1894.1.11 事业环境因素 1924.1.12 组织过程资产 1924.2.3 组织结构 1944.2.4 PMO在组织结构中的作用 199PMO类型&#xff08;支持型、控制型、指令型&#xff09;项目经理和PMO的区别 4.4 典型的信息系统项目…

图片存储方案-七牛云存储

1.引语 在实际开发中&#xff0c;我们会有很多处理不同功能的服务器。例如&#xff1a; 应用服务器&#xff1a;负责部署我们的应用 数据库服务器&#xff1a;运行我们的数据库 文件服务器&#xff1a;负责存储用户上传文件的服务器 分服务器处理的目的是让服务器各司其职…

tail:查看日志命令工具

文章目录 1. Windows下tail查看日志命令工具下载、使用方法2. baretail【windows端替代tail的工具】3. Tail4win【windows端替代tail的工具】4. MobaXterm【windows端替代tail的工具】5. tail 命令介绍 1. Windows下tail查看日志命令工具下载、使用方法 tail工具下载 链接&am…

中文改写神器下载-中文改写神器

自动文章生成器 随着人工智能技术的快速发展&#xff0c;自动文章生成器已经成为了一个越来越流行的营销推广工具。这种工具可以根据您提供的关键词和主题&#xff0c;在几秒钟之内生成高质量的文章&#xff0c;为企业加快文章产出速度&#xff0c;提高品牌知名度提供了优秀的…

C语言CRC-16 MAXIM格式校验函数

C语言CRC-16 MAXIM格式校验函数 CRC-16校验产生2个字节长度的数据校验码&#xff0c;通过计算得到的校验码和获得的校验码比较&#xff0c;用于验证获得的数据的正确性。基本的CRC-16校验算法实现&#xff0c;参考&#xff1a; C语言标准CRC-16校验函数。 不同厂家通过对输入…

android studio APP工程的项目结构说明

目录 1.APP工程的项目结构图 2.功能说明 2.1app 2.2Gradle Scripts 1.APP工程的项目结构图 2.功能说明 该项目下两个分类&#xff1a;一个是app&#xff08;代表app模块&#xff09;;另一个是Gradle Scripts。 2.1app app下面有3个子目录&#xff0c;功能如下&#xff1a;…

代码随想录之动态规划(力扣题号)

62 不同路径 很简单的dp class Solution {public int uniquePaths(int m, int n) {//58-02int[][] dp new int[m][n];//初始化for(int i 0;i<m;i){dp[i][0] 1;}for(int i 0;i<n;i){dp[0][i] 1;}for(int i1;i<m;i){for(int j 1;j<n;j){dp[i][j] dp[i-1][j]d…

开发小程序需要多少钱

开发小程序是如今网络世界中的一项重要活动&#xff0c;越来越多的企业和个人开始意识到通过开发小程序来提高自己的品牌价值和商业利益。那么&#xff0c;开发小程序需要多少钱呢&#xff1f; 首先&#xff0c;我们需要明确几个概念&#xff1a;小程序开发的成本通常包括以下…

kubespray-offline 下载并离线部署 kubernetes 自定义版本

kubespray-offline v2.21.0-0 默认部署 kubernetes 版本为 v1.25.6 我们以自定义部署 kubernetes 版本 v1.24.10为例。 下载&#xff1a;https://github.com/tmurakam/kubespray-offline/releases/tag/v2.21.0-0 unzip v2.21.0-0.zip cd kubespray-offline-2.21.0-0在下载介…

网络性能定位

根据tcp协议进行分析 目录 一、SYN_RECV阶段 1.1 确定半连接队列是否有丢包&#xff1a; 1.2 确定全连接队列是否有丢包现象 二、close_wait 三、TIME_WAIT ​ 一、SYN_RECV阶段 内核在监听套接字的时候&#xff0c;在三次握手时&#xff0c;会创建两个队列&#xff0c;在…

求解:使用Antv x6引入插件出现‘ToolItem’问题

一、前言 救救孩子&#xff0c;被困扰一周多了。 二、问题概述 2023年发布了antV X6的2.*版本&#xff0c;发现使用过程中会出现很多错误。 首先&#xff0c;个人使用的框架是Vue3&#xff0c;感觉有可能会是兼容性问题&#xff0c;但是有一个同事的电脑上是可以正常运行的。…

【C语言】基础语法2:运算符和表达式

❤️‍&#x1f525;前情提要❤️‍&#x1f525;   欢迎来到C语言基本语法教程   在本专栏结束后会将所有内容整理成思维导图&#xff08;结束换链接&#xff09;并免费提供给大家学习&#xff0c;希望大家纠错指正。本专栏将以基础出发&#xff0c;在之后的教程中将会不断…

【历史上的今天】4 月 19 日:摩尔定律被提出;微软发布 Pocket PC;第一个 FORTRAN 程序开始运行

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2023 年 4 月 19 日&#xff0c;在 1918 年的今天&#xff0c;克利福德贝里&#xff08;Clifford Berry&#xff09;出生。他是世界上第一台电子数字计算设备 Atanasof…

springboot中记录链路日志traceId

一 相关概念 在分布式服务架构下&#xff0c;一个 Web 请求从网关流入&#xff0c;有可能会调用多个服务对请求进行处理&#xff0c;拿到最终结果。在这个过程中每个服务之间的通信又是单独的网络请求&#xff0c;无论请求流经的哪个服务除了故障或者处理过慢都会对前端造成影…

基于PCA和NSST算法联合实现红外与可见光图像融合的Matlab仿真(完整源码+35组数据集)

以下是一个使用PCA和NSST算法实现红外与可见光图像融合的Matlab仿真完整源码。源码中只需修改红外图像&#xff08;IR.bmp&#xff09;和可见光图像&#xff08;VI.bmp&#xff09;名字即可 文章目录 效果展示数据集展示步骤说明完整源码下载地址 效果展示 最终融合效果展示&am…

cifar-10数据集+ResNet50

CIFAR-10-ObjectRecognition 作为一个古老年代的数据集&#xff0c;用ResNet来练一下手也是不错的。 比赛链接&#xff1a;CIFAR-10 - Object Recognition in Images | Kaggle 1. 预设置处理 创建各类超参数&#xff0c;其中如果是在Kaggle上训练的话batch_size是可以达到40…

安全狗深度参与编写《数据安全产品与服务观察报告》发布!

4月11日&#xff0c;由中国通信标准化协会联合数据安全推进计划主办的《数据安全产品与服务观察报告》发布会在北京顺利开展。 作为国内云原生安全领导厂商&#xff0c;安全狗也参与了数据安全推进计划《数据安全产品与服务观察报告》撰写。 此次活动针对数据安全产业、技术、…

排序算法合集(1)

前言&#xff1a; 今天我们正式开始讲述算法中的排序。排序算法是我们十分重要的算法&#xff0c;为什么呢&#xff1f; 排序是在各种情况下都非常重要的&#xff0c;无论是在人类社会还是在计算机科学中。以下是一些排序的重要性&#xff1a; 数据分析&#xff1a;在数据分析…

多连接数据库管理Navicat Premium 中文

Navicat Premium 是一款强大的数据库管理工具&#xff0c;它支持多种关系型数据库&#xff0c;包括 MySQL、MariaDB、Oracle、SQL Server、PostgreSQL 等等。 以下是 Navicat Premium 的一些主要功能&#xff1a; 连接管理&#xff1a;可以在一个用户界面中同时连接到多个数据库…